protected function processDeprecated(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
    {
        $tokens = $phpcsFile->getTokens();
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
            if ($tokens[$tag]['content'] !== '@deprecated') {
                continue;
            }

            $content = $tokens[($tag + 2)]['content'];
            if (empty($content) === true || $tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) {
                $error = 'Deprecated type missing for @deprecated tag in function comment';
                $phpcsFile->addError($error, $tag, 'MissingDeprecatedType');
            } else {
                //ONGR Validate that return comment begins with capital letter and ends with full stop.
                if ($content !== null) {
                    $firstChar = $content{0};
                    if (preg_match('|\p{Lu}|u', $firstChar) === 0) {
                        $error = 'Deprecated comment must start with a capital letter';
                        $fix = $phpcsFile->addFixableError($error, ($tag + 2), 'DeprecatedCommentNotCapital');

                        if ($fix === true) {
                            $newComment = ucfirst($content);
                            $tokenLength = strlen($tokens[($tag + 2)]['content']);
                            $commentLength = strlen($content);
                            $tokenWithoutComment
                                = substr($tokens[($tag + 2)]['content'], 0, $tokenLength - $commentLength);

                            $phpcsFile->fixer->replaceToken(($tag + 2), $tokenWithoutComment . $newComment);
                        }
                    }

                    $lastChar = substr($content, -1);
                    if ($lastChar !== '.') {
                        $error = 'Deprecated comment must end with a full stop';
                        $fix = $phpcsFile->addFixableError($error, ($tag + 2), 'DeprecatedCommentFullStop');

                        if ($fix === true) {
                            $phpcsFile->fixer->addContent(($tag + 2), '.');
                        }
                    }
                }
            }
        }
    }

Process any deprecated tags that this function comment has.

@param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
@param int                  $stackPtr     The position of the current token
in the stack passed in $tokens.
@param int                  $commentStart The position in the stack where the comment started.

@return void

Process any deprecated tags that this function comment has .


public static function start(): void     // TODO - not this.
    {
        ini_set('display_errors', 1);
        ini_set('track_errors', 1);
        error_reporting(self::$level);

        if (TEST) {
            return;
        }

        /**
         * if you return true from here it will continue script execution from the point of the error..
         * this is not wanted. Die and Exit are equivalent in execution. I ran across a post once that
         * explained how die should signify a complete error with no resolution, while exit has resolution
         * returning 1 rather than 0 in both cases will signify an error occurred
         * @param array $argv
         * @internal param TYPE_NAME $closure
         */
        $closure = function (...$argv) {
            static $count;

            if (empty($count)) {
                $count = 0;
            }
            $count++;

            self::generateLog($argv);

            if (!SOCKET && !APP_LOCAL && CarbonPHP::$setupComplete) {     // TODO - do we really want to reset?
                if ($count > 1) {
                    print 'A recursive error has occurred in (or at least affecting) your $app->defaultRoute();';
                    die(1);
                }
                startApplication(true);
                exit(1);
            }

            /** @noinspection ForgottenDebugOutputInspection
             * TODO - fix this? */
            print_r($argv);
            print "\n\nCarbonPHP Caught This Error.\n\n";
            die(1);

        };
        set_error_handler($closure);
        set_exception_handler($closure);
    }


public static function generateLog($e = null, string $level = 'log'): string
    {
        if (ob_get_status()) {
            // Attempt to remove any previous in-progress output buffers
            ob_end_clean();
        }

        ob_start(null, null, PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_FLUSHABLE | PHP_OUTPUT_HANDLER_REMOVABLE);     // start a new buffer for saving errors

        if ($e instanceof \Throwable) {
            $trace = self::generateCallTrace($e);
            if (!$e instanceof PublicAlert) {
                print '(set_error_handler || set_exception_handler) caught this error. #Bubbled up#' . PHP_EOL;
            } else {
                print 'Public Alert Thrown!' . PHP_EOL;
            }
            print PHP_EOL . $e->getMessage() . PHP_EOL;

        } else {
            $trace = self::generateCallTrace();

            if (\is_array($e) && \count($e) >= 4) {
                print PHP_EOL . 'Carbon caught this Message: ' . $e[1] . PHP_EOL . 'line: ' . $e[2] . '(' . $e[3] . ')' . PHP_EOL;
            }
        }

        print PHP_EOL . $trace . PHP_EOL;

        $output = ob_get_contents();

        ob_end_clean();

        /** @noinspection ForgottenDebugOutputInspection */
        error_log($output);

        if (self::$printToScreen) {
            print "
You have the print to screen Error Catching option turned on!

 Turn it off to suppress this reporting.

$output
";
        }

        if (self::$storeReport === true || self::$storeReport === 'file') {       // TODO - store to file?
            if (!is_dir(REPORTS) && !mkdir($concurrentDirectory = REPORTS) && !is_dir($concurrentDirectory)) {
                PublicAlert::danger('Failed Storing Log');
            } else {
                $file = fopen(REPORTS . '/Log_' . time() . '.log', 'ab');

                if (!\is_resource($file) || !fwrite($file, $output)) {
                    PublicAlert::danger('Failed Storing Log');
                }
                fclose($file);
            }
        }

        if (self::$storeReport === true || self::$storeReport === 'database') {       // TODO - store to file?
            $sql = 'INSERT INTO carbon_reports (log_level, report, call_trace) VALUES (?, ?, ?)';
            $sql = Database::database()->prepare($sql);
            if (!$sql->execute([$level, $output, $trace])) {
                print 'Failed to store error log, nothing works... Why does nothing work?' and die(1);
            }
        }

        return $output;
    }

Generate a full error log consisting of a
@param \Throwable|array|null $e
@param string $level
@return string
@internal param $argv


public static function generateCallTrace(\Throwable $e = null): string
    {
        ob_start();
        if (null === $e) {
            $e = new \Exception();
            $trace = explode("\n", $e->getTraceAsString());
            $args = array_reverse($e->getTrace());
            $trace = array_reverse($trace);
            array_shift($trace); // remove {main}
            array_pop($args); // remove call to this method
            array_pop($args); // remove call to this method
            array_pop($trace); // remove call to this method
            array_pop($trace); // remove call to this method
        } else {
            $trace = explode("\n", $e->getTraceAsString());
            $args = array_reverse($e->getTrace());
            $trace = array_reverse($trace);
            array_shift($trace); // remove {main}
        }

        $length = \count($trace);
        $result = array();
        for ($i = 0; $i < $length; $i++) {
            $result[] = ($i + 1) . ') ' . implode(' (', explode('(', substr($trace[$i], strpos($trace[$i], ' ')))) . PHP_EOL . "\t\t\t\t" . json_encode($args[$i]['args']) . PHP_EOL;
        }
        print "\n\t" . implode("\n\t", $result);

        $output = ob_get_contents();
        ob_end_clean();
        return $output;
    }

public
static
function
generateCallTrace
(
\
Throwable
$
e
=
)
:
string
{
ob_start
(
)
;
if
(
===
$
e
)
{
$
e
=
new
\
Exception
(
)
;
$
trace
=
explode
(
"\n"
,
$
e
->
getTraceAsString
(
)
)
;
$
args
=
array_reverse
(
$
e
->
getTrace
(
)
)
;
$
trace
=
array_reverse
(
$
trace
)
;
array_shift
(
$
trace
)
;
// remove {main}
array_pop
(
$
args
)
;
// remove call to this method
array_pop
(
$
args
)
;
// remove call to this method
array_pop
(
$
trace
)
;
// remove call to this method
array_pop
(
$
trace
)
;
// remove call to this method
}
else
{
$
trace
=
explode
(
"\n"
,
$
e
->
getTraceAsString
(
)
)
;
$
args
=
array_reverse
(
$
e
->
getTrace
(
)
)
;
$
trace
=
array_reverse
(
$
trace
)
;
array_shift
(
$
trace
)
;
// remove {main}
}
$
length
=
\
count
(
$
trace
)
;
$
result
=
array
(
)
;
for
(
$
i
=
0
;
$
i
<
$
length
;
$
i
++
)
{
$
result
[
]
=
(
$
i
+
1
)
.
') '
.
implode
(
' ('
,
explode
(
'('
,
substr
(
$
trace
[
$
i
]
,
strpos
(
$
trace
[
$
i
]
,
' '
)
)
)
)
.
PHP_EOL
.
"\t\t\t\t"
.
json_encode
(
$
args
[
$
i
]
[
'args'
]
)
.
PHP_EOL
;
}
print
"\n\t"
.
implode
(
"\n\t"
,
$
result
)
;
$
output
=
ob_get_contents
(
)
;
ob_end_clean
(
)
;
return
$
output
;
}

A simplified back trace for quickly identifying route.
reverse array to make steps line up chronologically
@link http://php.net/manual/en/function.debug-backtrace.php
@param \Throwable $e
@return string

A simplified back trace for quickly identifying route . reverse array to make steps line up chronologically


private static function alert(string $message, string $code) {
        global $json;
        if ($code !== 'success' && $code !== 'info') {
            $message .= ' Contact us if problem persists.';
        }
        $json['alert'][$code][] = $message;
    }

private
static
function
alert
(
string
$
message
,
string
$
code
)
{
global
$
json
;
if
(
$
code
!==
'success'
&&
$
code
!==
'info'
)
{
$
message
.=
' Contact us if problem persists.'
;
}
$
json
[
'alert'
]
[
$
code
]
[
]
=
$
message
;
}

Add an alert to the array. If the view is not executed, CarbonPHP will not
handle the global alert.
@param string $message the message to be stored in the alert variable
@param string $code you may choose between success, info, danger, or warning

Add an alert to the array . If the view is not executed CarbonPHP will not handle the global alert .


public static function become_daemon(callable $call = null) : int        // do not use this unless you know what you are doing
    {
        if (!\extension_loaded('pcntl')) {
            print 'You must have the PCNTL extencion installed. See Carbon PHP for documentation.' and die;
        }

        if ($pid = pcntl_fork()) {  // Parent
            if (\is_callable($call)) {
                return 1;
            }
            exit;
        }
        if ($pid < 0) {
            throw new \RuntimeException('Failed to fork');
        }

        \define('FORK', TRUE);

        /* child becomes our daemon */
        posix_setsid();

        chdir('/');   // What does this do ?

        umask(0);        // Give access to nothing

        register_shutdown_function(function () {
            session_abort();
            posix_kill(posix_getpid(), SIGHUP);
            exit(1);
        });

        if (\is_callable($call)) {
            $call();
            exit(1);
        }

        return posix_getpid();
    }

If a callable function is passes the interpreter will attempt to
fork using the pncl library and then execute the desired closure.
If no arguments are passed than the current execution environment
will become "Demonized". All masks will be set to 0 and the new
working environment will be the root dir. This can be exceptionally
dangerous and should only be used if your absolutely
sure you know whats going on.
@param callable|null $call
@return int
@throws \Exception

If a callable function is passes the interpreter will attempt to fork using the pncl library and then execute the desired closure . If no arguments are passed than the current execution environment will become Demonized . All masks will be set to 0 and the new working environment will be the root dir . This can be exceptionally dangerous and should only be used if your absolutely sure you know whats going on .


