s*?=\s*?(.+?)(\s|$)/ms', $params, $matches); $paramsCompiled = []; foreach ($matches[1] as $i => $key) { $value = str_replace('"', '', $matches[2][$i]); //its php code if (self::startsWith($key, ':')) { $key = substr($key, 1); $paramsCompiled[] = '"' . $key . '"' . '=>' . $value; continue; } $paramsCompiled[] = '"' . $key . '"' . '=>' . '"' . $value . '"'; } return '[' . implode(',', $paramsCompiled) . ']'; } /** * Compile Blade statements that start with "@". * * @param string $value * * @return array|string|string[]|null */ protected function compileStatements($value) { /** * @param array $match * [0]=full expression with @ and parenthesis * [1]=expression without @ and argument * [2]=???? * [3]=argument with parenthesis and without the first @ * [4]=argument without parenthesis. * * @return mixed|string */ $callback = function($match) { if (static::contains($match[1], '@')) { // @@escaped tag $match[0] = isset($match[3]) ? $match[1] . $match[3] : $match[1]; } else { if (strpos($match[1], '::') !== false) { // Someclass::method return $this->compileStatementClass($match); } if (isset($this->customDirectivesRT[$match[1]])) { if ($this->customDirectivesRT[$match[1]]) { $match[0] = $this->compileStatementCustom($match); } else { $match[0] = \call_user_func( $this->customDirectives[$match[1]], $this->stripParentheses(static::get($match, 3)) ); } } else { $nameMethod = 'compile' . \ucfirst($match[1]); if (isset($this->methods[$nameMethod])) { return $this->methods[$nameMethod](static::get($match, 3)); } if (\method_exists($this, $nameMethod)) { // it calls the function compile return $this->$nameMethod(static::get($match, 3)); } $nameMethod = 'runtime' . \ucfirst($match[1]); $m4 = $match[4] ?? ''; if (isset($this->methods[$nameMethod])) { return $this->autoruntime($m4, $nameMethod); } if (\method_exists($this, $nameMethod)) { return $this->autoruntime($m4, $nameMethod, true); } return $match[0]; } } return isset($match[3]) ? $match[0] : $match[0] . $match[2]; }; /* return \preg_replace_callback('/\B@(@?\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value); */ return preg_replace_callback('/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value); } /** * This function generates a php code to run a runtime method. * @param string|null $expression the expression to add in the code.
* For compile, it is of the type "($a2,"222")" * For runtime, it is of the time "arg1=$a2 arg2="222"" * @param string $nameFunction The name of the function. * @param bool $compileMethod If the method is a compiled method, or it is a runtime method. * @return string */ protected function autoruntime(?string $expression, string $nameFunction, $compileMethod = false): string { $args = $this->parseArgs($expression, ' ', '=', false); $argsV = '['; foreach ($args as $k => $v) { $argsV .= "'$k'=>$v,"; } $argsV .= ']'; if ($compileMethod) { return $this->wrapPHP("\$this->$nameFunction($argsV)", '', false); } return $this->wrapPHP("\$this->methods['$nameFunction']($argsV)", '', false); } /** * Determine if a given string contains a given substring. * * @param string $haystack * @param string|array $needles * @return bool */ public static function contains($haystack, $needles): bool { foreach ((array)$needles as $needle) { if ($needle != '') { if (\function_exists('mb_strpos')) { if (\mb_strpos($haystack, $needle) !== false) { return true; } } elseif (\strpos($haystack, $needle) !== false) { return true; } } } return false; } protected function compileStatementClass($match): string { if (isset($match[3])) { return $this->phpTagEcho . $this->fixNamespaceClass($match[1]) . $match[3] . '; ?>'; } return $this->phpTagEcho . $this->fixNamespaceClass($match[1]) . '(); ?>'; } /** * Util method to fix namespace of a class
* Example: "SomeClass::method()" -> "\namespace\SomeClass::method()"
* * @param string $text * * @return string * @see BladeOne */ protected function fixNamespaceClass($text): string { if (strpos($text, '::') === false) { return $text; } $classPart = explode('::', $text, 2); if (isset($this->aliasClasses[$classPart[0]])) { $classPart[0] = $this->aliasClasses[$classPart[0]]; } return $classPart[0] . '::' . $classPart[1]; } /** * For compile custom directive at runtime. * * @param $match * @return string */ protected function compileStatementCustom($match): string { $v = $this->stripParentheses(static::get($match, 3)); $v = ($v == '') ? '' : ',' . $v; return $this->phpTag . 'call_user_func($this->customDirectives[\'' . $match[1] . '\']' . $v . '); ?>'; } /** * Get an item from an array using "dot" notation. * * @param ArrayAccess|array $array * @param string $key * @param mixed $default * @return mixed */ public static function get($array, $key, $default = null) { $accesible = \is_array($array) || $array instanceof ArrayAccess; if (!$accesible) { return static::value($default); } if (\is_null($key)) { return $array; } if (static::exists($array, $key)) { return $array[$key]; } foreach (\explode('.', $key) as $segment) { if (static::exists($array, $segment)) { $array = $array[$segment]; } else { return static::value($default); } } return $array; } /** * Determine if the given key exists in the provided array. * * @param ArrayAccess|array $array * @param string|int $key * @return bool */ public static function exists($array, $key): bool { if ($array instanceof ArrayAccess) { return $array->offsetExists($key); } return \array_key_exists($key, $array); } /** * This method removes the parenthesis of the expression and parse the arguments. * @param string $expression * @return array */ protected function getArgs($expression): array { return $this->parseArgs($this->stripParentheses($expression), ' '); } /** * It separates a string using a separator and an identifier
* It excludes quotes,double quotes and the "¬" symbol.
* **Example**
* ``` * $this->parseArgs('a=2,b='a,b,c',d'); // ['a'=>'2','b'=>'a,b,c','d'=>null] * $this->parseArgs('a=2,b=c,d'); // ['a'=>'2','b'=>'c','d'=>null] * $this->parseArgs('a=2 b=c',' '); // ['a'=>'2','b'=>'c'] * $this->parseArgs('a:2 b:c',' ',':'); // ['a'=>'2','b'=>'c'] * ``` * Note: parseArgs('a = 2 b = c',' '); with return 4 values instead of 2. * * @param string $text the text to separate * @param string $separator the separator of arguments * @param string $assigment the character used to assign a new value * @param bool $emptyKey if the argument is without value, we return it as key (true) or value (false) ? * @return array */ public function parseArgs($text, $separator = ',', $assigment = '=', $emptyKey = true): array { if ($text === null || $text === '') { return []; //nothing to convert. } $chars = $text; // str_split($text); $parts = []; $nextpart = ''; $strL = strlen($chars); $stringArr = '"\'¬'; $parenthesis = '([{'; $parenthesisClose = ')]}'; $insidePar = false; for ($i = 0; $i < $strL; $i++) { $char = $chars[$i]; // we check if the character is a parenthesis. $pp = strpos($parenthesis, $char); if ($pp !== false) { // is a parenthesis, so we mark as inside a parenthesis. $insidePar = $parenthesisClose[$pp]; } if ($char === $insidePar) { // we close the parenthesis. $insidePar = false; } if (strpos($stringArr, $char) !== false) { // if ($char === '"' || $char === "'" || $char === "¬") { // we found a string initializer $inext = strpos($text, $char, $i + 1); $inext = $inext === false ? $strL : $inext; $nextpart .= substr($text, $i, $inext - $i + 1); $i = $inext; } else { $nextpart .= $char; } if ($char === $separator && !$insidePar) { $parts[] = substr($nextpart, 0, -1); $nextpart = ''; } } if ($nextpart !== '') { $parts[] = $nextpart; } $result = []; // duct taping for key= argument (it has a space). however, it doesn't work with key =argument /* foreach ($parts as $k=>$part) { if(substr($part,-1)===$assigment && isset($parts[$k+1])) { var_dump('ok'); $parts[$k].=$parts[$k+1]; unset($parts[$k+1]); } } */ foreach ($parts as $part) { $part = trim($part); if ($part) { $char = $part[0]; if (strpos($stringArr, $char) !== false) { // if ($char === '"' || $char === "'" || $char === "¬") { if ($emptyKey) { $result[$part] = null; } else { $result[] = $part; } } else { $r = explode($assigment, $part, 2); if (count($r) === 2) { // key=value. $result[trim($r[0])] = trim($r[1]); } elseif ($emptyKey) { $result[trim($r[0])] = null; } else { $result[] = trim($r[0]); } } } } return $result; } public function parseArgsOld($text, $separator = ','): array { if ($text === null || $text === '') { return []; //nothing to convert. } $chars = str_split($text); $parts = []; $nextpart = ''; $strL = count($chars); /** @noinspection ForeachInvariantsInspection */ for ($i = 0; $i < $strL; $i++) { $char = $chars[$i]; if ($char === '"' || $char === "'") { $inext = strpos($text, $char, $i + 1); $inext = $inext === false ? $strL : $inext; $nextpart .= substr($text, $i, $inext - $i + 1); $i = $inext; } else { $nextpart .= $char; } if ($char === $separator) { $parts[] = substr($nextpart, 0, -1); $nextpart = ''; } } if ($nextpart !== '') { $parts[] = $nextpart; } $result = []; foreach ($parts as $part) { $r = explode('=', $part, 2); $result[trim($r[0])] = count($r) === 2 ? trim($r[1]) : null; } return $result; } /** * Compile the "raw" echo statements. * * @param string $value * @return string */ protected function compileRawEchos($value): string { $pattern = \sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->rawTags[0], $this->rawTags[1]); $callback = function($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3] . $matches[3]; return $matches[1] ? \substr( $matches[0], 1 ) : $this->phpTagEcho . $this->compileEchoDefaults($matches[2]) . '; ?>' . $whitespace; }; return \preg_replace_callback($pattern, $callback, $value); } /** * Compile the default values for the echo statement. * Example: * {{ $test or 'test2' }} compiles to {{ isset($test) ? $test : 'test2' }} * * @param string $value * @return string */ protected function compileEchoDefaults($value): string { // Source: https://www.php.net/manual/en/language.variables.basics.php $patternPHPVariableName = '\$[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*'; $result = \preg_replace('/^(' . $patternPHPVariableName . ')\s+or\s+(.+?)$/s', 'isset($1) ? $1 : $2', $value); if (!$this->pipeEnable) { return $this->fixNamespaceClass($result); } return $this->pipeDream($this->fixNamespaceClass($result)); } /** * It converts a string separated by pipes | into a filtered expression.
* If the method exists (as directive), then it is used
* If the method exists (in this class) then it is used
* Otherwise, it uses a global function.
* If you want to escape the "|", then you could use "/|"
* **Note:** It only works if $this->pipeEnable=true and by default it is false
* **Example:**
* ``` * $this->pipeDream('$name | strtolower | substr:0,4'); // strtolower(substr($name ,0,4) * $this->pipeDream('$name| getMode') // $this->getMode($name) * ``` * * @param string $result * @return string * @\eftec\bladeone\BladeOne::$pipeEnable */ protected function pipeDream($result): string { $array = preg_split('~\\\\.(*SKIP)(*FAIL)|\|~s', $result); $c = count($array) - 1; // base zero. if ($c === 0) { return $result; } $prev = ''; for ($i = 1; $i <= $c; $i++) { $r = @explode(':', $array[$i], 2); $fnName = trim($r[0]); $fnNameF = $fnName[0]; // first character if ($fnNameF === '"' || $fnNameF === '\'' || $fnNameF === '$' || is_numeric($fnNameF)) { $fnName = '!isset(' . $array[0] . ') ? ' . $fnName . ' : '; } elseif (isset($this->customDirectives[$fnName])) { $fnName = '$this->customDirectives[\'' . $fnName . '\']'; } elseif (method_exists($this, $fnName)) { $fnName = '$this->' . $fnName; } $hasArgument = count($r) === 2; if ($i === 1) { $prev = $fnName . '(' . $array[0]; if ($hasArgument) { $prev .= ',' . $r[1]; } $prev .= ')'; } else { $prev = $fnName . '(' . $prev; if ($hasArgument) { $prev .= ',' . $r[1] . ')'; } else { $prev .= ')'; } } } return $prev; } /** * Compile the "regular" echo statements. {{ }} * * @param string $value * @return string */ protected function compileRegularEchos($value): string { $pattern = \sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->contentTags[0], $this->contentTags[1]); $callback = function($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3] . $matches[3]; $wrapped = \sprintf($this->echoFormat, $this->compileEchoDefaults($matches[2])); return $matches[1] ? \substr($matches[0], 1) : $this->phpTagEcho . $wrapped . '; ?>' . $whitespace; }; return \preg_replace_callback($pattern, $callback, $value); } /** * Compile the escaped echo statements. {!! !!} * * @param string $value * @return string */ protected function compileEscapedEchos($value): string { $pattern = \sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->escapedTags[0], $this->escapedTags[1]); $callback = function($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3] . $matches[3]; return $matches[1] ? $matches[0] : $this->phpTag . \sprintf($this->echoFormat, $this->compileEchoDefaults($matches[2])) . '; ?>' . $whitespace; //return $matches[1] ? $matches[0] : $this->phpTag // . 'echo static::e(' . $this->compileEchoDefaults($matches[2]) . '); ? >' . $whitespace; }; return \preg_replace_callback($pattern, $callback, $value); } /** * Compile the "@each" tag into valid PHP. * * @param string $expression * @return string */ protected function compileEach($expression): string { return $this->phpTagEcho . "\$this->renderEach$expression; ?>"; } protected function compileSet($expression): string { //$segments = \explode('=', \preg_replace("/[()\\\']/", '', $expression)); $segments = \explode('=', $this->stripParentheses($expression)); $value = (\count($segments) >= 2) ? '=@' . implode('=', array_slice($segments, 1)) : '++'; return $this->phpTag . \trim($segments[0]) . $value . ';?>'; } /** * Compile the yield statements into valid PHP. * * @param string $expression * @return string */ protected function compileYield($expression): string { return $this->phpTagEcho . "\$this->yieldContent$expression; ?>"; } /** * Compile the show statements into valid PHP. * * @return string */ protected function compileShow(): string { return $this->phpTagEcho . '$this->yieldSection(); ?>'; } /** * Compile the section statements into valid PHP. * * @param string $expression * @return string */ protected function compileSection($expression): string { return $this->phpTag . "\$this->startSection$expression; ?>"; } /** * Compile the append statements into valid PHP. * * @return string */ protected function compileAppend(): string { return $this->phpTag . '$this->appendSection(); ?>'; } /** * Compile the auth statements into valid PHP. * * @param string $expression * @return string */ protected function compileAuth($expression = ''): string { $role = $this->stripParentheses($expression); if ($role == '') { return $this->phpTag . 'if(isset($this->currentUser)): ?>'; } return $this->phpTag . "if(isset(\$this->currentUser) && \$this->currentRole==$role): ?>"; } /** * Compile the elseauth statements into valid PHP. * * @param string $expression * @return string */ protected function compileElseAuth($expression = ''): string { $role = $this->stripParentheses($expression); if ($role == '') { return $this->phpTag . 'else: ?>'; } return $this->phpTag . "elseif(isset(\$this->currentUser) && \$this->currentRole==$role): ?>"; } /** * Compile the end-auth statements into valid PHP. * * @return string */ protected function compileEndAuth(): string { return $this->phpTag . 'endif; ?>'; } protected function compileCan($expression): string { $v = $this->stripParentheses($expression); return $this->phpTag . 'if (call_user_func($this->authCallBack,' . $v . ')): ?>'; } /** * Compile the else statements into valid PHP. * * @param string $expression * @return string */ protected function compileElseCan($expression = ''): string { $v = $this->stripParentheses($expression); if ($v) { return $this->phpTag . 'elseif (call_user_func($this->authCallBack,' . $v . ')): ?>'; } return $this->phpTag . 'else: ?>'; } // // protected function compileCannot($expression): string { $v = $this->stripParentheses($expression); return $this->phpTag . 'if (!call_user_func($this->authCallBack,' . $v . ')): ?>'; } /** * Compile the elsecannot statements into valid PHP. * * @param string $expression * @return string */ protected function compileElseCannot($expression = ''): string { $v = $this->stripParentheses($expression); if ($v) { return $this->phpTag . 'elseif (!call_user_func($this->authCallBack,' . $v . ')): ?>'; } return $this->phpTag . 'else: ?>'; } /** * Compile the canany statements into valid PHP. * canany(['edit','write']) * * @param $expression * @return string */ protected function compileCanAny($expression): string { $role = $this->stripParentheses($expression); return $this->phpTag . 'if (call_user_func($this->authAnyCallBack,' . $role . ')): ?>'; } /** * Compile the else statements into valid PHP. * * @param $expression * @return string */ protected function compileElseCanAny($expression): string { $role = $this->stripParentheses($expression); if ($role == '') { return $this->phpTag . 'else: ?>'; } return $this->phpTag . 'elseif (call_user_func($this->authAnyCallBack,' . $role . ')): ?>'; } /** * Compile the guest statements into valid PHP. * * @param null $expression * @return string */ protected function compileGuest($expression = null): string { if ($expression === null) { return $this->phpTag . 'if(!isset($this->currentUser)): ?>'; } $role = $this->stripParentheses($expression); if ($role == '') { return $this->phpTag . 'if(!isset($this->currentUser)): ?>'; } return $this->phpTag . "if(!isset(\$this->currentUser) || \$this->currentRole!=$role): ?>"; } /** * Compile the else statements into valid PHP. * * @param $expression * @return string */ protected function compileElseGuest($expression): string { $role = $this->stripParentheses($expression); if ($role == '') { return $this->phpTag . 'else: ?>'; } return $this->phpTag . "elseif(!isset(\$this->currentUser) || \$this->currentRole!=$role): ?>"; } /** * /** * Compile the end-auth statements into valid PHP. * * @return string */ protected function compileEndGuest(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the end-section statements into valid PHP. * * @return string */ protected function compileEndsection(): string { return $this->phpTag . '$this->stopSection(); ?>'; } /** * Compile the stop statements into valid PHP. * * @return string */ protected function compileStop(): string { return $this->phpTag . '$this->stopSection(); ?>'; } /** * Compile the overwrite statements into valid PHP. * * @return string */ protected function compileOverwrite(): string { return $this->phpTag . '$this->stopSection(true); ?>'; } /** * Compile the unless statements into valid PHP. * * @param string $expression * @return string */ protected function compileUnless($expression): string { return $this->phpTag . "if ( ! $expression): ?>"; } /** * Compile the User statements into valid PHP. * * @return string */ protected function compileUser(): string { return $this->phpTagEcho . "'" . $this->currentUser . "'; ?>"; } /** * Compile the endunless statements into valid PHP. * * @return string */ protected function compileEndunless(): string { return $this->phpTag . 'endif; ?>'; } // // /** * @error('key') * * @param $expression * @return string */ protected function compileError($expression): string { $key = $this->stripParentheses($expression); return $this->phpTag . '$message = call_user_func($this->errorCallBack,' . $key . '); if ($message): ?>'; } /** * Compile the end-error statements into valid PHP. * * @return string */ protected function compileEndError(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the else statements into valid PHP. * * @return string */ protected function compileElse(): string { return $this->phpTag . 'else: ?>'; } /** * Compile the for statements into valid PHP. * * @param string $expression * @return string */ protected function compileFor($expression): string { return $this->phpTag . "for$expression: ?>"; } // // /** * Compile the foreach statements into valid PHP. * * @param string $expression * @return string */ protected function compileForeach($expression): string { //\preg_match('/\( *(.*) * as *([^\)]*)/', $expression, $matches); if ($expression === null) { return '@foreach'; } \preg_match('/\( *(.*) * as *([^)]*)/', $expression, $matches); $iteratee = \trim($matches[1]); $iteration = \trim($matches[2]); $initLoop = "\$__currentLoopData = $iteratee; \$this->addLoop(\$__currentLoopData);\$this->getFirstLoop();\n"; $iterateLoop = '$loop = $this->incrementLoopIndices(); '; return $this->phpTag . "$initLoop foreach(\$__currentLoopData as $iteration): $iterateLoop ?>"; } /** * Compile a split of a foreach cycle. Used for example when we want to separate limites each "n" elements. * * @param string $expression * @return string */ protected function compileSplitForeach($expression): string { return $this->phpTagEcho . '$this::splitForeach' . $expression . '; ?>'; } /** * Compile the break statements into valid PHP. * * @param string $expression * @return string */ protected function compileBreak($expression): string { return $expression ? $this->phpTag . "if$expression break; ?>" : $this->phpTag . 'break; ?>'; } /** * Compile the continue statements into valid PHP. * * @param string $expression * @return string */ protected function compileContinue($expression): string { return $expression ? $this->phpTag . "if$expression continue; ?>" : $this->phpTag . 'continue; ?>'; } /** * Compile the forelse statements into valid PHP. * * @param string $expression * @return string */ protected function compileForelse($expression): string { $empty = '$__empty_' . ++$this->forelseCounter; return $this->phpTag . "$empty = true; foreach$expression: $empty = false; ?>"; } /** * Compile the if statements into valid PHP. * * @param string $expression * @return string */ protected function compileIf($expression): string { return $this->phpTag . "if$expression: ?>"; } // // /** * Compile the else-if statements into valid PHP. * * @param string $expression * @return string */ protected function compileElseif($expression): string { return $this->phpTag . "elseif$expression: ?>"; } /** * Compile the forelse statements into valid PHP. * * @param string $expression empty if it's inside a for loop. * @return string */ protected function compileEmpty($expression = ''): string { if ($expression == '') { $empty = '$__empty_' . $this->forelseCounter--; return $this->phpTag . "endforeach; if ($empty): ?>"; } return $this->phpTag . "if (empty$expression): ?>"; } /** * Compile the has section statements into valid PHP. * * @param string $expression * @return string */ protected function compileHasSection($expression): string { return $this->phpTag . "if (! empty(trim(\$this->yieldContent$expression))): ?>"; } /** * Compile the end-while statements into valid PHP. * * @return string */ protected function compileEndwhile(): string { return $this->phpTag . 'endwhile; ?>'; } /** * Compile the end-for statements into valid PHP. * * @return string */ protected function compileEndfor(): string { return $this->phpTag . 'endfor; ?>'; } /** * Compile the end-for-each statements into valid PHP. * * @return string */ protected function compileEndforeach(): string { return $this->phpTag . 'endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>'; } /** * Compile the end-can statements into valid PHP. * * @return string */ protected function compileEndcan(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the end-can statements into valid PHP. * * @return string */ protected function compileEndcanany(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the end-cannot statements into valid PHP. * * @return string */ protected function compileEndcannot(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the end-if statements into valid PHP. * * @return string */ protected function compileEndif(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the end-for-else statements into valid PHP. * * @return string */ protected function compileEndforelse(): string { return $this->phpTag . 'endif; ?>'; } /** * Compile the raw PHP statements into valid PHP. * * @param string $expression * @return string */ protected function compilePhp($expression): string { return $expression ? $this->phpTag . "$expression; ?>" : $this->phpTag; } // /** * Compile end-php statement into valid PHP. * * @return string */ protected function compileEndphp(): string { return ' ?>'; } /** * Compile the unset statements into valid PHP. * * @param string $expression * @return string */ protected function compileUnset($expression): string { return $this->phpTag . "unset$expression; ?>"; } /** * Compile the extends statements into valid PHP. * * @param string $expression * @return string */ protected function compileExtends($expression): string { $expression = $this->stripParentheses($expression); // $_shouldextend avoids to runchild if it's not evaluated. // For example @if(something) @extends('aaa.bb') @endif() // If something is false then it's not rendered at the end (footer) of the script. $this->uidCounter++; $data = $this->phpTag . 'if (isset($_shouldextend[' . $this->uidCounter . '])) { echo $this->runChild(' . $expression . '); } ?>'; $this->footer[] = $data; return $this->phpTag . '$_shouldextend[' . $this->uidCounter . ']=1; ?>'; } /** * Execute the @parent command. This operation works in tandem with extendSection * * @return string * @see extendSection */ protected function compileParent(): string { return $this->PARENTKEY; } /** * Compile the include statements into valid PHP. * * @param string $expression * @return string */ protected function compileInclude($expression): string { $expression = $this->stripParentheses($expression); return $this->phpTagEcho . '$this->runChild(' . $expression . '); ?>'; } /** * It loads a compiled template and paste inside the code.
* It uses more disk space, but it decreases the number of includes
* * @param $expression * @return string * @throws Exception */ protected function compileIncludeFast($expression): string { $expression = $this->stripParentheses($expression); $ex = $this->stripParentheses($expression); $exp = \explode(',', $ex); $file = $this->stripQuotes($exp[0] ?? null); $fileC = $this->getCompiledFile($file); if (!@\is_file($fileC)) { // if the file doesn't exist then it's created $this->compile($file, true); } return $this->getFile($fileC); } /** * Compile the include statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeIf($expression): string { return $this->phpTag . 'if ($this->templateExist' . $expression . ') echo $this->runChild' . $expression . '; ?>'; } /** * Compile the include statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeWhen($expression): string { $expression = $this->stripParentheses($expression); return $this->phpTagEcho . '$this->includeWhen(' . $expression . '); ?>'; } /** * Compile the includefirst statement * * @param string $expression * @return string */ protected function compileIncludeFirst($expression): string { $expression = $this->stripParentheses($expression); return $this->phpTagEcho . '$this->includeFirst(' . $expression . '); ?>'; } /** * Compile the {@}compilestamp statement. * * @param string $expression * * @return false|string */ protected function compileCompileStamp($expression) { $expression = $this->stripQuotes($this->stripParentheses($expression)); $expression = ($expression === '') ? 'Y-m-d H:i:s' : $expression; return date($expression); } /** * compile the {@}viewname statement
* {@}viewname('compiled') returns the full compiled path * {@}viewname('template') returns the full template path * {@}viewname('') returns the view name. * * @param mixed $expression * * @return string */ protected function compileViewName($expression): string { $expression = $this->stripQuotes($this->stripParentheses($expression)); switch ($expression) { case 'compiled': return $this->getCompiledFile($this->fileName); case 'template': return $this->getTemplateFile($this->fileName); default: return $this->fileName; } } /** * Compile the stack statements into the content. * * @param string $expression * @return string * @see BladeOne::yieldPushContent */ protected function compileStack($expression): string { return $this->phpTagEcho . " \$this->CompileStackFinal$expression; ?>"; } public function CompileStackFinal($a = null, $b = null): string { return $this->escapeStack0 . $a . ',' . $b . $this->escapeStack1; } /** * Compile the endpush statements into valid PHP. * * @return string */ protected function compileEndpush(): string { return $this->phpTag . '$this->stopPush(); ?>'; } /** * Compile the endpushonce statements into valid PHP. * * @return string */ protected function compileEndpushOnce(): string { return $this->phpTag . '$this->stopPush(); endif; ?>'; } /** * Compile the endpush statements into valid PHP. * * @return string */ protected function compileEndPrepend(): string { return $this->phpTag . '$this->stopPrepend(); ?>'; } /** * Compile the component statements into valid PHP. * * @param string $expression * @return string */ protected function compileComponent($expression): string { return $this->phpTag . " \$this->startComponent$expression; ?>"; } /** * Compile the end-component statements into valid PHP. * * @return string */ protected function compileEndComponent(): string { return $this->phpTagEcho . '$this->renderComponent(); ?>'; } /** * Compile the slot statements into valid PHP. * * @param string $expression * @return string */ protected function compileSlot($expression): string { return $this->phpTag . " \$this->slot$expression; ?>"; } /** * Compile the end-slot statements into valid PHP. * * @return string */ protected function compileEndSlot(): string { return $this->phpTag . ' $this->endSlot(); ?>'; } protected function compileAsset($expression): string { return $this->phpTagEcho . "(isset(\$this->assetDict[$expression]))?\$this->assetDict[$expression]:\$this->baseUrl.'/'.$expression; ?>"; } protected function compileAssetCDN($expression): string { return $this->phpTagEcho . "(isset(\$this->assetDictCDN[$expression]))?\$this->assetDictCDN[$expression]:\$this->cdnUrl.'/'.$expression; ?>"; } protected function compileJSon($expression): string { $parts = \explode(',', $this->stripParentheses($expression)); $options = isset($parts[1]) ? \trim($parts[1]) : JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT; $depth = isset($parts[2]) ? \trim($parts[2]) : 512; return $this->phpTagEcho . "json_encode($parts[0], $options, $depth); ?>"; } //
// /** * Compile the checked statements into valid PHP. * * @param string $expression * @return string */ protected function compileChecked($expression): string { return $this->phpTag . "if$expression echo 'checked'; ?>"; } protected function compileStyle($expression): string { return $this->phpTag . "echo 'class=\"'.\$this->runtimeStyle($expression).'\"' ?>"; } protected function compileClass($expression): string { return $this->phpTag . "echo 'class=\"'.\$this->runtimeStyle($expression).'\"'; ?>"; } protected function runtimeStyle($expression = null, $separator = ' '): string { if ($expression === null) { return ''; } if (!is_array($expression)) { $expression = [$expression]; } $result = ''; foreach ($expression as $k => $v) { if (is_numeric($k)) { $result .= $v . $separator; } elseif ($v) { $result .= $k . $separator; } } return trim($result); } /** * Compile the selected statements into valid PHP. * * @param string $expression * @return string */ protected function compileSelected($expression): string { return $this->phpTag . "if$expression echo 'selected'; ?>"; } /** * Compile the disabled statements into valid PHP. * * @param string $expression * @return string */ protected function compileDisabled($expression): string { return $this->phpTag . "if$expression echo 'disabled'; ?>"; } /** * Compile the readonly statements into valid PHP. * * @param string $expression * @return string */ protected function compileReadonly($expression): string { return $this->phpTag . "if$expression echo 'readonly'; ?>"; } /** * Compile the required statements into valid PHP. * * @param string $expression * @return string */ protected function compileRequired($expression): string { return $this->phpTag . "if$expression echo 'required'; ?>"; } // // protected function compileIsset($expression): string { return $this->phpTag . "if(isset$expression): ?>"; } protected function compileEndIsset(): string { return $this->phpTag . 'endif; ?>'; } protected function compileEndEmpty(): string { return $this->phpTag . 'endif; ?>'; } // /** * Resolve a given class using the injectResolver callable. * * @param string $className * @param string|null $variableName * @return mixed */ protected function injectClass($className, $variableName = null) { if (isset($this->injectResolver)) { return call_user_func($this->injectResolver, $className, $variableName); } $fullClassName = $className . "\\" . $variableName; return new $fullClassName(); } /** * Used for @_e directive. * * @param $expression * * @return string */ protected function compile_e($expression): string { return $this->phpTagEcho . "\$this->_e$expression; ?>"; } /** * Used for @_ef directive. * * @param $expression * * @return string */ protected function compile_ef($expression): string { return $this->phpTagEcho . "\$this->_ef$expression; ?>"; } // /** * Used for @_n directive. * * @param $expression * * @return string */ protected function compile_n($expression): string { return $this->phpTagEcho . "\$this->_n$expression; ?>"; } // // public static function isCli(): bool { return !http_response_code(); } /** * @param $key * @param string $default is the defalut value is the parameter is set * without value. * @param bool $set it is the value returned when the argument is set but there is no value assigned * @return string */ public static function getParameterCli($key, $default = '', $set = true) { global $argv; $p = array_search('-' . $key, $argv, true); if ($p === false) { return $default; } if (isset($argv[$p + 1])) { return self::removeTrailSlash($argv[$p + 1]); } return $set; } protected static function removeTrailSlash($txt): string { return rtrim($txt, '/\\'); } /** * @param string $str * @param string $type =['i','e','s','w'][$i] * @return string */ public static function colorLog($str, $type = 'i'): string { switch ($type) { case 'e': //error return "\033[31m$str\033[0m"; case 's': //success return "\033[32m$str\033[0m"; case 'w': //warning return "\033[33m$str\033[0m"; case 'i': //info return "\033[36m$str\033[0m"; case 'b': return "\e[01m$str\e[22m"; default: return $str; } } public function checkHealthPath(): bool { echo self::colorLog("Checking Health\n"); $status = true; if (is_dir($this->compiledPath)) { echo "Compile-path [$this->compiledPath] is a folder " . self::colorLog("OK") . "\n"; } else { $status = false; echo "Compile-path [$this->compiledPath] is not a folder " . self::colorLog("ERROR", 'e') . "\n"; } foreach ($this->templatePath as $t) { if (is_dir($t)) { echo "Template-path (view) [$t] is a folder " . self::colorLog("OK") . "\n"; } else { $status = false; echo "Template-path (view) [$t] is not a folder " . self::colorLog("ERROR", 'e') . "\n"; } } $error = self::colorLog('OK'); try { /** @noinspection RandomApiMigrationInspection */ $rnd = $this->compiledPath . '/dummy' . rand(10000, 900009); $f = @file_put_contents($rnd, 'dummy'); if ($f === false) { $status = false; $error = self::colorLog("Unable to create file [" . $this->compiledPath . '/dummy]', 'e'); } @unlink($rnd); } catch (\Throwable $ex) { $status = false; $error = self::colorLog($ex->getMessage(), 'e'); } echo "Testing write in the compile folder [$rnd] $error\n"; $files = @glob($this->templatePath[0] . '/*'); echo "Testing reading in the view folder [" . $this->templatePath[0] . "].\n"; echo "View(s) found :" . count($files) . "\n"; return $status; } public function createFolders(): void { echo self::colorLog("Creating Folder\n"); echo "Creating compile folder[" . self::colorLog($this->compiledPath, 'b') . "] "; if (!\is_dir($this->compiledPath)) { $ok = @\mkdir($this->compiledPath, 0770, true); if ($ok === false) { echo self::colorLog("Error: Unable to create folder, check the permissions\n", 'e'); } else { echo self::colorLog("OK\n"); } } else { echo self::colorLog("Note: folder already exist.\n", 'w'); } foreach ($this->templatePath as $t) { echo "Creating template folder [" . self::colorLog($t, 'b') . "] "; if (!\is_dir($t)) { $ok = @\mkdir($t, 0770, true); if ($ok === false) { echo self::colorLog("Error: Unable to create folder, check the permissions\n", 'e'); } else { echo self::colorLog("OK\n"); } } else { echo self::colorLog("Note: folder already exist.\n", 'w'); } } } public function clearcompile(): int { echo self::colorLog("Clearing Compile Folder\n"); $files = glob($this->compiledPath . '/*'); // get all file names $count = 0; foreach ($files as $file) { // iterate files if (is_file($file)) { $count++; echo "deleting [$file] "; $r = @unlink($file); // delete file if ($r) { echo self::colorLog("OK\n"); } else { echo self::colorLog("ERROR\n", 'e'); } } } echo "Files deleted $count\n"; return $count; } public function cliEngine(): void { $clearcompile = self::getParameterCli('clearcompile'); $createfolder = self::getParameterCli('createfolder'); $check = self::getParameterCli('check'); echo ' ____ _ _ ____ ' . "\n"; echo ' | _ \| | | | / __ \ ' . "\n"; echo ' | |_) | | __ _ __| | ___| | | |_ __ ___ ' . "\n"; echo ' | _ <| |/ _` |/ _` |/ _ \ | | | \'_ \ / _ \\' . "\n"; echo ' | |_) | | (_| | (_| | __/ |__| | | | | __/' . "\n"; echo ' |____/|_|\__,_|\__,_|\___|\____/|_| |_|\___|' . " V." . self::VERSION . "\n\n"; echo "\n"; $done = false; if ($check) { $done = true; $this->checkHealthPath(); } if ($clearcompile) { $done = true; $this->clearcompile(); } if ($createfolder) { $done = true; $this->createFolders(); } if (!$done) { echo " Syntax:\n"; echo " " . self::colorLog("-templatepath", "b") . " (optional) the template-path (view path).\n"; echo " Default value: 'views'\n"; echo " Example: 'php /vendor/bin/bladeonecli /folder/views' (absolute)\n"; echo " Example: 'php /vendor/bin/bladeonecli folder/view1' (relative)\n"; echo " " . self::colorLog("-compilepath", "b") . " (optional) the compile-path.\n"; echo " Default value: 'compiles'\n"; echo " Example: 'php /vendor/bin/bladeonecli /folder/compiles' (absolute)\n"; echo " Example: 'php /vendor/bin/bladeonecli compiles' (relative)\n"; echo " " . self::colorLog("-createfolder", "b") . " it creates the folders if they don't exist.\n"; echo " Example: php ./vendor/bin/bladeonecli -createfolder\n"; echo " " . self::colorLog("-clearcompile", "b") . " It deletes the content of the compile path\n"; echo " " . self::colorLog("-check", "b") . " It checks the folders and permissions\n"; } } public static function isAbsolutePath($path): bool { if (!$path) { return true; } if (DIRECTORY_SEPARATOR === '/') { // linux and macos return $path[0] === '/'; } return $path[1] === ':'; } // } if (!function_exists("array_key_last")) { function array_key_last($array) { if (!is_array($array) || empty($array)) { return NULL; } return array_keys($array)[count($array) - 1]; } }