public static function safe(callable $closure = null) : int
    {
        if (!\extension_loaded('pcntl')) {
            if ($closure !== null) {
                $closure();
            }
            return 0;
        }
        if ($pid = pcntl_fork()) {    // return child id for parent and 0 for child
            return $pid;             // Parent
        }
        if ($pid < 0) {
            throw new \RuntimeException('Failed to fork');
        }
        \define('FORK', true);
        // Database::resetConnection();
        // fclose(STDIN); -- unset
        register_shutdown_function(function () {
            session_abort();
            posix_kill(posix_getpid(), SIGHUP);
            exit(1);
        });

        if ($closure !== null) {
            $closure();
        }
        exit;
    }

This will safely execute a passed closure if the pncl library in not
found in the environment. This should only be used when the callable
function does not access or modify the database or session. Carbon uses
this when realtime communication using named pipe is requested. It only
speeds up execution, however it is not required and will never throw an
error.
@param callable|null $closure
@return int
@throws \Exception

This will safely execute a passed closure if the pncl library in not found in the environment . This should only be used when the callable function does not access or modify the database or session . Carbon uses this when realtime communication using named pipe is requested . It only speeds up execution however it is not required and will never throw an error .


public function getSlug($forceRegeneration = false)
    {
        $owner = $this->getOwner();
        $field = $this->fieldToSlug;
        $unfilteredSlug = $owner->URLSlug;
        if (!$unfilteredSlug || $forceRegeneration) {
            $unfilteredSlug = $owner->$field;
        }
        return URLSegmentFilter::create()->filter($unfilteredSlug);
    }

public function getSlug ( $ forceRegeneration = false ) { $ owner = $ this -> getOwner ( ) ; $ field = $ this -> fieldToSlug ; $ unfilteredSlug = $ owner -> URLSlug ; if ( ! $ unfilteredSlug || $ forceRegeneration ) { $ unfilteredSlug = $ owner -> $ field ; } return URLSegmentFilter :: create ( ) -> filter ( $ unfilteredSlug ) ; }

Generate a url slug segment

@param  boolean $forceRegeneration
@return string


public function onBeforeWrite()
    {
        $owner = $this->getOwner();
        $slugHasChanged = $owner->isChanged('URLSlug');
        $fieldToSlugHasChanged = $owner->isChanged($this->fieldToSlug);
        $updateSlug = (
            empty($owner->URLSlug)
            || ($this->enforceParity && $fieldToSlugHasChanged)
            || (!$this->enforceParity && $slugHasChanged)
        );

        if ($updateSlug) {
            $owner->URLSlug = $this->getSlug($this->enforceParity);

            $collisionList = DataObject::get(get_class($owner))->exclude('ID', $owner->ID);
            $filter = ['URLSlug' => $owner->URLSlug];
            if ($this->relationName) {
                $parentIDField = $this->relationName . 'ID';
                $filter[$parentIDField] = $owner->$parentIDField;
                // Also handle polymorphic relationships
                $parentClassName = DataObject::getSchema()->hasOneComponent(get_class($owner), $this->relationName);
                if ($parentClassName === DataObject::class) {
                    $parentClassField = $this->relationName . 'Class';
                    $filter[$parentClassField] = $owner->$parentClassField;
                }
            }

            $count = 1;
            while ($collisionList->filter($filter)->exists()) {
                $owner->URLSlug = $owner->URLSlug . $count++;
                $filter['URLSlug'] = $owner->URLSlug;
            }
        } elseif ($slugHasChanged) {
            // enforceParity is set, and the slug has changed... but the
            // field to slug has not. We need to reset to keep parity.
            // Ideally we could do this via the $original property through
            // {@see DataObject::getChangedFields}, however the returned
            // 'before' value for a changed field is unreliable :(
            // https://github.com/silverstripe/silverstripe-framework/issues/8443
            throw new UnexpectedValueException(
                'URLSlug has been updated independently of the tracked field, ' .
                'but this has been disabled via Slug::enforceParity'
            );
        }
    }

Check for collisions, iff we need to update the slug and
upate the model with the confirmedsafe value before writing

Check for collisions iff we need to update the slug and upate the model with the confirmedsafe value before writing


public static function sendHeaders(): void
    {
        if (!(SOCKET || headers_sent())) {
            if (isset($_SESSION['Cookies']) && \is_array($_SESSION['Cookies'])) {
                foreach ($_SESSION['Cookies'] as $key => $array) {
                    if ($array[1] ?? false) {
                        static::setCookie($key, $array[0] ?? null, $array[1]);
                    } else {
                        static::setCookie($key, $array[0] ?? null);
                    }
                }
            }

            if (isset($_SESSION['Headers']) && \is_array($_SESSION['Headers'])) {
                foreach ($_SESSION['Headers'] as $value) {
                    static::setHeader($value);
                }
            }
            unset($_SESSION['Cookies'], $_SESSION['Headers']);
        }
    }

public static function sendHeaders ( ) : void { if ( ! ( SOCKET || headers_sent ( ) ) ) { if ( isset ( $ _SESSION [ 'Cookies' ] ) && \ is_array ( $ _SESSION [ 'Cookies' ] ) ) { foreach ( $ _SESSION [ 'Cookies' ] as $ key => $ array ) { if ( $ array [ 1 ] ?? false ) { static :: setCookie ( $ key , $ array [ 0 ] ?? null , $ array [ 1 ] ) ; } else { static :: setCookie ( $ key , $ array [ 0 ] ?? null ) ; } } } if ( isset ( $ _SESSION [ 'Headers' ] ) && \ is_array ( $ _SESSION [ 'Headers' ] ) ) { foreach ( $ _SESSION [ 'Headers' ] as $ value ) { static :: setHeader ( $ value ) ; } } unset ( $ _SESSION [ 'Cookies' ] , $ _SESSION [ 'Headers' ] ) ; } }

Headers can only be sent and set if output has not already started.
If we attempt to set a header after output has started, store it and
send on the next request.
@return void

Headers can only be sent and set if output has not already started . If we attempt to set a header after output has started store it and send on the next request .


public static function setCookie(string $key, $value = null, int $time = 604800): void // Week?
    {
        if (headers_sent()) {
            $_SESSION['Cookies'][] = [$key => [$value, $time]];
        } else {
            setcookie($key, $value, time() + $time, '/', SITE, HTTPS, true);
        }
    }

public
static
function
setCookie
(
string
$
key
,
$
value
=
,
int
$
time
=
604800
)
:
void
// Week?
{
if
(
headers_sent
(
)
)
{
$
_SESSION
[
'Cookies'
]
[
]
=
[
$
key
=>
[
$
value
,
$
time
]
]
;
}
else
{
setcookie
(
$
key
,
$
value
,
time
(
)
+
$
time
,
'/'
,
SITE
,
HTTPS
,
true
)
;
}
}

Cookies are a pain to set up as they also rely on headers not being sent.
This method makes setting cookies easy with three params.
@param string $key the name of the cookie
@param mixed $value
@param int $time the expiration time of our cookie

Cookies are a pain to set up as they also rely on headers not being sent . This method makes setting cookies easy with three params .


public function clearCookies(): void
    {
        $all = array_keys(\is_array($_COOKIE) ? $_COOKIE : []);
        foreach ($all as $key => $value) {
            static::setCookie($value);
        }
    }

public function clearCookies ( ) : void { $ all = array_keys ( \ is_array ( $ _COOKIE ) ? $ _COOKIE : [ ] ) ; foreach ( $ all as $ key => $ value ) { static :: setCookie ( $ value ) ; } }

Clear all active cookies in the current session


private function request(array $argv, array &$array, bool $removeHTML = false): self
    {
        $this->storage = null;
        $closure = function ($key) use ($removeHTML, &$array) {
            if (array_key_exists($key, $array)) {
                $this->storage[] = $removeHTML ? htmlspecialchars($array[$key]) : $array[$key];
                $array[$key] = null;    // by reference, if we validate it then we should ensure no one uses it
            } else {
                $this->storage[] = false;
            }
        };
        if (\count($argv) === 0 || !array_walk($argv, $closure)) {
            $this->storage = [];
        }
        return $this;
    }

Request is a blanket method for other data validation procedures.
@param array $argv values should match the keys in the given set
@param array $array usually a transfer protocol ($_POST, $_GET, $_COOKIE)
@param bool $removeHTML if true htmlspecialchars() will be run on each member of the set
@link http://php.net/manual/en/function.htmlspecialchars.php
@return Request

Request is a blanket method for other data validation procedures .


public function storeFiles(string $location = 'Data/Uploads/Temp/')
    {
        $storagePath = array();
        return $this->closure_array_walk(function ($file) use ($location, &$storagePath) {
            $storagePath[] = Files::uploadFile($file, $location);
        })($storagePath);
    }

public function storeFiles ( string $ location = 'Data/Uploads/Temp/' ) { $ storagePath = array ( ) ; return $ this -> closure_array_walk ( function ( $ file ) use ( $ location , & $ storagePath ) { $ storagePath [ ] = Files :: uploadFile ( $ file , $ location ) ; } ) ( $ storagePath ) ; }

storeFiles attempts to store files currently in the storage set
@param string $location the location to store the files
@return array|mixed
@throws PublicAlert if the files fail to be stored


public function except(...$argv): self
    {
        array_walk($argv, function ($key) {
            if (array_key_exists($key, $this->storage)) {
                unset($this->storage[$key]);
            }
        });
        return $this;
    }

public function except ( ... $ argv ) : self { array_walk ( $ argv , function ( $ key ) { if ( array_key_exists ( $ key , $ this -> storage ) ) { unset ( $ this -> storage [ $ key ] ) ; } } ) ; return $ this ; }

Removes passed arguments from the set
@param array ...$argv
@return Request


public function regex(string $condition)
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use ($condition, &$array) {
            return $array[] = (preg_match($condition, $key) ? $key : false);
        })($array);
    }

public function regex ( string $ condition ) { $ array = [ ] ; return $ this -> closure_array_walk ( function ( $ key ) use ( $ condition , & $ array ) { return $ array [ ] = ( preg_match ( $ condition , $ key ) ? $ key : false ) ; } ) ( $ array ) ; }

Preforms a regex expression using preg_match on each member of the set
@link http://php.net/manual/en/function.preg-match.php
@param string $condition
@return array|bool|mixed


public function noHTML($complete = false)
    {   // Disallow: $, ", ', <, >
        $array = [];
        $fn = $this->closure_array_walk(function ($key) use (&$array) {
            return $array[] = htmlspecialchars($key);
        });

        if ($complete) {
            return $fn($array);
        }

        return $this;
    }

public
function
noHTML
(
$
complete
=
false
)
{
// Disallow: $, ", ', <, >
$
array
=
[
]
;
$
fn
=
$
this
->
closure_array_walk
(
function
(
$
key
)
use
(
&
$
array
)
{
return
$
array
[
]
=
htmlspecialchars
(
$
key
)
;
}
)
;
if
(
$
complete
)
{
return
$
fn
(
$
array
)
;
}
return
$
this
;
}

Removes HTML chars from a given set
@param bool $complete if set to true than $this
will be returned
@return array|bool|Request|mixed


public function int(int $min = null, int $max = null)   // inclusive max and min
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array, $min, $max) {
            if (($key = (int)$key) === false) {
                return $array[] = false;
            }
            if ($max !== null) {
                $key = ($key <= $max ? $key : false);
            }
            if ($min !== null) {
                $key = ($key >= $min ? $key : false);
            }
            return $array[] = $key;
        })($array);
    }

public
function
int
(
int
$
min
=
,
int
$
max
=
)
// inclusive max and min
{
$
array
=
[
]
;
return
$
this
->
closure_array_walk
(
function
(
$
key
)
use
(
&
$
array
,
$
min
,
$
max
)
{
if
(
(
$
key
=
(
int
)
$
key
)
===
false
)
{
return
$
array
[
]
=
false
;
}
if
(
$
max
!==
)
{
$
key
=
(
$
key
<=
$
max
$
key
:
false
)
;
}
if
(
$
min
!==
)
{
$
key
=
(
$
key
>=
$
min
$
key
:
false
)
;
}
return
$
array
[
]
=
$
key
;
}
)
(
$
array
)
;
}

Returns found integers between the given min and max if set. If no max
or min is set, just validate integers.
@param int|null $min
@param int|null $max
@return array|bool|mixed

Returns found integers between the given min and max if set . If no max or min is set just validate integers .


public static function flush()
    {
        if (!self::$already_flushed && file_exists(self::getCacheDir())) {
            $paths = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator(self::getCacheDir(), FilesystemIterator::SKIP_DOTS),
                RecursiveIteratorIterator::CHILD_FIRST
            );
            foreach ($paths as $path) {
                $path->isDir() && !$path->isLink() ? rmdir($path->getPathname()) : unlink($path->getPathname());
            }
            // make sure we only flush once per request and not for each *.less
            self::$already_flushed = true;
        }
    }

Triggered early in the request when a flush is requested
Deletes the less.php cache folder and regenerates

Triggered early in the request when a flush is requested Deletes the less . php cache folder and regenerates


public function combineFiles($combinedFileName, $files, $options = array())
    {
        $new_files = [];

        foreach ($files as $file) {
            $new_files[] = $this->processLessFile($file);
        }

        return parent::combineFiles($combinedFileName, $new_files, $options);
    }

public function combineFiles ( $ combinedFileName , $ files , $ options = array ( ) ) { $ new_files = [ ] ; foreach ( $ files as $ file ) { $ new_files [ ] = $ this -> processLessFile ( $ file ) ; } return parent :: combineFiles ( $ combinedFileName , $ new_files , $ options ) ; }

Process any less files and return new filenames
@See Requirements_Backend->combineFiles() for options


protected function connect(ServerInterface $server)
    {
        if (false === function_exists('ssh2_connect')) {
            throw new \RuntimeException('The "ssh2_connect" function does not exist.');
        }

        $con = ssh2_connect($server->getHost(), $server->getPort());

        if (false === $con) {
            throw new SshException(sprintf('Cannot connect to server "%s"', $server->getHost()));
        }

        if (false === ssh2_auth_password($con, $server->getUser(), $server->getPassword())) {
            throw new SshException(sprintf('Authorization failed for user "%s"', $server->getUser()));
        }

        $this->con = $con;
    }

Open the SSH connection

@param Plum\Server\ServerInterface $server


protected function exec($cmd)
    {
        if (false === $stream = ssh2_exec($this->con, $cmd)) {
            throw new SshException(sprintf('"%s" : SSH command failed', $cmd));
        }

        stream_set_blocking($stream, true);

        $data = '';
        while ($buf = fread($stream, 4096)) {
            $data .= $buf;
        }

        fclose($stream);

        return $data;
    }

protected
function
exec
(
$
cmd
)
{
if
(
false
===
$
stream
=
ssh2_exec
(
$
this
->
con
,
$
cmd
)
)
{
throw
new
SshException
(
sprintf
(
'"%s" : SSH command failed'
,
$
cmd
)
)
;
}
stream_set_blocking
(
$
stream
,
true
)
;
$
data
=
''
;
while
(
$
buf
=
fread
(
$
stream
,
4096
)
)
{
$
data
.=
$
buf
;
}
fclose
(
$
stream
)
;
return
$
data
;
}

Execute a SSH command

@param string $cmd The SSH command

@return string The output


private function isClientServer()
    {
        if (PHP_SAPI === 'cli-server' || PHP_SAPI === 'cli' || \in_array($_SERVER['REMOTE_ADDR'] ?? [], ['127.0.0.1', 'fe80::1', '::1'], false)) {
            if (SOCKET && $ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                \define('IP', $ip);
                return false;
            }
            \define('IP', '127.0.0.1');
            return IP;
        }
        return false;
    }

private function isClientServer ( ) { if ( PHP_SAPI === 'cli-server' || PHP_SAPI === 'cli' || \ in_array ( $ _SERVER [ 'REMOTE_ADDR' ] ?? [ ] , [ '127.0.0.1' , 'fe80::1' , '::1' ] , false ) ) { if ( SOCKET && $ ip = filter_var ( $ _SERVER [ 'REMOTE_ADDR' ] , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) { \ define ( 'IP' , $ ip ) ; return false ; } \ define ( 'IP' , '127.0.0.1' ) ; return IP ; } return false ; }

returns 127.0.0.1 if you are using a local development server,
otherwise returns false.
@return bool|mixed|string

returns 127 . 0 . 0 . 1 if you are using a local development server otherwise returns false .


private function IP_FILTER()
    {
        $ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
        foreach ($ip_keys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    // trim for safety measures
                    $ip = trim($ip);
                    if ($ip = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                        \define('IP', $ip);
                        return IP;
                    }
                }
            }
        }   // TODO - log invalid ip addresses
        print 'Could not establish an IP address.';
        die(1);
    }

private
function
IP_FILTER
(
)
{
$
ip_keys
=
array
(
'HTTP_CLIENT_IP'
,
'HTTP_X_FORWARDED_FOR'
,
'HTTP_X_FORWARDED'
,
'HTTP_X_CLUSTER_CLIENT_IP'
,
'HTTP_FORWARDED_FOR'
,
'HTTP_FORWARDED'
,
'REMOTE_ADDR'
)
;
foreach
(
$
ip_keys
as
$
key
)
{
if
(
array_key_exists
(
$
key
,
$
_SERVER
)
===
true
)
{
foreach
(
explode
(
','
,
$
_SERVER
[
$
key
]
)
as
$
ip
)
{
// trim for safety measures
$
ip
=
trim
(
$
ip
)
;
if
(
$
ip
=
filter_var
(
$
ip
,
FILTER_VALIDATE_IP
,
FILTER_FLAG_IPV4
|
FILTER_FLAG_NO_PRIV_RANGE
|
FILTER_FLAG_NO_RES_RANGE
)
)
{
\
define
(
'IP'
,
$
ip
)
;
return
IP
;
}
}
}
}
// TODO - log invalid ip addresses
print
'Could not establish an IP address.'
;
die
(
1
)
;
}

This function uses common keys for obtaining the users real IP.
We use this for verbo se operating systems support.
@link http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/
@return mixed|string

This function uses common keys for obtaining the users real IP . We use this for verbo se operating systems support .


public static function named(string $fifoPath)  // Arbitrary)
    {

        if (file_exists($fifoPath)) {
            unlink($fifoPath);          // We are always the master, hopefully we'll catch the kill this time
        }

        umask(0000);

        if (!posix_mkfifo($fifoPath, 0666)) {
            print 'Failed to create named Pipe' . PHP_EOL;
            return false;
        }                   # create a named pipe 0644

        #$user = get_current_user();                            // get current process user

        #exec("chown -R {$user} $fifoPath");                    // We need to modify the permissions so users can write to it

        $fifoFile = fopen($fifoPath, 'rb+');              // Now we open the named pipe we Already created

        stream_set_blocking($fifoFile, false);           // setting to true (resource heavy) activates the handshake feature, aka timeout

        return $fifoFile;                                       // File descriptor
    }

This will open a named pipe on our server. This is used for sending
information between two active processes on the server. Generally,
each user can send data real time to each other using this method.
Keep in mind that the fifo file must be unique to the users listening
on it.
@param string $fifoPath is the location of the fifo file.
@return bool|resource

This will open a named pipe on our server . This is used for sending information between two active processes on the server . Generally each user can send data real time to each other using this method . Keep in mind that the fifo file must be unique to the users listening on it .


public function registerDeployer(DeployerInterface $deployer)
    {
        if (null !== $deployer) {
            $this->deployers[$deployer->getName()] = $deployer;
        }

        return $this;
    }

public function registerDeployer ( DeployerInterface $ deployer ) { if ( null !== $ deployer ) { $ this -> deployers [ $ deployer -> getName ( ) ] = $ deployer ; } return $ this ; }

Registers a deployer

@param DeployerInterface $deployer

@return \Plum\Plum


public function getDeployer($deployer)
    {
        if (false === isset($this->deployers[$deployer])) {
            throw new \InvalidArgumentException(sprintf('The deployer "%s" is not registered.', $deployer));
        }

        return $this->deployers[$deployer];
    }

public
function
getDeployer
(
$
deployer
)
{
if
(
false
===
isset
(
$
this
->
deployers
[
$
deployer
]
)
)
{
throw
new
\
InvalidArgumentException
(
sprintf
(
'The deployer "%s" is not registered.'
,
$
deployer
)
)
;
}
return
$
this
->
deployers
[
$
deployer
]
;
}

Returns a deployer

@param string $deployer The deployer name

@return \Plum\Deployer\DeployerInterface


public function addServer($name, ServerInterface $server)
    {
        if (null === $server) {
            throw new \InvalidArgumentException('The server can not be null.');
        }

        if (true === isset($this->servers[$name])) {
            throw new \InvalidArgumentException(sprintf('The server "%s" is already registered.', $name));
        }

        $this->servers[$name] = $server;

        return $this;
    }

Adds a server to the list

@param string $name
@param \Plum\Server\ServerInterface $server

@return \Plum\Plum


public function setServers(array $servers)
    {
        foreach ($servers as $name => $server) {
            $this->addServer($name, $server);
        }

        return $this;
    }

public function setServers ( array $ servers ) { foreach ( $ servers as $ name => $ server ) { $ this -> addServer ( $ name , $ server ) ; } return $ this ; }

Adds a list of servers

@param array $servers

@return \Plum\Plum


public function getServer($server)
    {
        if (!isset($this->servers[$server])) {
            throw new \InvalidArgumentException(sprintf('The server "%s" is not registered.', $server));
        }

        return $this->servers[$server];
    }

public
function
getServer
(
$
server
)
{
if
(
!
isset
(
$
this
->
servers
[
$
server
]
)
)
{
throw
new
\
InvalidArgumentException
(
sprintf
(
'The server "%s" is not registered.'
,
$
server
)
)
;
}
return
$
this
->
servers
[
$
server
]
;
}

Returns a server

@param type $server The server name

@return \Plum\Server\ServerInterface


public function deploy($server, $deployer)
    {
        $server   = $this->getServer($server);
        $deployer = $this->getDeployer($deployer);

        return $deployer->deploy($server, $this->options);
    }

public function deploy ( $ server , $ deployer ) { $ server = $ this -> getServer ( $ server ) ; $ deployer = $ this -> getDeployer ( $ deployer ) ; return $ deployer -> deploy ( $ server , $ this -> options ) ; }

Deploys to the server using the deployer

@param string $server   The name of the server
@param string $deployer The name of the deployer


public function getOptions($server = null)
    {
        if (null === $server) {
            return $this->options;
        }

        $server = $this->getServer($server);

        return array_merge($this->options, $server->getOptions());
    }

public function getOptions ( $ server = null ) { if ( null === $ server ) { return $ this -> options ; } $ server = $ this -> getServer ( $ server ) ; return array_merge ( $ this -> options , $ server -> getOptions ( ) ) ; }

Returns the array of options

@param string $server The server name


public function processOpen(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        parent::processOpen($phpcsFile, $stackPtr);

        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
            $prevContent = $tokens[($stackPtr - 1)]['content'];
            if ($prevContent !== $phpcsFile->eolChar) {
                $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
                $spaces     = strlen($blankSpace);

                if ($tokens[($stackPtr - 2)]['code'] !== T_ABSTRACT
                    && $tokens[($stackPtr - 2)]['code'] !== T_FINAL
                ) {
                    if ($spaces !== 0) {
                        $type  = strtolower($tokens[$stackPtr]['content']);
                        $error = 'Expected 0 spaces before %s keyword; %s found';
                        $data  = array(
                            $type,
                            $spaces,
                        );

                        $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data);
                        if ($fix === true) {
                            $phpcsFile->fixer->replaceToken(($stackPtr - 1), '');
                        }
                    }
                }
            }//end if
        }//end if
        //ONGR we do not allow blank line after an opening brace.
        $curlyBrace = $tokens[$stackPtr]['scope_opener'];
        $i = 1;
        while ($tokens[($curlyBrace + $i)]['code'] === T_WHITESPACE && $i < count($tokens)) {
            $i++;
        }
        $blankLineCount = ($tokens[($curlyBrace + $i)]['line'] - $tokens[$curlyBrace]['line']) - 1;
        if ($blankLineCount > 0) {
            $data = [$blankLineCount];
            $error = 'Expected no blank lines after an opening brace, %s found';
            $phpcsFile->addError($error, $curlyBrace, 'OpenBraceBlankLines', $data);
        }

    }

Processes the opening section of a class declaration.

@param PHP_CodeSniffer_File $phpcsFile The file being scanned.
@param int                  $stackPtr  The position of the current token
in the stack passed in $tokens.

@return void

Processes the opening section of a class declaration .


protected function ajax_slug( $action ) {
		$slug = $action;
		if ( ! empty( $this->action_prefix ) ) {
			$slug = $this->action_prefix . '_' . $slug;
		}
		if ( ! empty( $this->action_surfix ) ) {
			$slug .= '_' . $this->action_surfix;
		}
		return $slug;
	}

protected function ajax_slug ( $ action ) { $ slug = $ action ; if ( ! empty ( $ this -> action_prefix ) ) { $ slug = $ this -> action_prefix . '_' . $ slug ; } if ( ! empty ( $ this -> action_surfix ) ) { $ slug .= '_' . $ this -> action_surfix ; } return $ slug ; }

Returns Modified Ajax Action Slug

@param $action

@return string


public function ajax_request_single() {
		$action     = false;
		$action_key = ( true === $this->is_single ) ? $this->action : $this->is_single;

		if ( isset( $_REQUEST[ $action_key . '-action' ] ) && ! empty( $_REQUEST[ $action_key . '-action' ] ) ) {
			$action = $_REQUEST[ $action_key . '-action' ];
		} elseif ( isset( $_REQUEST[ $action_key ] ) && ! empty( $_REQUEST[ $action_key ] ) ) {
			$action = $_REQUEST[ $action_key ];
		}

		$_action = $this->extract_action_slug( $action );

		if ( false !== $action && isset( $this->actions[ $_action ] ) ) {
			if ( false === \is_user_logged_in() && true === $this->actions[ $_action ] ) {
				$this->trigger_ajax_callback( $action );
			} elseif ( \is_user_logged_in() === true ) {
				$this->trigger_ajax_callback( $action );
			}
		}

		\wp_die( 0 );
	}

public function ajax_request_single ( ) { $ action = false ; $ action_key = ( true === $ this -> is_single ) ? $ this -> action : $ this -> is_single ; if ( isset ( $ _REQUEST [ $ action_key . '-action' ] ) && ! empty ( $ _REQUEST [ $ action_key . '-action' ] ) ) { $ action = $ _REQUEST [ $ action_key . '-action' ] ; } elseif ( isset ( $ _REQUEST [ $ action_key ] ) && ! empty ( $ _REQUEST [ $ action_key ] ) ) { $ action = $ _REQUEST [ $ action_key ] ; } $ _action = $ this -> extract_action_slug ( $ action ) ; if ( false !== $ action && isset ( $ this -> actions [ $ _action ] ) ) { if ( false === \ is_user_logged_in ( ) && true === $ this -> actions [ $ _action ] ) { $ this -> trigger_ajax_callback ( $ action ) ; } elseif ( \ is_user_logged_in ( ) === true ) { $ this -> trigger_ajax_callback ( $ action ) ; } } \ wp_die ( 0 ) ; }

Triggers A Callback to a ajax request

@hook ajax_before_{ajax_action}
@hook ajax_after_{ajax_action}

if method not exists then below hook fires
@hook ajax_{ajax_action}
ajax_action will be replaced with {$this->action}-action from url


protected function trigger_ajax_callback( $action ) {
		$_function_action = $this->extract_action_slug( $action );
		if ( method_exists( $this, $this->function_name( $_function_action ) ) ) {
			$function = $this->function_name( $_function_action );
			\do_action( 'ajax_before_' . $action );
			$this->$function();
			\do_action( 'ajax_after_' . $action );
		} else {
			\do_action( 'ajax_' . $action );
		}
	}

protected function trigger_ajax_callback ( $ action ) { $ _function_action = $ this -> extract_action_slug ( $ action ) ; if ( method_exists ( $ this , $ this -> function_name ( $ _function_action ) ) ) { $ function = $ this -> function_name ( $ _function_action ) ; \ do_action ( 'ajax_before_' . $ action ) ; $ this -> $ function ( ) ; \ do_action ( 'ajax_after_' . $ action ) ; } else { \ do_action ( 'ajax_' . $ action ) ; } }

Triggers A AjaxCallback

@hook ajax_before_{ajax_action}
@hook ajax_after_{ajax_action}
if method not exists then below hook fires
@hook ajax_{ajax_action}

@param $action


public function ajax_request() {
		$action  = ( isset( $_REQUEST['action'] ) && ! empty( $_REQUEST['action'] ) ) ? $_REQUEST['action'] : false;
		$_action = $this->extract_action_slug( $action );

		if ( false !== $action && isset( $this->actions[ $_action ] ) ) {
			if ( is_array( $this->actions[ $_action ] ) && isset( $this->actions[ $_action ]['callback'] ) ) {
				call_user_func( $this->actions[ $_action ]['callback'] );
				\wp_die();
			} else {
				$this->trigger_ajax_callback( $_action );
			}
		}
		\wp_die( 0 );
	}

public function ajax_request ( ) { $ action = ( isset ( $ _REQUEST [ 'action' ] ) && ! empty ( $ _REQUEST [ 'action' ] ) ) ? $ _REQUEST [ 'action' ] : false ; $ _action = $ this -> extract_action_slug ( $ action ) ; if ( false !== $ action && isset ( $ this -> actions [ $ _action ] ) ) { if ( is_array ( $ this -> actions [ $ _action ] ) && isset ( $ this -> actions [ $ _action ] [ 'callback' ] ) ) { call_user_func ( $ this -> actions [ $ _action ] [ 'callback' ] ) ; \ wp_die ( ) ; } else { $ this -> trigger_ajax_callback ( $ _action ) ; } } \ wp_die ( 0 ) ; }


private function get_post_request( $key, $default, $type ) {
		$return = $default;
		if ( false !== $this->has( $key, $type ) ) {
			switch ( $type ) {
				case 'GET':
				case 'get':
					$return = $_GET[ $key ];
					break;

				case 'POST':
				case 'post':
					$return = $_POST[ $key ];
					break;

				case 'REQUEST':
				case 'request':
					$return = $_REQUEST[ $key ];
					break;
				default:
					$return = $default;
					break;
			}
		}
		return $return;
	}

private function get_post_request ( $ key , $ default , $ type ) { $ return = $ default ; if ( false !== $ this -> has ( $ key , $ type ) ) { switch ( $ type ) { case 'GET' : case 'get' : $ return = $ _GET [ $ key ] ; break ; case 'POST' : case 'post' : $ return = $ _POST [ $ key ] ; break ; case 'REQUEST' : case 'request' : $ return = $ _REQUEST [ $ key ] ; break ; default : $ return = $ default ; break ; } } return $ return ; }

Checks for the given key in the given method and returns it.

@param $key
@param $default
@param $type

@return mixed

Checks for the given key in the given method and returns it .


public static function genRandomHex($bitLength = 40)
    {
        $sudoRandom = 1;
        for ($i=0;$i<=$bitLength;$i++) $sudoRandom = ($sudoRandom<<1)|rand(0,1);
        return dechex($sudoRandom);
    }

public static function genRandomHex ( $ bitLength = 40 ) { $ sudoRandom = 1 ; for ( $ i = 0 ; $ i <= $ bitLength ; $ i ++ ) $ sudoRandom = ( $ sudoRandom << 1 ) | rand ( 0 , 1 ) ; return dechex ( $ sudoRandom ) ; }


public static function start(...$argv) : void
	{
	    //TODO - make base64 optional
        self::$sessionVar = $argv;
		foreach (self::$sessionVar as $value){
			if (isset($_SESSION[__CLASS__][$value])) {
                $GLOBALS[$value] = $_SESSION[__CLASS__][$value];
                #self::is_serialized( base64_decode(  $_SESSION[__CLASS__][$value] ), $GLOBALS[$value] );
            }
		}

		// You CAN register multiple shutdown functions
		register_shutdown_function( function () use ($argv) {
            $last_error = error_get_last();
            if ($last_error['type'] === E_ERROR) {
                sortDump($last_error);
            } else {
                foreach ($argv as $value) {
                    if (isset($GLOBALS[$value])) {
                        $_SESSION[__CLASS__][$value] = $GLOBALS[$value];
                        #$_SESSION[__CLASS__][$value] = base64_encode( serialize( $GLOBALS[$value] ) );
                    }
                }
            }
		} );
	}

Variables given will be cached between requests.
Variables should be provided as string names referencing
the global scope.
@param array ...$argv

Variables given will be cached between requests . Variables should be provided as string names referencing the global scope .


public static function clear() : void
    {
        if (!empty(self::$sessionVar)) {
            foreach (self::$sessionVar as $value) {
                $GLOBALS[$value] = $_SESSION[$value] = null;
            }
        }
    }

public static function clear ( ) : void { if ( ! empty ( self :: $ sessionVar ) ) { foreach ( self :: $ sessionVar as $ value ) { $ GLOBALS [ $ value ] = $ _SESSION [ $ value ] = null ; } } }

Clear any variables given to the start method.
This does not stop caching, just removes all data
from current variables and cache.

Clear any variables given to the start method . This does not stop caching just removes all data from current variables and cache .


public static function is_serialized($value, &$result = null) : bool
	{
		// Bit of a give away this one
		if (!\is_string( $value )) {
            return false;
        }

		// Serialized false, return true. unserialize() returns false on an
		// invalid string or it could return false if the string is serialized
		// false, eliminate that possibility.
		if ($value === 'b:0;') {
			$result = false;
			return true;
		}

		$length = \strlen( $value );
		$end = '';

		switch ($value[0]) {
			case 's':
				if ($value[$length - 2] !== '"') {
					return false;
				}
			case 'b':
			case 'i':
			case 'd':
				// This looks odd but it is quicker than isset()ing
				$end .= ';';
			case 'a':
			case 'O':
				$end .= '}';

				if ($value[1] !== ':') {
					return false;
				}

				switch ($value[2]) {
					case 0:
					case 1:
					case 2:
					case 3:
					case 4:
					case 5:
					case 6:
					case 7:
					case 8:
					case 9:
						break;

					default:
						return false;
				}
			case 'N':
				$end .= ';';

				if ($value[$length - 1] !== $end[0]) {
					return false;
				}
				break;

			default:
				return false;
		}

		if (($result = @unserialize( $value, true )) === false) {
			$result = null;
			return false;
		}
		return true;
	}

Tests if an input is valid PHP serialized string.

Checks if a string is serialized using quick string manipulation
to throw out obviously incorrect strings. Unserialize is then run
on the string to perform the final verification.

Valid serialized forms are the following:

boolean: b:1;

integer: i:1;

double: d:0.2;

string: s:4:"test";

array: a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}

object: O:8:"stdClass":0:{}

null: N;

@author		Chris Smith
@copyright	Copyright (c) 2009 Chris Smith (http://www.cs278.org/)
@license		http://sam.zoy.org/wtfpl/ WTFPL
@param		string	$value	Value to test for serialized form
@param		mixed	$result	Result of unserialize() of the $value
@return		boolean			True if $value is serialized data, otherwise false

Tests if an input is valid PHP serialized string .


public function handleSlug(HTTPRequest $request)
    {
        $item = $this->findSlug();
        if (!$item) {
            $owner = $this->getOwner();
            $owner->httpError(404);
        }
        $item->setSlugActive(Slug::ACTIVE_CURRENT);
        return ['ActiveSlug' => $item];
    }

public function handleSlug ( HTTPRequest $ request ) { $ item = $ this -> findSlug ( ) ; if ( ! $ item ) { $ owner = $ this -> getOwner ( ) ; $ owner -> httpError ( 404 ) ; } $ item -> setSlugActive ( Slug :: ACTIVE_CURRENT ) ; return [ 'ActiveSlug' => $ item ] ; }

Process a request for a slugged item.

@param HTTPRequest $request
@return array customisation of owner's otherwise normal output


private function addMethod(string $name, callable $closure): void
    {
        $this->methods[$name] = \Closure::bind($closure, $this, static::class);
    }

private function addMethod ( string $ name , callable $ closure ) : void { $ this -> methods [ $ name ] = \ Closure :: bind ( $ closure , $ this , static :: class ) ; }

Attempt to bind a closure to the working scope. This would mean the calling class
not the class which uses the Singelton trait
@param $name
@param $closure
@noinspection PhpUnusedPrivateMethodInspection

Attempt to bind a closure to the working scope . This would mean the calling class not the class which uses the Singelton trait


public static function update($clear = false)
    {
        global $user;
        static $count = 0;
        $count++;

        if ($clear || !($_SESSION['id'] ?? false)) {
            Serialized::clear();
        }

        if (!\is_array($user)) {
            $user = array();
        }

        if (static::$user_id = $_SESSION['id'] = $_SESSION['id'] ?? false) {
            $_SESSION['X_PJAX_Version'] = 'v' . SITE_VERSION . 'u' . $_SESSION['id'];
        } // force reload occurs when X_PJAX_Version changes between requests

        if (!isset($_SESSION['X_PJAX_Version'])) {
            $_SESSION['X_PJAX_Version'] = SITE_VERSION;     // static::$user_id, keep this static
        }

        Request::setHeader('X-PJAX-Version: ' . $_SESSION['X_PJAX_Version']);

        /* If the session variable changes from the constant we will
         * send the full html page and notify the pjax js to reload
         * everything
         * */

        if (\is_callable(self::$callback)) {
            /** @noinspection OnlyWritesOnParameterInspection */
            ($lambda = self::$callback)($clear);    // you must have callable in a variable in fn scope
        }
        if (!\defined('X_PJAX_VERSION')) {
            \define('X_PJAX_VERSION', $_SESSION['X_PJAX_Version']);
        }
        Request::sendHeaders();  // Send any stored headers
    }

This handles our users state. If the user goes form logged-in to logged-out
the outer html-wrapper will be sent.
@param bool $clear - if true is passed serialized data will be set to null

This handles our users state . If the user goes form logged - in to logged - out the outer html - wrapper will be sent .


public static function clear()
    {
        try {
            $id = session_id();
            $_SESSION = array();
            session_write_close();
            # $db = Database::database();
            # $db->prepare('DELETE FROM sessions WHERE session_id = ?')->execute([$id]);
            sessions::Delete($_SESSION,$id,[]);
            session_start();
        } catch (\PDOException $e) {
            sortDump($e);
        }
    }

This will remove our session data from our scope and the database


private function verifySocket($ip)
    {
        if ($ip) {
            $_SERVER['REMOTE_ADDR'] = $ip;
        }

        preg_match ('#PHPSESSID=([^;\s]+)#', $_SERVER['HTTP_COOKIE'] ?? false, $array, PREG_OFFSET_CAPTURE);

        $session_id = $array[1][0] ?? false;

        if (!$session_id) {
            print 'Failed to capture PHPSESSID' . PHP_EOL;
            die(1);
        }

        $db = Database::database();
        $sql = 'SELECT count(*) FROM sessions WHERE user_ip = ? AND session_id = ? LIMIT 1';
        $stmt = $db->prepare($sql);
        $stmt->execute([$_SERVER['REMOTE_ADDR'], $session_id]);
        $session = $stmt->fetchColumn();
        self::$session_id = $session_id;
        if (!$session) {
            if (SOCKET) {
                print 'BAD ADDRESS :: ' . $_SERVER['REMOTE_ADDR'] . "\n\n";
            }
            die(0);
        }
        session_id($session_id);
    }

This function was created to make sure all socket request come from
an existing user who has a session stored in our database. If database
session storage is turned off this method will fail and exit.

@param $ip - the ip address to look up from our database.

This function was created to make sure all socket request come from an existing user who has a session stored in our database . If database session storage is turned off this method will fail and exit .


public function open($savePath, $sessionName)
    {
        try {
            Database::database()->prepare('SELECT count(*) FROM sessions LIMIT 1')->execute();
        } catch (\PDOException $e) {
            if ($e->getCode()) {
                print "
Setting up database {$e->getCode()}
";
                Database::setUp();
                exit(1);
            }
        }
        return true;
    }

This is required for the session save handler interface.
Do no change.

@param string $savePath
@param string $sessionName
@return bool

This is required for the session save handler interface . Do no change .


public function gc($maxLife)
    {
        $db = Database::database();
        return $db->prepare('DELETE FROM sessions WHERE (UNIX_TIMESTAMP(session_expires) + ? ) < UNIX_TIMESTAMP(?)')->execute([$maxLife, date('Y-m-d H:i:s')]) ?
            true : false;
    }

This is our garbage collector. If a session is expired attempt to remove it.
This function is executed via a probability. See link for more details.
@link http://php.net/manual/en/features.gc.php
@param int $maxLife
@return bool

This is our garbage collector . If a session is expired attempt to remove it . This function is executed via a probability . See link for more details .


private function matchRule($route, RoutingRuleAbstract &$rule) {
        list($regex, $inputs) = $this->getRegexProperties($rule);

        $matches = array();
        preg_match($regex, $route, $matches);
        if (count($matches) > 0) {
            //Substract the first element of the array, which is the complete URL
            array_splice($matches, 0, 1);
            for ($i = 0; $i < count($inputs); $i++) {
                $key = $inputs[$i];
                $value = $matches[$i];
                $rule->getInput()->setInput($key, $value);
            }
            return true;
        }
        return false;
    }

Check if route matches with rule depending on regular expression which
defines them.
@param string $route
@param RoutingRuleAbstract $rule
@return bool true if rule matches with route or false if not

Check if route matches with rule depending on regular expression which defines them .


public function getDataPage()
    {
        return array(
            'title' => $this->getTitle(),
            'slug' => $this->getSlug(),
            'language' => $this->getLanguage(),
            'menu_title' => $this->getMenuTitle(),
            'is_in_navigation' => $this->getIsInNavigation(),
            'forced_url' => $this->getForcedUrl(),
            'left' => $this->getLeft(),
            'right' => $this->getRight(),
            'root' => $this->getRoot(),
            'level' => $this->getLevel(),
            'hasChildren' => $this->getHasChildren()
        );
    }

public function getDataPage ( ) { return array ( 'title' => $ this -> getTitle ( ) , 'slug' => $ this -> getSlug ( ) , 'language' => $ this -> getLanguage ( ) , 'menu_title' => $ this -> getMenuTitle ( ) , 'is_in_navigation' => $ this -> getIsInNavigation ( ) , 'forced_url' => $ this -> getForcedUrl ( ) , 'left' => $ this -> getLeft ( ) , 'right' => $ this -> getRight ( ) , 'root' => $ this -> getRoot ( ) , 'level' => $ this -> getLevel ( ) , 'hasChildren' => $ this -> getHasChildren ( ) ) ; }


public function isPage(Page $page = null)
    {
        return null !== $page && $this->getId() === $page->getId();
    }

public function isPage ( Page $ page = null ) { return null !== $ page && $ this -> getId ( ) === $ page -> getId ( ) ; }

Tells if the the given page is this page.

Useful when not hydrating all fields.

@param Page $Page
@return Boolean

Tells if the the given page is this page .


public function loadClassMetadata(string $className)
    {
        $metadata = new ClassMetadata();
        $reflection = new \ReflectionClass($className);

        $this->processClassAnnotations($reflection, $metadata);
        $this->processPropertyAnnotations($reflection, $metadata);

        return $metadata;
    }

public function loadClassMetadata ( string $ className ) { $ metadata = new ClassMetadata ( ) ; $ reflection = new \ ReflectionClass ( $ className ) ; $ this -> processClassAnnotations ( $ reflection , $ metadata ) ; $ this -> processPropertyAnnotations ( $ reflection , $ metadata ) ; return $ metadata ; }

Loads the ClassMetadata for the given class

@param string $className

@return ClassMetadata


public function createCondition(CreatePropertyConditionEvent $event)
    {
        $meta = $event->getData();

        if ('conditionpropertyvalueis' !== $meta['type']) {
            return;
        }

        $metaModel = $event->getMetaModel();
        $attribute = $metaModel->getAttributeById($meta['attr_id']);
        if (!($attribute instanceof TranslatedCheckbox)) {
            return;
        }

        if ((bool) $meta['value']) {
            $event->setInstance(new PropertyTrueCondition($attribute->getColName()));
            return;
        }
        $event->setInstance(new PropertyFalseCondition($attribute->getColName()));
    }

public function createCondition ( CreatePropertyConditionEvent $ event ) { $ meta = $ event -> getData ( ) ; if ( 'conditionpropertyvalueis' !== $ meta [ 'type' ] ) { return ; } $ metaModel = $ event -> getMetaModel ( ) ; $ attribute = $ metaModel -> getAttributeById ( $ meta [ 'attr_id' ] ) ; if ( ! ( $ attribute instanceof TranslatedCheckbox ) ) { return ; } if ( ( bool ) $ meta [ 'value' ] ) { $ event -> setInstance ( new PropertyTrueCondition ( $ attribute -> getColName ( ) ) ) ; return ; } $ event -> setInstance ( new PropertyFalseCondition ( $ attribute -> getColName ( ) ) ) ; }

Create property condition for the translated checkbox.

@param CreatePropertyConditionEvent $event The property condition event.

@return void

Create property condition for the translated checkbox .


public function initPluginInstalled() {
        try {
            foreach ($this->pluginPaths as $path) {
                //Get the installed plugins
                $newPluginInstalled = $this->pluginLocator->getInstalledPlugins($this->autoloader->getURLBase().$path);
                $listOfPluginsInstalled = $this->createPluginInstances($newPluginInstalled, true);
                foreach ($listOfPluginsInstalled as $newPlugin) {
                    $this->pluginList[] = $newPlugin['plugin'];
                }
            }
            return $this->pluginList;
        } catch (Exception $e) {
            throw new PluginException('Plugin Manager: Can not init all plugins. '
                    . 'Please find attach the error from the '
                    . 'initialization:'. $e->getMessage());
        }
    }

Get the list of plugins installed and init them.

@return false | array(PluginInterface)
@throws PluginException

Get the list of plugins installed and init them .


public function getPluginList() {
        $arrayPluginList = array();
        try {
            //Iterate over the plugins paths
            foreach ($this->pluginPaths as $path) {
                //Search new plugins
                $newPluginsDiscover = $this->pluginLocator->discoverPlugins($this->autoloader->getURLBase().$path);

                //Instantiate the plugins
                $listOfPluginsDiscover = $this->createPluginInstances($newPluginsDiscover);
                foreach ($listOfPluginsDiscover as $newPlugin) {
                    $arrayPluginList[] = array('plugin'=>$newPlugin['plugin'], 'enabled'=>$newPlugin['enabled']);
                }
            }
        } catch (\Exception $e) {
            throw new PluginException('Plugin Manager: Can not init all plugins. '
                    . 'Please find attach the error from the '
                    . 'initialization:'. $e->getMessage());
        }
        return (array)$arrayPluginList;
    }

Return the list of all plugin available, installed and not installed.

@return array PluginInterface
@throws PluginException

Return the list of all plugin available installed and not installed .


public function loadTwig() {

        $loader = new \Twig_Loader_Filesystem(
            array (
                $this->viewsFolder
            )
        );

        // Set up environment
        $params = array(
            //'cache' => $this->viewsFolder . "cache",
        );

        $this->twig = new \Twig_Environment($loader, $params);
    }

Prepare Twig to be use into views
@return Twig instance


private function setDefaultLanguage($userId) {
        if ($this->language !== null) {
            $languageModel = new \Mmf\Language\LanguageModel($this->connection);
            $userLanguageProperties = $languageModel->getUserLanguage($userId);
            if ($userLanguageProperties !== false) {
                $this->language->setLocale($userLanguageProperties['code']);
            }
        }
    }

private function setDefaultLanguage ( $ userId ) { if ( $ this -> language !== null ) { $ languageModel = new \ Mmf \ Language \ LanguageModel ( $ this -> connection ) ; $ userLanguageProperties = $ languageModel -> getUserLanguage ( $ userId ) ; if ( $ userLanguageProperties !== false ) { $ this -> language -> setLocale ( $ userLanguageProperties [ 'code' ] ) ; } } }

Set the default language for this user.

@param int $userId

Set the default language for this user .


private function checkIfTokenIsValidAndUpdateTheExpireDate() {
        $userInfo = $this->authModel->getRoleAndUserFromToken($this->token);
        if ($userInfo === false) {
            throw new AuthException('The token is not valid', 2000);
        }
        if ($userInfo['expire'] !== null &&
                $userInfo['expire'] < $userInfo['db_date']) {
            throw new AuthException('The token expires', 2001);
        }
        if ($userInfo['expire'] !== null) {
            $futureExpiredate = date('Y-m-d H:i:s',
                    strtotime($userInfo['db_date']) + $this->config->get('auth')['sessionTimeLife']
                    * 60);
            $this->authModel->updateExpireDate($this->token, $futureExpiredate);
        }
        return $userInfo;
    }

Check if token is valid, if not throws and error.

@throws MmfAuthException

Check if token is valid if not throws and error .


public function get($name, $template = '', $vars = array(), $globalScriptVars = '') {
        if ($template !== '') {
            $this->setTemplate($template);
        }
        //Creation the full path of the view
        $path = $this->viewsFolder . '/html/' . $name;
        //If exists vars to assign, we assing one by one.
        $viewVars = (count($vars) > 0) ? $vars : $this->viewVars;

        //Include the style if exists some style to include
        if (isset($this->styles)) {
            $vars['styles'] = $this->styles;
        }

        //Finalmente, incluimos la plantilla con las variables de los scripts.
        $this->contentView = $this->getFileContent($path, $viewVars) . $globalScriptVars;
        return $this;
    }

Get the view render as string.

@param string $name path name to the view.
@param string $template name of the template used for this view in case
to be the last one to be output.
@param mixed $vars vars to include into the view.
@param mixed $globalScriptVars global scripts included in the view.
@return BasicViewInterface


public function addJsVar($vars, $value, $encode = false) {
        if (is_array($vars)) {
            foreach ($vars as $key => $value) {
                // if JSONencode it's enable then is because it doesn't want json_encode.
                $this->addJsVar($key, $value);
            }
        } else { // apply the logic
            $this->scriptVars = $this->scriptVars . "var $vars = " . ($encode ? json_encode($value) : $value) . ";";
        }
    }

Add a global JS variable to the view

@param mixed $vars array(variable_name => value, ...) or simply the
variable name. If $value happens to be a number (or something else you
don't want to "json_encode()", set $encode = FALSE
@param string $value
@param bool $encode = TRUE. If we don't want to encode some variable,
it is mandatory to add them one by one, under the pattern
addJsVar( $varName, $varValue, FALSE )
@note remember that if $foo is a string, then json_encode($var) === $var


public function addScript($jsfile, $min = FALSE, $type = 'text/javascript') {
        //Check if we must minified the style
        $minTag = "<script type='$type' src='min/?f=" . $this->asset($jsfile, TRUE) . "' ></script>";
        $maxTag = "<script type='$type' src='" . $this->asset($jsfile, TRUE) . "' ></script>";

        //TODO: min files
        $includeTag = $maxTag;

        $minPos = strpos($this->scripts, $minTag);
        $maxPos = strpos($this->scripts, $maxTag);

        if ($minPos === FALSE && $maxPos === FALSE) {  // Si no esta, concatenamos
            $this->scripts .= $includeTag;
        }
    }

public
function
addScript
(
$
jsfile
,
$
min
=
FALSE
,
$
type
=
'text/javascript'
)
{
//Check if we must minified the style
$
minTag
=
"<script type='$type' src='min/?f="
.
$
this
->
asset
(
$
jsfile
,
TRUE
)
.
"' ></script>"
;
$
maxTag
=
"<script type='$type' src='"
.
$
this
->
asset
(
$
jsfile
,
TRUE
)
.
"' ></script>"
;
//TODO: min files
$
includeTag
=
$
maxTag
;
$
minPos
=
strpos
(
$
this
->
scripts
,
$
minTag
)
;
$
maxPos
=
strpos
(
$
this
->
scripts
,
$
maxTag
)
;
if
(
$
minPos
===
FALSE
&&
$
maxPos
===
FALSE
)
{
// Si no esta, concatenamos
$
this
->
scripts
.=
$
includeTag
;
}
}

Add Script into the cue of Script vars.

@param string $jsfile
@param bool $min
@param string $type

Add Script into the cue of Script vars .


public function addStyles($cssfile, $min = FALSE) {
        //Check if we must minified the style
        $minTag = "<link href='min/?f=" . $this->asset($cssfile, TRUE) . "' rel='stylesheet' type='text/css'/>";
        $maxTag = "<link href='" . $this->asset($cssfile, TRUE) . "' rel='stylesheet' type='text/css'/>";

        //TODO: min styles
        $includeTag = $maxTag;

        $minPos = strpos($this->styles, $minTag);
        $maxPos = strpos($this->styles, $maxTag);

        //If it doesn't exist, we concat with the actual styles
        if ($minPos === FALSE && $maxPos === FALSE) {
            $value = $this->styles . $includeTag;
            $this->styles = $value;
        }
    }

Add Style into the cue of style vars.

@param string $cssfile
@param bool $min


protected function getFileContent($path, $vars = array()) {

        //If there is vars to assign.
        if (is_array($vars)) {
            foreach ($vars as $key => $value) {
                /* @var $value BasicViewInterface */
                //If is a view, get the content of the view.
                if (is_object($value) && is_a($value, '\Mmf\View\BasicViewInterface')) {
                    $$key = $value->getContentView();
                } else {
                    $$key = $value;
                }
            }
        }
        ob_start();
        /** @noinspection PhpIncludeInspection */
        include($path);
        $output = ob_get_clean();
        return $output;
    }

Get the content of the view with the template vars replace it.

@param string $path
@param array  $vars

@return string

Get the content of the view with the template vars replace it .


public function getContentWithTemplate() {
        $vars = $this->viewVars;
        //If there is vars to assign.
        if (is_array($vars)) {
            foreach ($vars as $key => $value) {
                /* @var $value BasicViewInterface */
                //If is a view, get the content of the view.
                if (is_object($value) && is_a($value, '\Mmf\View\BasicViewInterface')) {
                    $$key = $value->getContentView();
                } else {
                    $$key = $value;
                }
            }
        }

        $content = $this->getContentView();
        if ($this->template == "") {
            $output = $content;
        } else {
            $scripts = '';
            if (strlen($this->scriptVars) > 0) {
                $scripts = "<script>/* Global Vars */".$this->scriptVars."</script>";
            }
            $styles = $this->getAllCss();
            $scripts .= $this->getAllScripts();
            ob_start();
            $path = $this->viewsFolder . '/template/' . $this->template;

            if (file_exists($path)) {
                /** @noinspection PhpIncludeInspection */
                include ($path);
            } else {
                $output = ob_get_clean();
                throw new \Exception('Template does not exists', 1502);
            }

            $output = ob_get_clean();
        }
        return $output;
    }

Get the view content but included into a template.

@return string
@throws Exception

Get the view content but included into a template .


public function getAllScripts() {
        $return = '';
        foreach ($this->config->get('mvc')['defaultScripts'] as $script) {
            //If the script includes the // is for example http or https absolute route
            if (strpos($script, '//') !== FALSE) {
                $return .= '<script type="text/javascript" src="' . $script . '"></script>';
            } else {
                $return .= '<script type="text/javascript" src="' . $this->asset($script, TRUE) . '"></script>';
            }
        }
        $return .= $this->scripts;
        return $return;
    }

Get all the scripts, included the default scripts defined in the config
file.

@return string with the dinamic and default scripts

Get all the scripts included the default scripts defined in the config file .


public function getAllCss() {
        $return = '';
        foreach ($this->config->get('mvc')['defaultCSS'] as $script) {
            //If the script includes the // is for example http or https absolute route
            if (strpos($script, '//') !== FALSE) {
                $return .= "<link href='" . $script . "' rel='stylesheet' type='text/css'/>";
            } else {
                $return .= "<link href='" . $this->asset($script, TRUE) . "' rel='stylesheet' type='text/css'/>";
            }
        }
        $return .= $this->styles;
        return $return;
    }

Get all the styles.
file.

@return string with the dinamic and default scripts


public function asset($path = "/", $return = FALSE) {
        $installFolder = $this->config->get('mvc')['installFolder'];
        if (!$return) {
            echo $installFolder . $path;
        }
        return $installFolder . $path;
    }

public function asset ( $ path = "/" , $ return = FALSE ) { $ installFolder = $ this -> config -> get ( 'mvc' ) [ 'installFolder' ] ; if ( ! $ return ) { echo $ installFolder . $ path ; } return $ installFolder . $ path ; }

Return or Echo the install folder.

@param string $path path from install path
@param bool $return (return=FALSE) if it's true, the result is returned.
@return string | void


public function isAllowed(RoutingRuleAbstract $routingRule) {
        $controller = $routingRule->getController();
        if (substr($controller, -10) == "Controller") {
            $controller = substr($controller,0, -10);
        }

        //$function = new \ReflectionClass($routingRule->getController() . 'Controller');
        /*
        var_dump($function->inNamespace());
        var_dump($function->getName());
        var_dump($function->getNamespaceName());
        var_dump($function->getShortName());
         */
        //$controller = str_ireplace("Controller", "", $function->getShortName());

        $action = $routingRule->getAction();
        $access = $this->getAccess();
        $allowed = FALSE;
        if (array_key_exists($controller, $access)) {
            foreach ($access[$controller] as $rule) {
                if ($rule == "*") {
                    $allowed = TRUE;
                } else {
                    if ($allowed) { //After general acceptation like * can be an exception
                        $negation = FALSE;
                        if ($rule[0] == "!") {
                            $negation = TRUE;
                            $rule = substr($rule, 1);
                        }

                        if ($negation) { //By the moment is allowed but maybe there is an exception rule
                            if ($rule == $action) {
                                $allowed = FALSE;
                            }
                        }
                    } else {
                        if ($rule == $action) {
                            $allowed = TRUE;
                        }
                    }
                }
            }
        }
        return $allowed;
    }

Main Function, used to check if the request have autorization to access
into the controller and action required.

@param \MmfRoutingRuleAbstract $routingRule
@return bool TRUE if the user is allow to execute the routing rule or
FALSE if the user is not allowed.

Main Function used to check if the request have autorization to access into the controller and action required .


private function getAccess() {
        if (is_null($this->access)) {
            $chain = $this->getRolesChain();
            $tmpAccess = array();

            foreach ($chain as $role) {
                $arrAccess = $this->aclModel->getAccessForARole($role['id_role']);
                foreach ($arrAccess as $accessItem) {
                    $tmpAccess[$accessItem['controller']] = explode("|",
                            $accessItem['rules']);
                }
            }
            $this->access = $tmpAccess;
            return $this->access;
        } else {
            return $this->access;
        }
    }

private function getAccess ( ) { if ( is_null ( $ this -> access ) ) { $ chain = $ this -> getRolesChain ( ) ; $ tmpAccess = array ( ) ; foreach ( $ chain as $ role ) { $ arrAccess = $ this -> aclModel -> getAccessForARole ( $ role [ 'id_role' ] ) ; foreach ( $ arrAccess as $ accessItem ) { $ tmpAccess [ $ accessItem [ 'controller' ] ] = explode ( "|" , $ accessItem [ 'rules' ] ) ; } } $ this -> access = $ tmpAccess ; return $ this -> access ; } else { return $ this -> access ; } }

Return a normal access array.

@return array


private function getRolesChain() {
        if (is_null($this->rolesChain)) {
            $chain = array();
            $role = $this->aclModel->getRoleById($this->roleId);
            while ($role != FALSE) {
                $chain[] = $role;
                $currId = $role['id_parent'];
                $role = $this->aclModel->getRoleById($currId);
            }

            $this->rolesChain = array_reverse($chain);
        }
        return $this->rolesChain;
    }

private function getRolesChain ( ) { if ( is_null ( $ this -> rolesChain ) ) { $ chain = array ( ) ; $ role = $ this -> aclModel -> getRoleById ( $ this -> roleId ) ; while ( $ role != FALSE ) { $ chain [ ] = $ role ; $ currId = $ role [ 'id_parent' ] ; $ role = $ this -> aclModel -> getRoleById ( $ currId ) ; } $ this -> rolesChain = array_reverse ( $ chain ) ; } return $ this -> rolesChain ; }

Get the list of roles chain. For example, if admin have user as parent
role, it returns the admin and user role.

@return array

Get the list of roles chain . For example if admin have user as parent role it returns the admin and user role .


public function getUserLanguage($userId) {
        $sql = 'SELECT language.id_language,
                       language.name,
                       language.code,
                       language.default
                FROM user
                INNER JOIN language ON language.id_language = user.id_language
                WHERE user.id_user=\''.$userId.'\'';

        $language = $this->select($sql);
        if (count($language)>0) {
            return $language[0];
        } else {
            return false;
        }
    }

Return the user language properties.

@param int $userId
@return boolean


public function translateChoice($id, $number, array $parameters = array(), $locale = null) {
        if (null === $locale) {
            $locale = $this->getLocale();
        } else {
            $this->assertValidLocale($locale);
        }
        //Get the translations
        $translations = $this->getTranslation($locale);

        //Calculate the translation and replace the parameters
        return strtr($this->getTranslationForId($id, $translations, $number), $parameters);
    }

Translates the given choice message by choosing a translation according to a number.

@param string      $id         The message id (may also be an object that can be cast to string)
@param int         $number     The number to use to find the indice of the message
@param array       $parameters An array of parameters for the message
@param string|null $locale     The locale or null to use the default

@throws \InvalidArgumentException If the locale contains invalid characters

@return string The translated string

Translates the given choice message by choosing a translation according to a number .


public function getTranslation($locale) {
        if (!isset($this->translations[$locale])) {
            $this->translations[$locale] = $this->getFileTranslations($locale, $this->translatePath);
        }
        return $this->translations[$locale];
    }

public function getTranslation ( $ locale ) { if ( ! isset ( $ this -> translations [ $ locale ] ) ) { $ this -> translations [ $ locale ] = $ this -> getFileTranslations ( $ locale , $ this -> translatePath ) ; } return $ this -> translations [ $ locale ] ; }

Returns the list of translations.

@param string $locale
@return array|null


protected function getFileTranslations($locale, $translatePath) {
        $fileToInclude = $translatePath.$locale.'.php';
        if (file_exists($fileToInclude)) {
            /** @noinspection PhpIncludeInspection */
            require $fileToInclude;
            return $translation;
        }  else {
            throw new \InvalidArgumentException('Invalid path file');
        }
    }

Get the translation array.

@param string $locale
@param string $translatePath

@throws \InvalidArgumentException

@returns array of translations


protected function getTranslationForId($id, $translationArray, $number = 0) {
        $translation = '';
        if(isset($translationArray[$id])) { //Id all join
            $translation = $this->getBasicTranslationForId($translationArray[$id], $number);
        } else { //Id separataly
            $arrayOfIds = explode(' ', $id);
            $constructTranslateArray = $translationArray;
            foreach ($arrayOfIds as $subId) {
                if(!isset($constructTranslateArray[$subId])) {
                    throw new TranslateException('Translation id not exists.('.$id.')');
                }
                $constructTranslateArray = $constructTranslateArray[$subId];

            }
            $translation = $this->getBasicTranslationForId($constructTranslateArray, $number);
        }
        //Return the string translate with the parameters include into the placeholders
        return $translation;
    }

Get the translation.

@param string  $id
@param array   $translationArray
@param int     $number

@throws TranslateException

@return string translation


private function getBasicTranslationForId($translationId, $number) {
        if(is_array($translationId) //Is array and we get the translate given for number array
            && isset($translationId[$number])
            && is_string($translationId[$number])) {
             $translation = $translationId[$number];
         } else if (is_string($translationId)) { //Is string directly
             $translation = $translationId;
         }
         return $translation;
    }

Calculate the basic translation.

@param mixed  $translationId
@param int     $number

@throws TranslateException

@return string


protected function generateToggleCommand($commands, $attribute, $commandName, $class, $language)
    {
        if (!$commands->hasCommandNamed($commandName)) {
            $toggle = new TranslatedToggleCommand();
            $toggle
                ->setLanguage($language)
                ->setToggleProperty($attribute->getColName())
                ->setName($commandName)
                ->setLabel($GLOBALS['TL_LANG']['MSC']['metamodelattribute_translatedcheckbox']['toggle'][0])
                ->setDescription(
                    \sprintf(
                        $GLOBALS['TL_LANG']['MSC']['metamodelattribute_translatedcheckbox']['toggle'][1],
                        $attribute->getName(),
                        $language
                    )
                );

            $extra          = $toggle->getExtra();
            $extra['icon']  = 'visible.svg';
            $extra['class'] = $class;

            if ($commands->hasCommandNamed('show')) {
                $info = $commands->getCommandNamed('show');
            } else {
                $info = null;
            }
            $commands->addCommand($toggle, $info);
        }
    }

protected function generateToggleCommand ( $ commands , $ attribute , $ commandName , $ class , $ language ) { if ( ! $ commands -> hasCommandNamed ( $ commandName ) ) { $ toggle = new TranslatedToggleCommand ( ) ; $ toggle -> setLanguage ( $ language ) -> setToggleProperty ( $ attribute -> getColName ( ) ) -> setName ( $ commandName ) -> setLabel ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'metamodelattribute_translatedcheckbox' ] [ 'toggle' ] [ 0 ] ) -> setDescription ( \ sprintf ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'metamodelattribute_translatedcheckbox' ] [ 'toggle' ] [ 1 ] , $ attribute -> getName ( ) , $ language ) ) ; $ extra = $ toggle -> getExtra ( ) ; $ extra [ 'icon' ] = 'visible.svg' ; $ extra [ 'class' ] = $ class ; if ( $ commands -> hasCommandNamed ( 'show' ) ) { $ info = $ commands -> getCommandNamed ( 'show' ) ; } else { $ info = null ; } $ commands -> addCommand ( $ toggle , $ info ) ; } }

Generate the toggle command information.

@param CommandCollectionInterface $commands    The already existing commands.

@param IAttribute                 $attribute   The attribute.

@param string                     $commandName The name of the new command.

@param string                     $class       The name of the CSS class for the command.

@param string                     $language    The language name.

@return void

@SuppressWarnings(PHPMD.Superglobals)
@SuppressWarnings(PHPMD.CamelCaseVariableName)

Generate the toggle command information .


protected function buildCommandsFor($attribute, $commands)
    {
        $activeLanguage = $attribute->getMetaModel()->getActiveLanguage();
        $commandName    = 'publishtranslatedcheckboxtoggle_' . $attribute->getColName();

        $this->generateToggleCommand(
            $commands,
            $attribute,
            $commandName . '_' . $activeLanguage,
            'contextmenu',
            $activeLanguage
        );

        foreach (\array_diff($attribute->getMetaModel()->getAvailableLanguages(), [$activeLanguage]) as $langCode) {
            $this->generateToggleCommand(
                $commands,
                $attribute,
                $commandName . '_' . $langCode,
                'edit-header',
                $langCode
            );
        }
    }

protected function buildCommandsFor ( $ attribute , $ commands ) { $ activeLanguage = $ attribute -> getMetaModel ( ) -> getActiveLanguage ( ) ; $ commandName = 'publishtranslatedcheckboxtoggle_' . $ attribute -> getColName ( ) ; $ this -> generateToggleCommand ( $ commands , $ attribute , $ commandName . '_' . $ activeLanguage , 'contextmenu' , $ activeLanguage ) ; foreach ( \ array_diff ( $ attribute -> getMetaModel ( ) -> getAvailableLanguages ( ) , [ $ activeLanguage ] ) as $ langCode ) { $ this -> generateToggleCommand ( $ commands , $ attribute , $ commandName . '_' . $ langCode , 'edit-header' , $ langCode ) ; } }

Build a attribute toggle operation for all languages of the MetaModel.

@param TranslatedCheckbox         $attribute The checkbox attribute.

@param CommandCollectionInterface $commands  The already existing commands.

@return void

Build a attribute toggle operation for all languages of the MetaModel .


public function handle(BuildMetaModelOperationsEvent $event)
    {
        foreach ($event->getMetaModel()->getAttributes() as $attribute) {
            if (($attribute instanceof TranslatedCheckbox) && ($attribute->get('check_publish') == 1)) {
                $container = $event->getContainer();
                if ($container->hasDefinition(Contao2BackendViewDefinitionInterface::NAME)) {
                    $view = $container->getDefinition(Contao2BackendViewDefinitionInterface::NAME);
                } else {
                    $view = new Contao2BackendViewDefinition();
                    $container->setDefinition(Contao2BackendViewDefinitionInterface::NAME, $view);
                }
                $this->buildCommandsFor($attribute, $view->getModelCommands());
            }
        }
    }

public function handle ( BuildMetaModelOperationsEvent $ event ) { foreach ( $ event -> getMetaModel ( ) -> getAttributes ( ) as $ attribute ) { if ( ( $ attribute instanceof TranslatedCheckbox ) && ( $ attribute -> get ( 'check_publish' ) == 1 ) ) { $ container = $ event -> getContainer ( ) ; if ( $ container -> hasDefinition ( Contao2BackendViewDefinitionInterface :: NAME ) ) { $ view = $ container -> getDefinition ( Contao2BackendViewDefinitionInterface :: NAME ) ; } else { $ view = new Contao2BackendViewDefinition ( ) ; $ container -> setDefinition ( Contao2BackendViewDefinitionInterface :: NAME , $ view ) ; } $ this -> buildCommandsFor ( $ attribute , $ view -> getModelCommands ( ) ) ; } } }

Create the property conditions.

@param BuildMetaModelOperationsEvent $event The event.

@return void

@throws \RuntimeException When no MetaModel is attached to the event or any other important information could
not be retrieved.


public function main() {
        $this->config->set('URLBase', $this->autoload->getURLBase());

        $this->setAndAppLibraries(); //Load All library paths, not include in try because ErrorController is not present.
        $this->loadAppFilesystem(); //Include the app filesystem structure into the loader path.

        $this->errorController = $this->getLibraryInstance('mvc', 'errorClass'); //Create error controller.
        //TODO log
        try {

            return $this->createMVCAction(); //Load Event, Plugin, Language, Routing, Auth, ACL, View, and controllers.
        } catch (ControllerException $e) { //Catch the false response from controller, not catch the problem errors.
            return $this->routingRule->getOutput()->formatResponseBad(['errorCode' => $e->getCode(),
                        'errorMessage' => $e->getMessage()]);
        } catch (RoutingException $e) { //Catch the routing not resolve.
            $respAutoClass = $this->getLibraryInstance('io', 'respAutoClass', $this->config);
            /* @var $respAutoClass ResponseInterface */
            return $respAutoClass->formatResponseBad(['errorCode' => $e->getCode(),
                        'errorMessage' => 'The URL not match with any of our defined routes']);
            //TODO translate all the texts
        } catch (Exception $e) { //Catch the All other frameworks exceptions.
            $respAutoClass = $this->getLibraryInstance('io', 'respAutoClass', $this->config);
            /* @var $respAutoClass ResponseInterface */
            return $respAutoClass->formatResponseBad(['errorCode' => $e->getCode(),
                        'errorMessage' => $e->getMessage()]);
        } catch (\Exception $e) { //Catch not controlled errors
            $this->executionErrors = 1;
            $this->messageErrors = 'File:' . $e->getFile() . ' File line:' . $e->getLine() . ', Message:' . $e->getMessage() . ', Traceroute:' . $e->getTraceAsString();
            $this->traceRouteErrors = $e->getTrace();
            $this->errorController->displayError(500);

            $respAutoClass = $this->getLibraryInstance('io', 'respAutoClass', $this->config);
            /* @var $respAutoClass ResponseInterface */
            return $respAutoClass->formatResponseBad(['errorCode' => $e->getCode(),
                        'errorMessage' => 'Internal Server Error']);
        }
    }

Is the function to start the Framework. Is usually call in index .

@throws Exception

Is the function to start the Framework . Is usually call in index .


protected function prepareAndCreateControllerAction() {
        //Create the view controller
        $this->view = $this->getLibraryInstance('mvc', 'viewClass', $this->config);

        //Create the controller with the core.
        $controller = $this->createCoreAndController(
                $this->routingRule->getController() . 'Controller',
                $this->eventManager,
                $this->routingRule->getInput(),
                $this->routingRule->getOutput(),
                $this->view,
                $this->language,
                $this->routingResolver,
                $this->errorController,
                $this->session,
                $this->connection,
                $this->auth
        );

        //Execute the controller action with the parameters.
        $actionReturn = $this->callClassAndMethodWithInputArguments($controller, $this->routingRule->getAction(), $this->routingRule->getInput());

        //Format the response
        return $this->routingRule->getOutput()->formatResponse($actionReturn);
    }

This method will create the view, the core and controller and
execute the action.

@return mixed controller->action return

This method will create the view the core and controller and execute the action .


protected function executeACL() {
        //Create the ACL
        $this->acl = $this->getLibraryInstance('acl', 'aclClass', $this->auth, $this->connection, $this->language);
        $isAllowed = $this->acl->isAllowed($this->routingRule);

        //Check if is allow to create the controller and call the action
        if (!$isAllowed) {
            throw new ControllerException('User not allow to access', 1500);
        }
    }

Execute the Access Control List, throws and ControllerException if is not allowed.

@throws ControllerException

Execute the Access Control List throws and ControllerException if is not allowed .


protected function executeAuth() {
        //Create Auth controller
        $this->auth = $this->getLibraryInstance('auth', 'authClass', $this->session, $this->routingRule->getInput(), $this->connection, $this->config, $this->language);
    }

protected
function
executeAuth
(
)
{
//Create Auth controller
$
this
->
auth
=
$
this
->
getLibraryInstance
(
'auth'
,
'authClass'
,
$
this
->
session
,
$
this
->
routingRule
->
getInput
(
)
,
$
this
->
connection
,
$
this
->
config
,
$
this
->
language
)
;
}

Execute the Authentication system, throws and ControllerException if
the session is not longer valid.

@throws ControllerException

Execute the Authentication system throws and ControllerException if the session is not longer valid .


protected function executeResolveRoute() {
        //Add bulk routes
        $routingIniFile = $this->autoload->getURLBase() . $this->config->get('routing')['bulkRoutePath'];
        $this->routingResolver->addBulkRoutes($routingIniFile);

        //Resolve route
        $this->routingRule = $this->routingResolver->resolve();
    }

protected
function
executeResolveRoute
(
)
{
//Add bulk routes
$
routingIniFile
=
$
this
->
autoload
->
getURLBase
(
)
.
$
this
->
config
->
get
(
'routing'
)
[
'bulkRoutePath'
]
;
$
this
->
routingResolver
->
addBulkRoutes
(
$
routingIniFile
)
;
//Resolve route
$
this
->
routingRule
=
$
this
->
routingResolver
->
resolve
(
)
;
}

Resolve the route.

@throws \RoutingException when no route is matching


private function setAndAppLibraries() {
        //Get the  libraries and application libraries
        $this->appLibraries = $this->config->get('app')['paths'];

        //Get the Structure
        $this->Structure = $this->config->get('Structure')['filesystem'];

        //Set to Autoloader the internal Structure
        $this->autoload->setStructure($this->Structure);
    }

Set the libraries from the config and set the structure from the config
file.

Set the libraries from the config and set the structure from the config file .


private function getLibraryInstance($libraryName, $libraryClass) {
        $instance = null;
            $libraryClassName = $this->config->get($libraryName)[$libraryClass];
            if (class_exists($libraryClassName)) {
                if (count(func_get_args()) > 2) {
                    $arguments = array_slice(func_get_args(), 2, count(func_get_args()) - 2);
                    $ref = new \ReflectionClass($libraryClassName);
                    $instance = $ref->newInstanceArgs($arguments);
                    //$instance = new $libraryClassName(array_slice(func_get_args(), 2, count(func_get_args())-2));
                } else {
                    $instance = new $libraryClassName();
                }
                return $instance;
            } else {
                throw new \InvalidArgumentException('Invalid library class(' . $libraryClassName . ')');
            }
        throw new \InvalidArgumentException('We can not instantiate the library class (' . $libraryClassName . ')');
    }

Return the instance of the library class.

@param string $libraryName
@param string $libraryClass

@throws \InvalidArgumentException

@return stdClass | null $libraryClass

Return the instance of the library class .


public function createCoreAndController(
        $class,
        \Mmf\Event\EventManagerInterface $eventManager,
        \Mmf\IO\RequestInterface $request,
        \Mmf\IO\ResponseInterface $response,
        \Mmf\View\BasicViewInterface $view,
        \Mmf\Language\LanguageInterface $language,
        \Mmf\Routing\RoutingResolverAbstract $router,
        ErrorControllerInterface $error,
        \Mmf\Parameter\SessionInterface $session,
        \Mmf\Model\ConnectionInterface $connection,
        \Mmf\Auth\AuthInterface $auth
    ) {
        $coreClass = $this->config->get('mvc')['coreClass'];

        if (class_exists($class) && class_exists($coreClass)) {
            $this->core = new $coreClass(
                $this->autoload,
                $this->config,
                $eventManager,
                $request,
                $response,
                $view,
                $language,
                $router,
                $error,
                $session,
                $connection,
                $auth
            );

            $this->controller = new $class($this->core);
            return $this->controller;
        } else {
            $className = is_object($class) ? get_class($class) : $class;
            throw new \Mmf\Core\CoreException('Is not unable to create the controller'
            . ' (' . $className . '), check if the path is correct and if '
            . 'exists the controller or if The CoreClass is correct (' . $coreClass . ')');
        }
    }

Creates the Concret controller with the constructor parameters and

@param                              $class
@param \PluginManagerInterface   $pluginManager
@param \EventManagerInterface    $eventManager
@param \RequestInterface         $request
@param \ResponseInterface        $response
@param \BasicViewInterface       $view
@param \LanguageInterface        $language
@param \RoutingResolverAbstract  $router
@param \ErrorControllerInterface $error
@param \SessionInterface         $session
@param \ConnectionInterface      $connection
@param \AuthInterface            $auth

@return mixed
@throws \CoreException