From 977ad13577c7df0dae18ebb10cd1b4a73e04ee86 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 11:49:07 +0300 Subject: [PATCH 01/21] Generated .editorconfig file --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b9c127d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false \ No newline at end of file From 1eb93ca8d5339d2583fe2bdf53d9ddb0827629a2 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 11:51:21 +0300 Subject: [PATCH 02/21] Fixed issue #7: Error: @forelse with keys failed to return @empty --- src/Methods/Forelse/ForelseMethod.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Methods/Forelse/ForelseMethod.php b/src/Methods/Forelse/ForelseMethod.php index 631ccb6..84837bf 100644 --- a/src/Methods/Forelse/ForelseMethod.php +++ b/src/Methods/Forelse/ForelseMethod.php @@ -12,9 +12,7 @@ class ForelseMethod extends Method */ public function toPhpCode(?string $parameters = null): string { - $matches = []; - preg_match('/\$\w+/m', $parameters ?? '', $matches); - $v = $matches[0]; + $v = explode(' as ', $parameters)[0]; $code = " Date: Mon, 29 Jul 2024 13:38:53 +0300 Subject: [PATCH 03/21] Fixed issue #8: prepared ability to combine both conditional and static HTML elements classes --- src/Methods/ClassMethod.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Methods/ClassMethod.php b/src/Methods/ClassMethod.php index 92ac139..a1212da 100644 --- a/src/Methods/ClassMethod.php +++ b/src/Methods/ClassMethod.php @@ -12,7 +12,8 @@ public function toPhpCode(?string $parameters = null): string { $code = 'class=" \$__ccheck) {"; - $code .= 'if ($__ccheck) echo $__cclassname, \' \'; '; + $code .= 'if (is_bool($__ccheck) and $__ccheck) { echo $__cclassname, \' \'; } '; + $code .= 'else if (is_numeric($__cclassname)) { echo $__ccheck, \' \'; } '; $code .= '} ?>"'; return $code; } From 04a2c42238b832f6e096fa0010700cef6a34445c Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 15:05:49 +0300 Subject: [PATCH 04/21] Fixed issue #16: set default namespace for components '\' if not set. For now, no need to write \ at the start and end of the namespace. Example: (App\Component) instead of (\App\Component\). --- src/ComponentConverter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ComponentConverter.php b/src/ComponentConverter.php index 7232bd7..4874ba8 100644 --- a/src/ComponentConverter.php +++ b/src/ComponentConverter.php @@ -155,7 +155,7 @@ private function getComponentClass(string $componentTagName): ?string { $pieces = explode('.', substr($componentTagName, 2)); $className = $this->dashToUpperCamelCase(array_pop($pieces)); - $namespace = $this->namespacesMap['default']; + $namespace = $this->namespacesMap['default'] ?? ''; if (!empty($pieces)) { do { @@ -170,6 +170,6 @@ private function getComponentClass(string $componentTagName): ?string } while(!empty($pieces)); } - return !empty($namespace) ? "\\$namespace\\$className" : "\\$className"; + return !empty($namespace) ? "\\{$namespace}\\{$className}" : "\\{$className}"; } } From 9962928488b36625705ad3c531b7f74fa17ab940 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 20:40:05 +0300 Subject: [PATCH 05/21] Fixed issue #10: it's been solved by introducing a way to customize extension for each component's view. See related issue comment. --- src/Component.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Component.php b/src/Component.php index b1fa7cf..24788f3 100644 --- a/src/Component.php +++ b/src/Component.php @@ -75,12 +75,13 @@ abstract public function render(): void; * * @return void */ - protected function view(string $file, array $data = []): void + protected function view(string $file, array $data = [], $extension = null): void { $data = $data + get_object_vars($this) + [ 'contents' => $this->getContents(), 'attributes' => $this->getAttributes(), ]; + $extension ??= $this->extension; $oldExt = Crow::getExtension(); Crow::setExtension($this->extension); From 81603dab255b60a1d71980e19054f05afe04b830 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 20:52:51 +0300 Subject: [PATCH 06/21] Fixed issue #17: introduced trimmed custom extension for a cleaner referring. See issue #17 comment for more info. --- src/FileLoader.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/FileLoader.php b/src/FileLoader.php index b57381e..4f23e2f 100644 --- a/src/FileLoader.php +++ b/src/FileLoader.php @@ -83,9 +83,11 @@ public function setExtension(?string $extension): FileLoader */ private function getFilePath(string $file, string $path = null) { - $path = $path ?? $this->defaultPath ?? ''; + $path ??= $this->defaultPath ?? ''; $extension = $this->extension ?? ''; + $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; + $extension = str_ends_with($extension, '.php') ? rtrim($extension, '.php') : $extension; - return "$path/{$file}{$extension}"; + return "{$path}/{$file}.{$extension}.php"; } } From 54ae6e9f117e8d4a6fffde33e77e6b48187cb17b Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 29 Jul 2024 23:21:27 +0300 Subject: [PATCH 07/21] linted all files --- .editorconfig | 2 +- src/CodeConverter.php | 199 ++++--- src/Component.php | 141 +++-- src/ComponentConverter.php | 296 +++++----- src/Crow.php | 669 +++++++++++------------ src/FileLoader.php | 141 +++-- src/Method.php | 19 +- src/Methods/BreakMethod.php | 16 +- src/Methods/CheckedMethod.php | 16 +- src/Methods/ClassMethod.php | 26 +- src/Methods/ContinueMethod.php | 16 +- src/Methods/DisabledMethod.php | 16 +- src/Methods/Empty/EmptyMethod.php | 26 +- src/Methods/Empty/EndEmptyMethod.php | 16 +- src/Methods/ExtendsMethod.php | 20 +- src/Methods/For/EndForMethod.php | 16 +- src/Methods/For/ForMethod.php | 16 +- src/Methods/Foreach/EndForeachMethod.php | 16 +- src/Methods/Foreach/ForeachMethod.php | 16 +- src/Methods/Forelse/EndforelseMethod.php | 16 +- src/Methods/Forelse/ForelseMethod.php | 26 +- src/Methods/If/ElseIfMethod.php | 16 +- src/Methods/If/ElseMethod.php | 16 +- src/Methods/If/EndIfMethod.php | 16 +- src/Methods/If/IfMethod.php | 16 +- src/Methods/IncludeMethod.php | 18 +- src/Methods/Isset/EndIssetMethod.php | 16 +- src/Methods/Isset/IssetMethod.php | 16 +- src/Methods/Php/EndPhpMethod.php | 16 +- src/Methods/Php/PhpMethod.php | 16 +- src/Methods/ReadonlyMethod.php | 16 +- src/Methods/Section/EndSectionMethod.php | 16 +- src/Methods/Section/SectionMethod.php | 53 +- src/Methods/SelectedMethod.php | 16 +- src/Methods/Switch/CaseMethod.php | 16 +- src/Methods/Switch/DefaultMethod.php | 16 +- src/Methods/Switch/EndSwitchMethod.php | 16 +- src/Methods/Switch/SwitchMethod.php | 16 +- src/Methods/Unless/EndUnlessMethod.php | 16 +- src/Methods/Unless/UnlessMethod.php | 16 +- src/Methods/While/EndWhileMethod.php | 16 +- src/Methods/While/WhileMethod.php | 16 +- src/Methods/YieldMethod.php | 16 +- src/SectionsManager.php | 47 +- src/Traits/SelfCreate.php | 20 +- 45 files changed, 1025 insertions(+), 1158 deletions(-) diff --git a/.editorconfig b/.editorconfig index b9c127d..88bf97c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,7 +5,7 @@ root = true [*] indent_style = space -indent_size = 4 +indent_size = 2 end_of_line = crlf charset = utf-8 trim_trailing_whitespace = false diff --git a/src/CodeConverter.php b/src/CodeConverter.php index 2be865a..f49d1bb 100644 --- a/src/CodeConverter.php +++ b/src/CodeConverter.php @@ -2,117 +2,112 @@ namespace Corviz\Crow; -final class CodeConverter -{ - /** - * @var array - */ - private array $methods = []; - - /** - * @param string $templateCode - * - * @return string - */ - public function toPhp(string $templateCode): string - { - while($this->convertMethods($templateCode, 'extends|include')); - while($this->convertMethods($templateCode)); - $this->convertComments($templateCode); - $this->convertEscaped($templateCode); - $this->convertUnescaped($templateCode); - - return $templateCode; - } +final class CodeConverter { + /** + * @var array + */ + private array $methods = []; - /** - * @param string $method - * @param string $class - * - * @return void - */ - public function addMethod(string $method, string $class): void - { - $this->methods[$method] = ['c' => $class, 'i' => null]; - } + /** + * @param string $templateCode + * + * @return string + */ + public function toPhp(string $templateCode): string { + while ($this->convertMethods($templateCode, 'extends|include')); + while ($this->convertMethods($templateCode)); + $this->convertComments($templateCode); + $this->convertEscaped($templateCode); + $this->convertUnescaped($templateCode); - /** - * @param string $templateCode - * - * @return void - */ - private function convertEscaped(string &$templateCode): void - { - $templateCode = preg_replace( - '/{{(.*?)}}/', - '', - $templateCode - ); - } + return $templateCode; + } - /** - * @param string $templateCode - * @return void - */ - private function convertUnescaped(string &$templateCode): void - { - $templateCode = preg_replace( - '/{!!(.*?)!!}/', - '', - $templateCode - ); - } + /** + * @param string $method + * @param string $class + * + * @return void + */ + public function addMethod(string $method, string $class): void { + $this->methods[$method] = ['c' => $class, 'i' => null]; + } - /** - * @param string $templateCode - * @return void - */ - private function convertComments(string &$templateCode): void - { - $templateCode = preg_replace( - '/{{--(.*?)--}}/', - '', - $templateCode - ); - } + /** + * @param string $templateCode + * + * @return void + */ + private function convertEscaped(string &$templateCode): void { + $templateCode = preg_replace( + '/{{(.*?)}}/', + '', + $templateCode + ); + } - /** - * @param string $templateCode - * @return int - */ - private function convertMethods(string &$templateCode, string $tag = null): int - { - $count = 0; - - if (is_null($tag)) { - $methods = array_keys($this->methods); - //Evaluate longer named methods first - usort($methods, function ($a, $b) { - return strlen($b) <=> strlen($a); - }); - $tag = implode('|', $methods); - } + /** + * @param string $templateCode + * @return void + */ + private function convertUnescaped(string &$templateCode): void { + $templateCode = preg_replace( + '/{!!(.*?)!!}/', + '', + $templateCode + ); + } - $templateCode = preg_replace_callback( - '/@('.$tag.')\s*(\(((?:[^()]++|(\g<2>))*)\))?/m', - function($match){ - if (isset($this->methods[$match[1]])) { - if (!$this->methods[$match[1]]['i']) { - $this->methods[$match[1]]['i'] = $this->methods[$match[1]]['c']::create(); - } + /** + * @param string $templateCode + * @return void + */ + private function convertComments(string &$templateCode): void { + $templateCode = preg_replace( + '/{{--(.*?)--}}/', + '', + $templateCode + ); + } - /* @var $method Method */ - $method = $this->methods[$match[1]]['i']; + /** + * @param string $templateCode + * @return int + */ + private function convertMethods(string &$templateCode, string $tag = null): int { + $count = 0; - return $method->toPhpCode($match[3] ?? null); - } + if (is_null($tag)) { + $methods = array_keys($this->methods); - return $match[0]; - }, - $templateCode, - count: $count - ); + // Evaluate longer named methods first + usort($methods, function ($a, $b) { + return strlen($b) <=> strlen($a); + }); - return $count; + $tag = implode('|', $methods); } + + $templateCode = preg_replace_callback( + '/@(' . $tag . ')\s*(\(((?:[^()]++|(\g<2>))*)\))?/m', + function ($match) { + if (isset($this->methods[$match[1]])) { + if (!$this->methods[$match[1]]['i']) { + $this->methods[$match[1]]['i'] = $this->methods[$match[1]]['c']::create(); + } + + /* @var $method Method */ + $method = $this->methods[$match[1]]['i']; + + return $method->toPhpCode($match[3] ?? null); + } + + return $match[0]; + }, + $templateCode, + count: $count + ); + + return $count; + } } diff --git a/src/Component.php b/src/Component.php index 24788f3..816fdd8 100644 --- a/src/Component.php +++ b/src/Component.php @@ -4,88 +4,83 @@ use Corviz\Crow\Traits\SelfCreate; -abstract class Component -{ - use SelfCreate; +abstract class Component { + use SelfCreate; - /** - * @var string|null - */ - protected ?string $templatesPath = null; + /** + * @var string|null + */ + protected ?string $templatesPath = null; - /** - * @var string|null - */ - protected ?string $extension = Crow::DEFAULT_EXTENSION; + /** + * @var string|null + */ + protected ?string $extension = Crow::DEFAULT_EXTENSION; - /** - * @var array - */ - private array $attributes = []; + /** + * @var array + */ + private array $attributes = []; - /** - * @var string|null - */ - private ?string $contents = null; + /** + * @var string|null + */ + private ?string $contents = null; - /** - * @return array - */ - public function getAttributes(): array - { - return $this->attributes; - } + /** + * @return array + */ + public function getAttributes(): array { + return $this->attributes; + } - /** - * @return string|null - */ - public function getContents(): ?string - { - return $this->contents; - } + /** + * @return string|null + */ + public function getContents(): ?string { + return $this->contents; + } - /** - * @param array $attributes - * @return Component - */ - public function setAttributes(array $attributes): Component - { - $this->attributes = $attributes; - return $this; - } + /** + * @param array $attributes + * @return Component + */ + public function setAttributes(array $attributes): Component { + $this->attributes = $attributes; + return $this; + } - /** - * @param string|null $contents - * @return Component - */ - public function setContents(?string $contents): Component - { - $this->contents = $contents; - return $this; - } + /** + * @param string|null $contents + * @return Component + */ + public function setContents(?string $contents): Component { + $this->contents = $contents; + return $this; + } - /** - * @return void - */ - abstract public function render(): void; + /** + * @return void + */ + abstract public function render(): void; - /** - * @param string $file - * @param array $data - * - * @return void - */ - protected function view(string $file, array $data = [], $extension = null): void - { - $data = $data + get_object_vars($this) + [ - 'contents' => $this->getContents(), - 'attributes' => $this->getAttributes(), - ]; - $extension ??= $this->extension; - $oldExt = Crow::getExtension(); + /** + * @param string $file + * @param array $data + * + * @return void + */ + protected function view(string $file, array $data = [], $extension = null): void { + $data = $data + get_object_vars($this) + [ + 'contents' => $this->getContents(), + 'attributes' => $this->getAttributes(), + ]; - Crow::setExtension($this->extension); - Crow::render($file, $data, $this->templatesPath); - Crow::setExtension($oldExt); - } + $extension ??= $this->extension; + $oldExt = Crow::getExtension(); + + Crow::setExtension($extension); + Crow::render($file, $data, $this->templatesPath); + Crow::setExtension($oldExt); + } } diff --git a/src/ComponentConverter.php b/src/ComponentConverter.php index 4874ba8..fdd04ba 100644 --- a/src/ComponentConverter.php +++ b/src/ComponentConverter.php @@ -5,171 +5,163 @@ use Corviz\Crow\Traits\SelfCreate; use Exception; -class ComponentConverter -{ - use SelfCreate; - - /** - * @var array - */ - private array $namespacesMap = []; - - /** - * @var string - */ - private string $componentsNamespace; - - /** - * @param string $namespace - * @param string $prefix - * @return ComponentConverter - * @throws Exception - */ - public function addComponentsNamespace(string $namespace, string $prefix = 'default'): ComponentConverter - { - if (isset($this->namespacesMap[$prefix])) { - throw new Exception("The prefix '$prefix' is registered already"); - } - - $this->namespacesMap[$prefix] = trim($namespace, '\\'); - return $this; +class ComponentConverter { + use SelfCreate; + + /** + * @var array + */ + private array $namespacesMap = []; + + /** + * @var string + */ + private string $componentsNamespace; + + /** + * @param string $namespace + * @param string $prefix + * @return ComponentConverter + * @throws Exception + */ + public function addComponentsNamespace(string $namespace, string $prefix = 'default'): ComponentConverter { + if (isset($this->namespacesMap[$prefix])) { + throw new Exception("The prefix '$prefix' is registered already"); } - /** - * @param string $componentsNamespace - * - * @return ComponentConverter - */ - public function setComponentsNamespace(string $componentsNamespace): ComponentConverter - { - return $this->addComponentsNamespace($componentsNamespace); - } - - /** - * @param string $template - * - * @return void - */ - public function toPhp(string &$template): void - { - do { - $count = 0; - $template = preg_replace_callback( - '/<(x-[\w.-]+)([^\/>]*?)(\/>|>((?:(?!<\/?\1\b).|(?R))*)<\/\1>)/s', - function($match) { - $code = ""; - $componentClassName = $this->getComponentClass($match[1]); - $contents = $match[4] ?? null; - - $attrsArrayCode = $this->attrsStringToArrayCode($match[2] ?? null); - - if (class_exists($componentClassName)) { - if ($contents) { - $code .= "$contents"; - } - $code .= "setAttributes($attrsArrayCode)"; - if ($contents) { - $code .= "->setContents(\$__componentContents)"; - } - $code .= "->render();"; - $code .= " ?>"; - } else { - $code .= "Component class not found: $componentClassName"; - } - - return $code; - }, - $template, - count: $count - ); - } while ($count > 0); - } - - /** - * @param string $str - * - * @return string - */ - private function dashToUpperCamelCase(string $str) - { - return ucfirst($this->dashToCamelCase($str)); - } + $this->namespacesMap[$prefix] = trim($namespace, '\\'); + return $this; + } + + /** + * @param string $componentsNamespace + * + * @return ComponentConverter + */ + public function setComponentsNamespace(string $componentsNamespace): ComponentConverter { + return $this->addComponentsNamespace($componentsNamespace); + } + + /** + * @param string $template + * + * @return void + */ + public function toPhp(string &$template): void { + do { + $count = 0; + $template = preg_replace_callback( + '/<(x-[\w.-]+)([^\/>]*?)(\/>|>((?:(?!<\/?\1\b).|(?R))*)<\/\1>)/s', + function ($match) { + $code = ""; + $componentClassName = $this->getComponentClass($match[1]); + $contents = $match[4] ?? null; + + $attrsArrayCode = $this->attrsStringToArrayCode($match[2] ?? null); + + if (class_exists($componentClassName)) { + if ($contents) { + $code .= "$contents"; + } - /** - * @param string $str - * - * @return string - */ - private function dashToCamelCase(string $str): string - { - return preg_replace_callback('/-(\w)/', function($match){ - return mb_strtoupper($match[1]); - }, $str); - } + $code .= "setAttributes($attrsArrayCode)"; - /** - * @param string|null $componentAttrs - * - * @return string - */ - private function attrsStringToArrayCode(?string $componentAttrs): string - { - $code = '['; + if ($contents) { + $code .= "->setContents(\$__componentContents)"; + } - if (!is_null($componentAttrs)) { + $code .= "->render();"; + $code .= " ?>"; + } + else { + $code .= "Component class not found: $componentClassName"; + } + + return $code; + }, + $template, + count: $count + ); + } while ($count > 0); + } + + /** + * @param string $str + * + * @return string + */ + private function dashToUpperCamelCase(string $str) { + return ucfirst($this->dashToCamelCase($str)); + } + + /** + * @param string $str + * + * @return string + */ + private function dashToCamelCase(string $str): string { + return preg_replace_callback('/-(\w)/', function ($match) { + return mb_strtoupper($match[1]); + }, $str); + } + + /** + * @param string|null $componentAttrs + * + * @return string + */ + private function attrsStringToArrayCode(?string $componentAttrs): string { + $code = '['; + + if (!is_null($componentAttrs)) { + $re = '/((:?)((\w|-)+))(="((?:[^"]++|\g<4>)(.*?))")?/s'; + + preg_match_all($re, $componentAttrs, $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + $index = $this->dashToCamelCase($match[3]); + $value = 'true'; + $isString = empty($match[2]); + + if (!empty($match[6])) { + $value = $match[6]; + $value = $isString ? "'{$value}'" : $value; + } - $re = '/((:?)((\w|-)+))(="((?:[^"]++|\g<4>)(.*?))")?/s'; + $code .= "'$index' => $value,"; + } + } - preg_match_all($re, $componentAttrs, $matches, PREG_SET_ORDER); + $code .= ']'; - foreach ($matches as $match) { - $index = $this->dashToCamelCase($match[3]); - $value = 'true'; - $isString = empty($match[2]); + return $code; + } - if (!empty($match[6])) { - $value = $match[6]; + /** + * @param string $componentTagName + * + * @return string|null + */ + private function getComponentClass(string $componentTagName): ?string { + $pieces = explode('.', substr($componentTagName, 2)); + $className = $this->dashToUpperCamelCase(array_pop($pieces)); + $namespace = $this->namespacesMap['default'] ?? ''; - if ($isString) { - $value = "'$value'"; - } - } + if (!empty($pieces)) { + do { + $currentIndex = implode('.', $pieces); - $code .= "'$index' => $value,"; - } + if (isset($this->namespacesMap[$currentIndex])) { + $namespace = $this->namespacesMap[$currentIndex]; + break; } - $code .= ']'; - - return $code; + $className = $this->dashToUpperCamelCase(array_pop($pieces)) . '\\' . $className; + } while (!empty($pieces)); } - /** - * @param string $componentTagName - * - * @return string|null - */ - private function getComponentClass(string $componentTagName): ?string - { - $pieces = explode('.', substr($componentTagName, 2)); - $className = $this->dashToUpperCamelCase(array_pop($pieces)); - $namespace = $this->namespacesMap['default'] ?? ''; - - if (!empty($pieces)) { - do { - $currentIndex = implode('.', $pieces); - - if (isset($this->namespacesMap[$currentIndex])) { - $namespace = $this->namespacesMap[$currentIndex]; - break; - } - - $className = $this->dashToUpperCamelCase(array_pop($pieces)).'\\'.$className; - } while(!empty($pieces)); - } - - return !empty($namespace) ? "\\{$namespace}\\{$className}" : "\\{$className}"; - } + return !empty($namespace) ? "\\{$namespace}\\{$className}" : "\\{$className}"; + } } diff --git a/src/Crow.php b/src/Crow.php index 63703e2..c04fbec 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -6,379 +6,350 @@ use Corviz\Crow\Methods; use Exception; -class Crow -{ - /** - * - */ - public const DEFAULT_EXTENSION = '.crow.php'; - - /** - * - */ - private const DEFAULT_METHODS = [ - 'empty' => Methods\Empty\EmptyMethod::class, - 'endempty' => Methods\Empty\EndEmptyMethod::class, - 'for' => Methods\For\ForMethod::class, - 'endfor' => Methods\For\EndForMethod::class, - 'foreach' => Methods\Foreach\ForeachMethod::class, - 'endforeach' => Methods\Foreach\EndForeachMethod::class, - 'forelse' => Methods\Forelse\ForelseMethod::class, - 'endforelse' => Methods\Forelse\EndforelseMethod::class, - 'if' => Methods\If\IfMethod::class, - 'else' => Methods\If\ElseMethod::class, - 'elseif' => Methods\If\ElseIfMethod::class, - 'endif' => Methods\If\EndIfMethod::class, - 'isset' => Methods\Isset\IssetMethod::class, - 'endisset' => Methods\Isset\EndIssetMethod::class, - 'php' => Methods\Php\PhpMethod::class, - 'endphp' => Methods\Php\EndPhpMethod::class, - 'section' => Methods\Section\SectionMethod::class, - 'endsection' => Methods\Section\EndSectionMethod::class, - 'case' => Methods\Switch\CaseMethod::class, - 'default' => Methods\Switch\DefaultMethod::class, - 'endswitch' => Methods\Switch\EndSwitchMethod::class, - 'switch' => Methods\Switch\SwitchMethod::class, - 'unless' => Methods\Unless\UnlessMethod::class, - 'endunless' => Methods\Unless\EndUnlessMethod::class, - 'while' => Methods\While\WhileMethod::class, - 'endwhile' => Methods\While\EndWhileMethod::class, - 'break' => Methods\BreakMethod::class, - 'checked' => Methods\CheckedMethod::class, - 'class' => Methods\ClassMethod::class, - 'continue' => Methods\ContinueMethod::class, - 'disabled' => Methods\DisabledMethod::class, - 'extends' => Methods\ExtendsMethod::class, - 'include' => Methods\IncludeMethod::class, - 'readonly' => Methods\ReadonlyMethod::class, - 'selected' => Methods\SelectedMethod::class, - 'yield' => Methods\YieldMethod::class, - ]; - - /** - * @var array - */ - private static array $pathHashes = []; - - /** - * @var Closure|null - */ - private static ?Closure $pathHashingFunction = null; - - /** - * @var string|null - */ - private static ?string $cacheFolder = null; - - /** - * @var array - */ - private static array $data = []; - - /** - * @var FileLoader - */ - private static ?FileLoader $loader = null; - - /** - * @var CodeConverter - */ - private static ?CodeConverter $codeConverter = null; - - /** - * @var ComponentConverter|null - */ - private static ?ComponentConverter $componentConverter = null; - - /** - * @var array - */ - private static array $renderQueue = []; - - /** - * @param string $file - * @param array $data - * @param string|null $path - * - * @throws Exception - * @return void - */ - public static function render(string $file, array $data = [], ?string $path = null) - { - $cacheFile = null; - self::data('dataKeys', array_keys($data)); - $isCached = false; - - if (!is_null(self::$cacheFolder)) { - $folder = 'c'.self::generatePathHash($path); - $cacheFile = self::$cacheFolder."/$folder/$file.cache.php"; - - $loader = self::getLoader(); - if (is_file($cacheFile) && filemtime($cacheFile) > $loader->getModificationTime($file, $path)) { - $isCached = true; - } - } - - if (!$isCached) { - $__crowTemplateCode = self::getPhpCode($file, $path); - self::getComponentConverter()->toPhp($__crowTemplateCode); - - if (!is_null(self::$cacheFolder)) { - $cacheDir = dirname($cacheFile); - if (!is_dir($cacheDir)) { - mkdir($cacheDir, recursive: true); - } - - if (false === file_put_contents($cacheFile, $__crowTemplateCode)) { - throw new Exception('Could not write cache file: '.$cacheFile); - } - } - - extract($data); - eval("?>$__crowTemplateCodeaddComponentsNamespace(...$arguments); - } - - /** - * @param string $method - * @param string $class - * - * @return void - */ - public static function addMethod(string $method, string $class): void - { - self::getCodeConverter()->addMethod($method, $class); - } - - /** - * @param string|null $key - * @param mixed|null $value - * - * @return mixed - */ - public static function data(string $key = null, mixed $value = null): mixed - { - if (is_null($key) && is_null($value)) - return self::$data; - - if (is_null($value)) - return self::$data[$key] ?? null; - - self::$data[$key] = $value; - return null; - } - - /** - * @return void - */ - public static function disableCodeMinifying(): void - { - self::data('options.disable-minifying', true); - } - - /** - * @param string $key - * - * @return void - */ - public static function removeData(string $key): void - { - if (isset(self::$data[$key])) - unset(self::$data[$key]); +class Crow { + /** + * @const DEFAULT_EXTENSION + */ + public const DEFAULT_EXTENSION = '.crow.php'; + + /** + * @const DEFAULT_METHODS + */ + private const DEFAULT_METHODS = [ + 'empty' => Methods\Empty\EmptyMethod::class, + 'endempty' => Methods\Empty\EndEmptyMethod::class, + 'for' => Methods\For\ForMethod::class, + 'endfor' => Methods\For\EndForMethod::class, + 'foreach' => Methods\Foreach\ForeachMethod::class, + 'endforeach' => Methods\Foreach\EndForeachMethod::class, + 'forelse' => Methods\Forelse\ForelseMethod::class, + 'endforelse' => Methods\Forelse\EndforelseMethod::class, + 'if' => Methods\If\IfMethod::class, + 'else' => Methods\If\ElseMethod::class, + 'elseif' => Methods\If\ElseIfMethod::class, + 'endif' => Methods\If\EndIfMethod::class, + 'isset' => Methods\Isset\IssetMethod::class, + 'endisset' => Methods\Isset\EndIssetMethod::class, + 'php' => Methods\Php\PhpMethod::class, + 'endphp' => Methods\Php\EndPhpMethod::class, + 'section' => Methods\Section\SectionMethod::class, + 'endsection' => Methods\Section\EndSectionMethod::class, + 'case' => Methods\Switch\CaseMethod::class, + 'default' => Methods\Switch\DefaultMethod::class, + 'endswitch' => Methods\Switch\EndSwitchMethod::class, + 'switch' => Methods\Switch\SwitchMethod::class, + 'unless' => Methods\Unless\UnlessMethod::class, + 'endunless' => Methods\Unless\EndUnlessMethod::class, + 'while' => Methods\While\WhileMethod::class, + 'endwhile' => Methods\While\EndWhileMethod::class, + 'break' => Methods\BreakMethod::class, + 'checked' => Methods\CheckedMethod::class, + 'class' => Methods\ClassMethod::class, + 'continue' => Methods\ContinueMethod::class, + 'disabled' => Methods\DisabledMethod::class, + 'extends' => Methods\ExtendsMethod::class, + 'include' => Methods\IncludeMethod::class, + 'readonly' => Methods\ReadonlyMethod::class, + 'selected' => Methods\SelectedMethod::class, + 'yield' => Methods\YieldMethod::class, + ]; + + /** + * @var array + */ + private static array $pathHashes = []; + + /** + * @var Closure|null + */ + private static ?Closure $pathHashingFunction = null; + + /** + * @var string|null + */ + private static ?string $cacheFolder = null; + + /** + * @var array + */ + private static array $data = []; + + /** + * @var FileLoader + */ + private static ?FileLoader $loader = null; + + /** + * @var CodeConverter + */ + private static ?CodeConverter $codeConverter = null; + + /** + * @var ComponentConverter|null + */ + private static ?ComponentConverter $componentConverter = null; + + /** + * @var array + */ + private static array $renderQueue = []; + + /** + * @param string $file + * @param array $data + * @param string|null $path + * + * @throws Exception + * @return void + */ + public static function render(string $file, array $data = [], ?string $path = null) { + $cacheFile = null; + self::data('dataKeys', array_keys($data)); + $isCached = false; + + if (!is_null(self::$cacheFolder)) { + $folder = 'c' . self::generatePathHash($path); + $cacheFile = self::$cacheFolder . "/$folder/$file.cache.php"; + + $loader = self::getLoader(); + if (is_file($cacheFile) && filemtime($cacheFile) > $loader->getModificationTime($file, $path)) { + $isCached = true; + } } - /** - * @return string|null - */ - public static function getExtension(): string - { - return self::getLoader()->getExtension() ?? self::DEFAULT_EXTENSION; - } + if (!$isCached) { + $__crowTemplateCode = self::getPhpCode($file, $path); + self::getComponentConverter()->toPhp($__crowTemplateCode); - /** - * @param string $file - * @param string|null $path - * - * @return string - * @throws Exception - */ - public static function getPhpCode(string $file, ?string $path = null): string - { - $code = self::getCodeConverter()->toPhp( - self::getTemplateContents($file, $path) - ); - - while (!empty(self::$renderQueue)) { - $tpl = array_pop(self::$renderQueue); - - $code .= self::getCodeConverter()->toPhp( - self::getTemplateContents($tpl['file'], $tpl['path']) - ); + if (!is_null(self::$cacheFolder)) { + $cacheDir = dirname($cacheFile); + if (!is_dir($cacheDir)) { + mkdir($cacheDir, recursive: true); } - self::minify($code); + if (false === file_put_contents($cacheFile, $__crowTemplateCode)) { + throw new Exception('Could not write cache file: ' . $cacheFile); + } + } - return $code; + extract($data); + eval ("?>$__crowTemplateCodeload($file, $path); + else { + extract($data); + require $cacheFile; } - - /** - * @param string|null $cacheFolder - */ - public static function setCacheFolder(?string $cacheFolder): void - { - self::$cacheFolder = $cacheFolder; + } + + /** + * @param string $namespace + * @param string|null $prefix + * @return void + * @throws Exception + */ + public static function addComponentsNamespace(string $namespace, string $prefix = null): void { + $arguments = [$namespace]; + + if (!is_null($prefix)) { + $arguments[] = $prefix; } - /** - * @param string $namespace - * @return void - * @throws Exception - */ - public static function setComponentsNamespace(string $namespace) - { - self::addComponentsNamespace($namespace); + self::getComponentConverter()->addComponentsNamespace(...$arguments); + } + + /** + * @param string $method + * @param string $class + * + * @return void + */ + public static function addMethod(string $method, string $class): void { + self::getCodeConverter()->addMethod($method, $class); + } + + /** + * @param string|null $key + * @param mixed|null $value + * + * @return mixed + */ + public static function data(string $key = null, mixed $value = null): mixed { + if (is_null($key) && is_null($value)) return self::$data; + if (is_null($value)) return self::$data[$key] ?? null; + + self::$data[$key] = $value; + return null; + } + + /** + * @return void + */ + public static function disableCodeMinifying(): void { + self::data('options.disable-minifying', true); + } + + /** + * @param string $key + * + * @return void + */ + public static function removeData(string $key): void { + if (isset(self::$data[$key])) unset(self::$data[$key]); + } + + /** + * @return string|null + */ + public static function getExtension(): string { + return self::getLoader()->getExtension() ?? self::DEFAULT_EXTENSION; + } + + /** + * @param string $file + * @param string|null $path + * + * @return string + * @throws Exception + */ + public static function getPhpCode(string $file, ?string $path = null): string { + $code = self::getCodeConverter()->toPhp( + self::getTemplateContents($file, $path) + ); + + while (!empty(self::$renderQueue)) { + $tpl = array_pop(self::$renderQueue); + $code .= self::getCodeConverter()->toPhp(self::getTemplateContents($tpl['file'], $tpl['path'])); } - /** - * @param string $path - * @return void - */ - public static function setDefaultPath(string $path) - { - self::getLoader()->setDefaultPath($path); + self::minify($code); + + return $code; + } + + /** + * @param string $file + * @param string|null $path + * + * @return string + * @throws Exception + */ + public static function getTemplateContents(string $file, ?string $path = null): string { + return self::getLoader()->load($file, $path); + } + + /** + * @param string|null $cacheFolder + */ + public static function setCacheFolder(?string $cacheFolder): void { + self::$cacheFolder = $cacheFolder; + } + + /** + * @param string $namespace + * @return void + * @throws Exception + */ + public static function setComponentsNamespace(string $namespace) { + self::addComponentsNamespace($namespace); + } + + /** + * @param string $path + * @return void + */ + public static function setDefaultPath(string $path) { + self::getLoader()->setDefaultPath($path); + } + + /** + * @param string $extension + * @return void + */ + public static function setExtension(string $extension) { + self::getLoader()->setExtension($extension); + } + + /** + * @param callable $pathHashingFunction + * + * @return void + */ + public static function setPathHashingFunction(callable $pathHashingFunction): void { + self::$pathHashingFunction = Closure::fromCallable($pathHashingFunction); + } + + /** + * @param string $file + * @param string|null $path + * + * @return void + */ + public static function queueTemplate(string $file, ?string $path = null) { + self::$renderQueue[] = compact('file', 'path'); + } + + /** + * @param string|null $path + * @return string + */ + private static function generatePathHash(?string $path): string { + $path ??= 'default'; + + if (!isset(self::$pathHashes[$path])) { + $hashingFunction = self::$pathHashingFunction ?? 'md5'; + self::$pathHashes[$path] = $hashingFunction($path); } - /** - * @param string $extension - * @return void - */ - public static function setExtension(string $extension) - { - self::getLoader()->setExtension($extension); - } + return self::$pathHashes[$path]; + } - /** - * @param callable $pathHashingFunction - * - * @return void - */ - public static function setPathHashingFunction(callable $pathHashingFunction): void - { - self::$pathHashingFunction = Closure::fromCallable($pathHashingFunction); - } + /** + * @return CodeConverter + */ + private static function getCodeConverter(): CodeConverter { + if (!self::$codeConverter) { + self::$codeConverter = new CodeConverter(); - /** - * @param string $file - * @param string|null $path - * - * @return void - */ - public static function queueTemplate(string $file, ?string $path = null) - { - self::$renderQueue[] = compact('file', 'path'); + // Register all default methods + foreach (self::DEFAULT_METHODS as $m => $c) { + self::$codeConverter->addMethod($m, $c); + } } - /** - * @param string|null $path - * @return string - */ - private static function generatePathHash(?string $path): string - { - $path = $path ?? 'default'; - - if (!isset(self::$pathHashes[$path])) { - $hashingFunction = self::$pathHashingFunction ?? 'md5'; - self::$pathHashes[$path] = $hashingFunction($path); - } + return self::$codeConverter; + } - return self::$pathHashes[$path]; + /** + * @return ComponentConverter + */ + private static function getComponentConverter(): ComponentConverter { + if (!self::$componentConverter) { + self::$componentConverter = new ComponentConverter(); } - /** - * @return CodeConverter - */ - private static function getCodeConverter(): CodeConverter - { - if (!self::$codeConverter){ - self::$codeConverter = new CodeConverter(); - - //Register all default methods - foreach (self::DEFAULT_METHODS as $m => $c) { - self::$codeConverter->addMethod($m, $c); - } - } + return self::$componentConverter; + } - return self::$codeConverter; + /** + * @return FileLoader + */ + private static function getLoader(): FileLoader { + if (!self::$loader) { + self::$loader = FileLoader::create()->setExtension(self::DEFAULT_EXTENSION); } - /** - * @return ComponentConverter - */ - private static function getComponentConverter(): ComponentConverter - { - if (!self::$componentConverter){ - self::$componentConverter = new ComponentConverter(); - } - - return self::$componentConverter; - } + return self::$loader; + } - /** - * @return FileLoader - */ - private static function getLoader(): FileLoader - { - if (!self::$loader) { - self::$loader = FileLoader::create() - ->setExtension(self::DEFAULT_EXTENSION); - } + /** + * @param string $code + * @return string + */ + private static function minify(string &$code): void { + if (self::data('options.disable-minifying')) return; - return self::$loader; - } - - /** - * @param string $code - * @return string - */ - private static function minify(string &$code): void - { - if (self::data('options.disable-minifying')) - return; - - $code = str_replace(["\t", "\n", "\r"], ' ', $code); - $code = preg_replace('/\s{2,}/m', ' ', $code); - $code = trim($code); - } + $code = str_replace(["\t", "\n", "\r"], ' ', $code); + $code = preg_replace('/\s{2,}/m', ' ', $code); + $code = trim($code); + } } diff --git a/src/FileLoader.php b/src/FileLoader.php index 4f23e2f..2a1da2f 100644 --- a/src/FileLoader.php +++ b/src/FileLoader.php @@ -5,89 +5,82 @@ use Corviz\Crow\Traits\SelfCreate; use Exception; -class FileLoader -{ - use SelfCreate; +class FileLoader { + use SelfCreate; - /** - * @var string|null - */ - private ?string $defaultPath = null; + /** + * @var string|null + */ + private ?string $defaultPath = null; - /** - * @var string|null - */ - private ?string $extension = null; + /** + * @var string|null + */ + private ?string $extension = null; - /** - * @return string|null - */ - public function getExtension(): ?string - { - return $this->extension; - } - - /** - * @param string $file - * @param string|null $path - * @return int|false - */ - public function getModificationTime(string $file, string $path = null): int|false - { - return filemtime($this->getFilePath($file, $path)); - } + /** + * @return string|null + */ + public function getExtension(): ?string { + return $this->extension; + } - /** - * - * @param string $file - * @param string|null $path - * - * @return string - * @throws Exception - */ - public function load(string $file, string $path = null): string - { - $filename = $this->getFilePath($file, $path); + /** + * @param string $file + * @param string|null $path + * @return int|false + */ + public function getModificationTime(string $file, string $path = null): int|false { + return filemtime($this->getFilePath($file, $path)); + } - if (!is_file($filename) || !is_readable($filename)) { - throw new Exception("File is unreadable: '$filename'"); - } + /** + * + * @param string $file + * @param string|null $path + * + * @return string + * @throws Exception + */ + public function load(string $file, string $path = null): string { + $filename = $this->getFilePath($file, $path); - return file_get_contents($filename); + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception("File is unreadable: '$filename'"); } - /** - * @param string|null $defaultPath - * @return FileLoader - */ - public function setDefaultPath(?string $defaultPath): FileLoader - { - $this->defaultPath = $defaultPath; - return $this; - } + return file_get_contents($filename); + } - /** - * @param string|null $extension - * @return FileLoader - */ - public function setExtension(?string $extension): FileLoader - { - $this->extension = $extension; - return $this; - } + /** + * @param string|null $defaultPath + * @return FileLoader + */ + public function setDefaultPath(?string $defaultPath): FileLoader { + $this->defaultPath = $defaultPath; + return $this; + } - /** - * @param string $file - * @param string|null $path - * @return string - */ - private function getFilePath(string $file, string $path = null) - { - $path ??= $this->defaultPath ?? ''; - $extension = $this->extension ?? ''; - $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; - $extension = str_ends_with($extension, '.php') ? rtrim($extension, '.php') : $extension; + /** + * @param string|null $extension + * @return FileLoader + */ + public function setExtension(?string $extension): FileLoader { + $this->extension = $extension; + return $this; + } - return "{$path}/{$file}.{$extension}.php"; - } + /** + * @param string $file + * @param string|null $path + * @return string + */ + private function getFilePath(string $file, string $path = null) { + $path ??= $this->defaultPath ?? ''; + $extension = $this->extension ?? ''; + $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; + $extension = str_ends_with($extension, '.php') ? rtrim($extension, '.php') : $extension; + + return "{$path}/{$file}.{$extension}.php"; + } } diff --git a/src/Method.php b/src/Method.php index 90c2d31..8aa35cf 100644 --- a/src/Method.php +++ b/src/Method.php @@ -4,15 +4,14 @@ use Corviz\Crow\Traits\SelfCreate; -abstract class Method -{ - use SelfCreate; +abstract class Method { + use SelfCreate; - /** - * Php code representing this method - * - * @param string|null $parameters - * @return string - */ - abstract public function toPhpCode(?string $parameters = null): string; + /** + * Php code representing this method + * + * @param string|null $parameters + * @return string + */ + abstract public function toPhpCode(?string $parameters = null): string; } diff --git a/src/Methods/BreakMethod.php b/src/Methods/BreakMethod.php index e0fa777..202e3eb 100644 --- a/src/Methods/BreakMethod.php +++ b/src/Methods/BreakMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class BreakMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ''; - } +class BreakMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ''; + } } diff --git a/src/Methods/CheckedMethod.php b/src/Methods/CheckedMethod.php index 2198a09..520f9a5 100644 --- a/src/Methods/CheckedMethod.php +++ b/src/Methods/CheckedMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class CheckedMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class CheckedMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/ClassMethod.php b/src/Methods/ClassMethod.php index a1212da..fca67bd 100644 --- a/src/Methods/ClassMethod.php +++ b/src/Methods/ClassMethod.php @@ -2,19 +2,17 @@ namespace Corviz\Crow\Methods; -class ClassMethod extends \Corviz\Crow\Method -{ +class ClassMethod extends \Corviz\Crow\Method { - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - $code = 'class=" \$__ccheck) {"; - $code .= 'if (is_bool($__ccheck) and $__ccheck) { echo $__cclassname, \' \'; } '; - $code .= 'else if (is_numeric($__cclassname)) { echo $__ccheck, \' \'; } '; - $code .= '} ?>"'; - return $code; - } + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + $code = 'class=" \$__ccheck) {"; + $code .= 'if (is_bool($__ccheck) and $__ccheck) { echo $__cclassname, \' \'; } '; + $code .= 'else if (is_numeric($__cclassname)) { echo $__ccheck, \' \'; } '; + $code .= '} ?>"'; + return $code; + } } \ No newline at end of file diff --git a/src/Methods/ContinueMethod.php b/src/Methods/ContinueMethod.php index cd456b8..95a90e1 100644 --- a/src/Methods/ContinueMethod.php +++ b/src/Methods/ContinueMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class ContinueMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ''; - } +class ContinueMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/DisabledMethod.php b/src/Methods/DisabledMethod.php index 4f1a5b1..d00faf6 100644 --- a/src/Methods/DisabledMethod.php +++ b/src/Methods/DisabledMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class DisabledMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class DisabledMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Empty/EmptyMethod.php b/src/Methods/Empty/EmptyMethod.php index de95283..53afafd 100644 --- a/src/Methods/Empty/EmptyMethod.php +++ b/src/Methods/Empty/EmptyMethod.php @@ -5,20 +5,18 @@ use Corviz\Crow\Crow; use Corviz\Crow\Method; -class EmptyMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - $code = ""; +class EmptyMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + $code = ""; - if (Crow::data('forelse')) { - $code = ""; - Crow::removeData('forelse'); - } - - return $code; + if (Crow::data('forelse')) { + $code = ""; + Crow::removeData('forelse'); } + + return $code; + } } diff --git a/src/Methods/Empty/EndEmptyMethod.php b/src/Methods/Empty/EndEmptyMethod.php index 856fa6b..01d6542 100644 --- a/src/Methods/Empty/EndEmptyMethod.php +++ b/src/Methods/Empty/EndEmptyMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndEmptyMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndEmptyMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/ExtendsMethod.php b/src/Methods/ExtendsMethod.php index 5409a9d..431d98e 100644 --- a/src/Methods/ExtendsMethod.php +++ b/src/Methods/ExtendsMethod.php @@ -5,15 +5,13 @@ use Corviz\Crow\Crow; use Corviz\Crow\Method; -class ExtendsMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - eval('$parameters = '.$parameters.';'); - Crow::queueTemplate($parameters); - return ''; - } +class ExtendsMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + eval ("\$parameters = {$parameters};"); + Crow::queueTemplate($parameters); + return ''; + } } diff --git a/src/Methods/For/EndForMethod.php b/src/Methods/For/EndForMethod.php index a31928a..a3bab9e 100644 --- a/src/Methods/For/EndForMethod.php +++ b/src/Methods/For/EndForMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndForMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndForMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/For/ForMethod.php b/src/Methods/For/ForMethod.php index bdbb672..7a5c982 100644 --- a/src/Methods/For/ForMethod.php +++ b/src/Methods/For/ForMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class ForMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class ForMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Foreach/EndForeachMethod.php b/src/Methods/Foreach/EndForeachMethod.php index 30e31f6..93cb4a8 100644 --- a/src/Methods/Foreach/EndForeachMethod.php +++ b/src/Methods/Foreach/EndForeachMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndForeachMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndForeachMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Foreach/ForeachMethod.php b/src/Methods/Foreach/ForeachMethod.php index 651c6b8..dbefd9e 100644 --- a/src/Methods/Foreach/ForeachMethod.php +++ b/src/Methods/Foreach/ForeachMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class ForeachMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class ForeachMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Forelse/EndforelseMethod.php b/src/Methods/Forelse/EndforelseMethod.php index 5311b37..e12a518 100644 --- a/src/Methods/Forelse/EndforelseMethod.php +++ b/src/Methods/Forelse/EndforelseMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndforelseMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndforelseMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Forelse/ForelseMethod.php b/src/Methods/Forelse/ForelseMethod.php index 84837bf..4bb4051 100644 --- a/src/Methods/Forelse/ForelseMethod.php +++ b/src/Methods/Forelse/ForelseMethod.php @@ -5,21 +5,19 @@ use Corviz\Crow\Crow; use Corviz\Crow\Method; -class ForelseMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - $v = explode(' as ', $parameters)[0]; +class ForelseMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + $v = explode(' as ', $parameters)[0]; - $code = ""; + $code = ""; - Crow::data('forelse', true); + Crow::data('forelse', true); - return $code; - } + return $code; + } } diff --git a/src/Methods/If/ElseIfMethod.php b/src/Methods/If/ElseIfMethod.php index 83c835d..ced6ed3 100644 --- a/src/Methods/If/ElseIfMethod.php +++ b/src/Methods/If/ElseIfMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class ElseIfMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class ElseIfMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/If/ElseMethod.php b/src/Methods/If/ElseMethod.php index 3542407..9dd6eb0 100644 --- a/src/Methods/If/ElseMethod.php +++ b/src/Methods/If/ElseMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class ElseMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class ElseMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/If/EndIfMethod.php b/src/Methods/If/EndIfMethod.php index 6ee1ea6..74b5474 100644 --- a/src/Methods/If/EndIfMethod.php +++ b/src/Methods/If/EndIfMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndIfMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndIfMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/If/IfMethod.php b/src/Methods/If/IfMethod.php index d83a6f4..40f6fc3 100644 --- a/src/Methods/If/IfMethod.php +++ b/src/Methods/If/IfMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class IfMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class IfMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/IncludeMethod.php b/src/Methods/IncludeMethod.php index 351c705..2b48ea5 100644 --- a/src/Methods/IncludeMethod.php +++ b/src/Methods/IncludeMethod.php @@ -5,14 +5,12 @@ use Corviz\Crow\Crow; use Corviz\Crow\Method; -class IncludeMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - eval("\$code = \Corviz\Crow\Crow::getTemplateContents($parameters);"); - return $code; - } +class IncludeMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + eval ("\$code = \Corviz\Crow\Crow::getTemplateContents({$parameters});"); + return $code; + } } diff --git a/src/Methods/Isset/EndIssetMethod.php b/src/Methods/Isset/EndIssetMethod.php index 12cd377..29e9537 100644 --- a/src/Methods/Isset/EndIssetMethod.php +++ b/src/Methods/Isset/EndIssetMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndIssetMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndIssetMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Isset/IssetMethod.php b/src/Methods/Isset/IssetMethod.php index 5859606..d51f592 100644 --- a/src/Methods/Isset/IssetMethod.php +++ b/src/Methods/Isset/IssetMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class IssetMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class IssetMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } \ No newline at end of file diff --git a/src/Methods/Php/EndPhpMethod.php b/src/Methods/Php/EndPhpMethod.php index 92c2b49..1395e59 100644 --- a/src/Methods/Php/EndPhpMethod.php +++ b/src/Methods/Php/EndPhpMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndPhpMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return " ?>"; - } +class EndPhpMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return " ?>"; + } } diff --git a/src/Methods/Php/PhpMethod.php b/src/Methods/Php/PhpMethod.php index 9b0ae30..9ac3e50 100644 --- a/src/Methods/Php/PhpMethod.php +++ b/src/Methods/Php/PhpMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class PhpMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class ReadonlyMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Section/EndSectionMethod.php b/src/Methods/Section/EndSectionMethod.php index 046a08a..f468877 100644 --- a/src/Methods/Section/EndSectionMethod.php +++ b/src/Methods/Section/EndSectionMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndSectionMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ''; - } +class EndSectionMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ''; + } } diff --git a/src/Methods/Section/SectionMethod.php b/src/Methods/Section/SectionMethod.php index 667f8d5..2298ca4 100644 --- a/src/Methods/Section/SectionMethod.php +++ b/src/Methods/Section/SectionMethod.php @@ -5,37 +5,34 @@ use Corviz\Crow\Crow; use Corviz\Crow\Method; -class SectionMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - eval("\$p = [$parameters];"); - $use = $this->buildUse(); - $code = ""; - - if (count($p) > 1) { - $code .= $p[1]; - $code .= ""; - } - - return $code; +class SectionMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + eval ("\$p = [$parameters];"); + $use = $this->buildUse(); + $code = ""; + + if (count($p) > 1) { + $code .= $p[1]; + $code .= ""; } - /** - * @return string - */ - private function buildUse(): string - { - $use = ''; + return $code; + } - $dataKeys = Crow::data('dataKeys') ?? []; - if (!empty($dataKeys)) { - $use = 'use ('.implode(',', array_map(fn($k) => "&$$k", $dataKeys)).')'; - } + /** + * @return string + */ + private function buildUse(): string { + $use = ''; + $dataKeys = Crow::data('dataKeys') ?? []; - return $use; + if (!empty($dataKeys)) { + $use = 'use (' . implode(',', array_map(fn($k) => "&$$k", $dataKeys)) . ')'; } + + return $use; + } } \ No newline at end of file diff --git a/src/Methods/SelectedMethod.php b/src/Methods/SelectedMethod.php index 8a25f6f..621407d 100644 --- a/src/Methods/SelectedMethod.php +++ b/src/Methods/SelectedMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class SelectedMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class SelectedMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Switch/CaseMethod.php b/src/Methods/Switch/CaseMethod.php index ea6e28a..52cb7c8 100644 --- a/src/Methods/Switch/CaseMethod.php +++ b/src/Methods/Switch/CaseMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class CaseMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class CaseMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Switch/DefaultMethod.php b/src/Methods/Switch/DefaultMethod.php index 4e163ba..1bc6298 100644 --- a/src/Methods/Switch/DefaultMethod.php +++ b/src/Methods/Switch/DefaultMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class DefaultMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class DefaultMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Switch/EndSwitchMethod.php b/src/Methods/Switch/EndSwitchMethod.php index 697b064..712bed5 100644 --- a/src/Methods/Switch/EndSwitchMethod.php +++ b/src/Methods/Switch/EndSwitchMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndSwitchMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndSwitchMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Switch/SwitchMethod.php b/src/Methods/Switch/SwitchMethod.php index 11b8845..b83b381 100644 --- a/src/Methods/Switch/SwitchMethod.php +++ b/src/Methods/Switch/SwitchMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class SwitchMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class SwitchMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Unless/EndUnlessMethod.php b/src/Methods/Unless/EndUnlessMethod.php index 770725b..9f9a527 100644 --- a/src/Methods/Unless/EndUnlessMethod.php +++ b/src/Methods/Unless/EndUnlessMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndUnlessMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndUnlessMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/Unless/UnlessMethod.php b/src/Methods/Unless/UnlessMethod.php index 95e3d39..8d62f07 100644 --- a/src/Methods/Unless/UnlessMethod.php +++ b/src/Methods/Unless/UnlessMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class UnlessMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class UnlessMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/While/EndWhileMethod.php b/src/Methods/While/EndWhileMethod.php index 936cdd4..68a403b 100644 --- a/src/Methods/While/EndWhileMethod.php +++ b/src/Methods/While/EndWhileMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class EndWhileMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class EndWhileMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/While/WhileMethod.php b/src/Methods/While/WhileMethod.php index dc308fd..43c7f3a 100644 --- a/src/Methods/While/WhileMethod.php +++ b/src/Methods/While/WhileMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class WhileMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class WhileMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/Methods/YieldMethod.php b/src/Methods/YieldMethod.php index 4b8f946..4676add 100644 --- a/src/Methods/YieldMethod.php +++ b/src/Methods/YieldMethod.php @@ -4,13 +4,11 @@ use Corviz\Crow\Method; -class YieldMethod extends Method -{ - /** - * @inheritDoc - */ - public function toPhpCode(?string $parameters = null): string - { - return ""; - } +class YieldMethod extends Method { + /** + * @inheritDoc + */ + public function toPhpCode(?string $parameters = null): string { + return ""; + } } diff --git a/src/SectionsManager.php b/src/SectionsManager.php index dd72239..cc95c7b 100644 --- a/src/SectionsManager.php +++ b/src/SectionsManager.php @@ -2,32 +2,29 @@ namespace Corviz\Crow; -class SectionsManager -{ - /** - * @var array - */ - private static array $sections = []; +class SectionsManager { + /** + * @var array + */ + private static array $sections = []; - /** - * @param string $index - * @param callable $section - * - * @return void - */ - public static function addSection(string $index, callable $section): void - { - self::$sections[$index] = $section; - } + /** + * @param string $index + * @param callable $section + * + * @return void + */ + public static function addSection(string $index, callable $section): void { + self::$sections[$index] = $section; + } - /** - * @param string $index - * @return void - */ - public static function renderSection(string $index) - { - if (isset(self::$sections[$index])) { - self::$sections[$index](); - } + /** + * @param string $index + * @return void + */ + public static function renderSection(string $index) { + if (isset(self::$sections[$index])) { + self::$sections[$index](); } + } } diff --git a/src/Traits/SelfCreate.php b/src/Traits/SelfCreate.php index a72a3c7..3ed69ab 100644 --- a/src/Traits/SelfCreate.php +++ b/src/Traits/SelfCreate.php @@ -2,15 +2,13 @@ namespace Corviz\Crow\Traits; -trait SelfCreate -{ - /** - * @see static::__construct(); - * - * @return static - */ - public static function create(...$arguments) - { - return new static(...$arguments); - } +trait SelfCreate { + /** + * @see static::__construct(); + * + * @return static + */ + public static function create(...$arguments) { + return new static(...$arguments); + } } \ No newline at end of file From 67c7953e36e920e81f71d7c2d68bf03ecfe55ab9 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Sat, 10 Aug 2024 20:44:38 +0300 Subject: [PATCH 08/21] Fixed issue #11 and changed the behavior of parsing attributes: dashed attributes won't be camelCased anymore due to ability to user custom data attributes, also introduced $this->getAttributesParsed() passed through custom component by $attributesParsed. --- src/Component.php | 11 +++++++++-- src/ComponentConverter.php | 14 +++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Component.php b/src/Component.php index 816fdd8..43c37b1 100644 --- a/src/Component.php +++ b/src/Component.php @@ -41,6 +41,12 @@ public function getContents(): ?string { return $this->contents; } + protected function getAttributesParsed() { + $attrs = ""; + foreach ($this->getAttributes() as $a => $v) { $attrs .= "{$a}='{$v}' "; } + return $attrs; + } + /** * @param array $attributes * @return Component @@ -72,8 +78,9 @@ abstract public function render(): void; */ protected function view(string $file, array $data = [], $extension = null): void { $data = $data + get_object_vars($this) + [ - 'contents' => $this->getContents(), - 'attributes' => $this->getAttributes(), + 'contents' => $this->getContents(), + 'attributes' => $this->getAttributes(), + 'attributesParsed' => $this->getAttributesParsed(), ]; $extension ??= $this->extension; diff --git a/src/ComponentConverter.php b/src/ComponentConverter.php index fdd04ba..4660007 100644 --- a/src/ComponentConverter.php +++ b/src/ComponentConverter.php @@ -116,18 +116,18 @@ private function attrsStringToArrayCode(?string $componentAttrs): string { $code = '['; if (!is_null($componentAttrs)) { - $re = '/((:?)((\w|-)+))(="((?:[^"]++|\g<4>)(.*?))")?/s'; + // $re = '/((:?)((\w|-)+))(="((?:[^"]++|\g<4>)(.*?))")?/s'; // origin regex + $re = '/((:?)((\w|-)+))=["\']((?:[^"\'\\\\]|\\\\.)*?)["\']/s'; preg_match_all($re, $componentAttrs, $matches, PREG_SET_ORDER); foreach ($matches as $match) { - $index = $this->dashToCamelCase($match[3]); - $value = 'true'; - $isString = empty($match[2]); + $index = $match[3]; //$this->dashToCamelCase($match[3]); + $value = "''"; - if (!empty($match[6])) { - $value = $match[6]; - $value = $isString ? "'{$value}'" : $value; + if (!empty($match[5])) { + $value = $match[5]; + $value = empty($match[2]) ? "'{$value}'" : $value; } $code .= "'$index' => $value,"; From f30b11726f69f09264fae9697c8b8b98bbd03841 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Sat, 10 Aug 2024 23:09:52 +0300 Subject: [PATCH 09/21] fixed suffixed namespaces due to keywords conflicts --- src/Crow.php | 12 ++++++------ src/Methods/{Empty => EmptyUtil}/EmptyMethod.php | 2 +- src/Methods/{Empty => EmptyUtil}/EndEmptyMethod.php | 2 +- .../{Foreach => ForeachUtil}/EndForeachMethod.php | 2 +- .../{Foreach => ForeachUtil}/ForeachMethod.php | 2 +- src/Methods/{Isset => IssetUtil}/EndIssetMethod.php | 2 +- src/Methods/{Isset => IssetUtil}/IssetMethod.php | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) rename src/Methods/{Empty => EmptyUtil}/EmptyMethod.php (90%) rename src/Methods/{Empty => EmptyUtil}/EndEmptyMethod.php (82%) rename src/Methods/{Foreach => ForeachUtil}/EndForeachMethod.php (82%) rename src/Methods/{Foreach => ForeachUtil}/ForeachMethod.php (83%) rename src/Methods/{Isset => IssetUtil}/EndIssetMethod.php (82%) rename src/Methods/{Isset => IssetUtil}/IssetMethod.php (84%) diff --git a/src/Crow.php b/src/Crow.php index c04fbec..6aa8b1f 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -16,20 +16,20 @@ class Crow { * @const DEFAULT_METHODS */ private const DEFAULT_METHODS = [ - 'empty' => Methods\Empty\EmptyMethod::class, - 'endempty' => Methods\Empty\EndEmptyMethod::class, + 'empty' => Methods\EmptyUtil\EmptyMethod::class, // // (Empty) itself causes error, so decided to suffix it. + 'endempty' => Methods\EmptyUtil\EndEmptyMethod::class, // // (Empty) itself causes error, so decided to suffix it. 'for' => Methods\For\ForMethod::class, 'endfor' => Methods\For\EndForMethod::class, - 'foreach' => Methods\Foreach\ForeachMethod::class, - 'endforeach' => Methods\Foreach\EndForeachMethod::class, + 'foreach' => Methods\ForeachUtil\ForeachMethod::class, // // (Foreach) itself causes error, so decided to suffix it. + 'endforeach' => Methods\ForeachUtil\EndForeachMethod::class, // // (Foreach) itself causes error, so decided to suffix it. 'forelse' => Methods\Forelse\ForelseMethod::class, 'endforelse' => Methods\Forelse\EndforelseMethod::class, 'if' => Methods\If\IfMethod::class, 'else' => Methods\If\ElseMethod::class, 'elseif' => Methods\If\ElseIfMethod::class, 'endif' => Methods\If\EndIfMethod::class, - 'isset' => Methods\Isset\IssetMethod::class, - 'endisset' => Methods\Isset\EndIssetMethod::class, + 'isset' => Methods\IssetUtil\IssetMethod::class, // // (Isset) itself causes error, so decided to suffix it. + 'endisset' => Methods\IssetUtil\EndIssetMethod::class, // // (Isset) itself causes error, so decided to suffix it. 'php' => Methods\Php\PhpMethod::class, 'endphp' => Methods\Php\EndPhpMethod::class, 'section' => Methods\Section\SectionMethod::class, diff --git a/src/Methods/Empty/EmptyMethod.php b/src/Methods/EmptyUtil/EmptyMethod.php similarity index 90% rename from src/Methods/Empty/EmptyMethod.php rename to src/Methods/EmptyUtil/EmptyMethod.php index 53afafd..0f84a6a 100644 --- a/src/Methods/Empty/EmptyMethod.php +++ b/src/Methods/EmptyUtil/EmptyMethod.php @@ -1,6 +1,6 @@ Date: Sat, 10 Aug 2024 23:22:27 +0300 Subject: [PATCH 10/21] Solved issue #19: prepared notisset method --- src/Crow.php | 2 ++ src/Methods/Notisset/EndNotissetMethod.php | 14 ++++++++++++++ src/Methods/Notisset/NotissetMethod.php | 14 ++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 src/Methods/Notisset/EndNotissetMethod.php create mode 100644 src/Methods/Notisset/NotissetMethod.php diff --git a/src/Crow.php b/src/Crow.php index 6aa8b1f..168c0ee 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -30,6 +30,8 @@ class Crow { 'endif' => Methods\If\EndIfMethod::class, 'isset' => Methods\IssetUtil\IssetMethod::class, // // (Isset) itself causes error, so decided to suffix it. 'endisset' => Methods\IssetUtil\EndIssetMethod::class, // // (Isset) itself causes error, so decided to suffix it. + 'notisset' => Methods\NotIsset\NotIssetMethod::class, + 'endnotisset' => Methods\NotIsset\EndNotIssetMethod::class, 'php' => Methods\Php\PhpMethod::class, 'endphp' => Methods\Php\EndPhpMethod::class, 'section' => Methods\Section\SectionMethod::class, diff --git a/src/Methods/Notisset/EndNotissetMethod.php b/src/Methods/Notisset/EndNotissetMethod.php new file mode 100644 index 0000000..a9dddda --- /dev/null +++ b/src/Methods/Notisset/EndNotissetMethod.php @@ -0,0 +1,14 @@ +"; + } +} diff --git a/src/Methods/Notisset/NotissetMethod.php b/src/Methods/Notisset/NotissetMethod.php new file mode 100644 index 0000000..6f3e3ed --- /dev/null +++ b/src/Methods/Notisset/NotissetMethod.php @@ -0,0 +1,14 @@ +"; + } +} \ No newline at end of file From 1a19ac5a81fe5a20512030732b728aa24f6a0b87 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Sat, 17 Aug 2024 21:46:00 +0300 Subject: [PATCH 11/21] fixed prefixing the dot only when passing extension value --- src/FileLoader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FileLoader.php b/src/FileLoader.php index 2a1da2f..41e0986 100644 --- a/src/FileLoader.php +++ b/src/FileLoader.php @@ -79,8 +79,8 @@ private function getFilePath(string $file, string $path = null) { $path ??= $this->defaultPath ?? ''; $extension = $this->extension ?? ''; $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; - $extension = str_ends_with($extension, '.php') ? rtrim($extension, '.php') : $extension; + $extension = str_ends_with($extension, '.php') ? '.' . rtrim($extension, '.php') : $extension; - return "{$path}/{$file}.{$extension}.php"; + return "{$path}/{$file}{$extension}.php"; } } From 33e9dd5906745216ccc4bf692f94108c2df8b2e8 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Sun, 18 Aug 2024 16:48:48 +0300 Subject: [PATCH 12/21] prepared new two static constants: $global to bypass the $this to be used in the views (issue #20), $viewbag to bypass variables globally through all the engine (issue #21). --- src/Component.php | 2 +- src/Crow.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Component.php b/src/Component.php index 43c37b1..62f2aef 100644 --- a/src/Component.php +++ b/src/Component.php @@ -85,7 +85,7 @@ protected function view(string $file, array $data = [], $extension = null): void $extension ??= $this->extension; $oldExt = Crow::getExtension(); - + Crow::setExtension($extension); Crow::render($file, $data, $this->templatesPath); Crow::setExtension($oldExt); diff --git a/src/Crow.php b/src/Crow.php index 168c0ee..11f4853 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -96,6 +96,22 @@ class Crow { */ private static array $renderQueue = []; + /** + * Globalize main object instance + * @var object + */ + public static $global = []; + + /** + * Globalize array of variables + * @var array + */ + public static $viewbag = []; + + public static function setViewbag(array $viewbag): void { + self::$viewbag = [... self::$viewbag, ...$viewbag]; + } + /** * @param string $file * @param array $data @@ -135,10 +151,12 @@ public static function render(string $file, array $data = [], ?string $path = nu } extract($data); + extract(self::$viewbag); eval ("?>$__crowTemplateCode Date: Sun, 18 Aug 2024 16:57:12 +0300 Subject: [PATCH 13/21] fixed attributes regex parsing --- src/ComponentConverter.php | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/ComponentConverter.php b/src/ComponentConverter.php index 4660007..8fd4af8 100644 --- a/src/ComponentConverter.php +++ b/src/ComponentConverter.php @@ -116,21 +116,16 @@ private function attrsStringToArrayCode(?string $componentAttrs): string { $code = '['; if (!is_null($componentAttrs)) { - // $re = '/((:?)((\w|-)+))(="((?:[^"]++|\g<4>)(.*?))")?/s'; // origin regex - $re = '/((:?)((\w|-)+))=["\']((?:[^"\'\\\\]|\\\\.)*?)["\']/s'; + $re = '/(:?\w+)(=("[^"]+"))?/s'; preg_match_all($re, $componentAttrs, $matches, PREG_SET_ORDER); foreach ($matches as $match) { - $index = $match[3]; //$this->dashToCamelCase($match[3]); - $value = "''"; + $has_placeholder = str_starts_with($match[1], ':'); + $index = $has_placeholder ? substr($match[1], 1) : $match[1]; // $this->dashToCamelCase($match[1]); + $value = $match[3] ? ($has_placeholder ? trim($match[3], "\"'") : $match[3]) : "''"; - if (!empty($match[5])) { - $value = $match[5]; - $value = empty($match[2]) ? "'{$value}'" : $value; - } - - $code .= "'$index' => $value,"; + $code .= "'$index' => $value, "; } } From f804cabd6c7128da48b7a63f4cfbb797670e090e Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Mon, 19 Aug 2024 00:10:17 +0300 Subject: [PATCH 14/21] fixed passing arrays and objects as attributes parameters --- src/Component.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Component.php b/src/Component.php index 62f2aef..9f321b2 100644 --- a/src/Component.php +++ b/src/Component.php @@ -43,7 +43,12 @@ public function getContents(): ?string { protected function getAttributesParsed() { $attrs = ""; - foreach ($this->getAttributes() as $a => $v) { $attrs .= "{$a}='{$v}' "; } + + foreach ($this->getAttributes() as $a => $v) { + $v = in_array(gettype($v), ["array","object"]) ? json_encode($v, JSON_UNESCAPED_UNICODE) : $v; + $attrs .= "{$a}='{$v}' "; + } + return $attrs; } From 3e087c3355a7ffe301cdfafc222d327f0f17c352 Mon Sep 17 00:00:00 2001 From: Mohammad Nael Dahman Date: Wed, 28 Aug 2024 01:54:21 +0300 Subject: [PATCH 15/21] fixed issue #23: improved multilines comment block --- src/CodeConverter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CodeConverter.php b/src/CodeConverter.php index f49d1bb..e689a76 100644 --- a/src/CodeConverter.php +++ b/src/CodeConverter.php @@ -64,7 +64,8 @@ private function convertUnescaped(string &$templateCode): void { */ private function convertComments(string &$templateCode): void { $templateCode = preg_replace( - '/{{--(.*?)--}}/', + // '/{{--(.*?)--}}/', + '/({{--.?)((.|\n)*)(.?--}})/', '', $templateCode ); From 7cb5372e492134e00b75492534594879e191c19f Mon Sep 17 00:00:00 2001 From: Nael Dahman Date: Fri, 14 Feb 2025 01:02:21 +0300 Subject: [PATCH 16/21] fixed issue #5 by Crow owner but still need to avoid using `disableCodeMinifying()` --- src/Crow.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Crow.php b/src/Crow.php index 11f4853..20b2b0d 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -370,6 +370,7 @@ private static function minify(string &$code): void { $code = str_replace(["\t", "\n", "\r"], ' ', $code); $code = preg_replace('/\s{2,}/m', ' ', $code); + $code = str_replace('?> Date: Fri, 14 Feb 2025 01:39:25 +0300 Subject: [PATCH 17/21] Revert "fixed issue #5 by Crow owner but still need to avoid using `disableCodeMinifying()`" This reverts commit 7cb5372e492134e00b75492534594879e191c19f. --- src/Crow.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Crow.php b/src/Crow.php index 20b2b0d..11f4853 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -370,7 +370,6 @@ private static function minify(string &$code): void { $code = str_replace(["\t", "\n", "\r"], ' ', $code); $code = preg_replace('/\s{2,}/m', ' ', $code); - $code = str_replace('?> Date: Mon, 31 Mar 2025 14:31:46 +0300 Subject: [PATCH 18/21] fixed added parameter type `null` for php 8.4 compatibility --- src/CodeConverter.php | 2 +- src/Crow.php | 4 ++-- src/FileLoader.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CodeConverter.php b/src/CodeConverter.php index e689a76..3346a98 100644 --- a/src/CodeConverter.php +++ b/src/CodeConverter.php @@ -75,7 +75,7 @@ private function convertComments(string &$templateCode): void { * @param string $templateCode * @return int */ - private function convertMethods(string &$templateCode, string $tag = null): int { + private function convertMethods(string &$templateCode, string|null $tag = null): int { $count = 0; if (is_null($tag)) { diff --git a/src/Crow.php b/src/Crow.php index 11f4853..db00e3c 100644 --- a/src/Crow.php +++ b/src/Crow.php @@ -167,7 +167,7 @@ public static function render(string $file, array $data = [], ?string $path = nu * @return void * @throws Exception */ - public static function addComponentsNamespace(string $namespace, string $prefix = null): void { + public static function addComponentsNamespace(string $namespace, string|null $prefix = null): void { $arguments = [$namespace]; if (!is_null($prefix)) { @@ -193,7 +193,7 @@ public static function addMethod(string $method, string $class): void { * * @return mixed */ - public static function data(string $key = null, mixed $value = null): mixed { + public static function data(string|null $key = null, mixed $value = null): mixed { if (is_null($key) && is_null($value)) return self::$data; if (is_null($value)) return self::$data[$key] ?? null; diff --git a/src/FileLoader.php b/src/FileLoader.php index 41e0986..d597af4 100644 --- a/src/FileLoader.php +++ b/src/FileLoader.php @@ -30,7 +30,7 @@ public function getExtension(): ?string { * @param string|null $path * @return int|false */ - public function getModificationTime(string $file, string $path = null): int|false { + public function getModificationTime(string $file, string|null $path = null): int|false { return filemtime($this->getFilePath($file, $path)); } @@ -42,7 +42,7 @@ public function getModificationTime(string $file, string $path = null): int|fals * @return string * @throws Exception */ - public function load(string $file, string $path = null): string { + public function load(string $file, string|null $path = null): string { $filename = $this->getFilePath($file, $path); if (!is_file($filename) || !is_readable($filename)) { @@ -75,7 +75,7 @@ public function setExtension(?string $extension): FileLoader { * @param string|null $path * @return string */ - private function getFilePath(string $file, string $path = null) { + private function getFilePath(string $file, string|null $path = null) { $path ??= $this->defaultPath ?? ''; $extension = $this->extension ?? ''; $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; From 88a97a090e753f88b305d7b08d2d8b5bbd085024 Mon Sep 17 00:00:00 2001 From: Nael Dahman Date: Fri, 4 Apr 2025 03:07:25 +0300 Subject: [PATCH 19/21] fixed comments regex detection --- src/CodeConverter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CodeConverter.php b/src/CodeConverter.php index 3346a98..583e519 100644 --- a/src/CodeConverter.php +++ b/src/CodeConverter.php @@ -64,8 +64,7 @@ private function convertUnescaped(string &$templateCode): void { */ private function convertComments(string &$templateCode): void { $templateCode = preg_replace( - // '/{{--(.*?)--}}/', - '/({{--.?)((.|\n)*)(.?--}})/', + '/{{--(.*?)--}}/s', '', $templateCode ); From 63b274f544bab8ab38442be7421eb2c73dd09a64 Mon Sep 17 00:00:00 2001 From: Nael Dahman Date: Sun, 25 May 2025 00:15:58 +0300 Subject: [PATCH 20/21] Fix comment conversion regex to handle whitespace in template engine comments --- src/CodeConverter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CodeConverter.php b/src/CodeConverter.php index 583e519..ce3502b 100644 --- a/src/CodeConverter.php +++ b/src/CodeConverter.php @@ -64,7 +64,8 @@ private function convertUnescaped(string &$templateCode): void { */ private function convertComments(string &$templateCode): void { $templateCode = preg_replace( - '/{{--(.*?)--}}/s', + // '/{{--(.*?)--}}/s', // old + '/{{--\s*(.*?)\s*--}}/s', '', $templateCode ); From eb09b4a6aeee0b5555e6fa57f244b5d1dd737e72 Mon Sep 17 00:00:00 2001 From: Nael Dahman Date: Sat, 1 Nov 2025 03:10:08 +0300 Subject: [PATCH 21/21] Refactor getFilePath to handle file extensions --- src/FileLoader.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/FileLoader.php b/src/FileLoader.php index d597af4..705840f 100644 --- a/src/FileLoader.php +++ b/src/FileLoader.php @@ -79,7 +79,9 @@ private function getFilePath(string $file, string|null $path = null) { $path ??= $this->defaultPath ?? ''; $extension = $this->extension ?? ''; $extension = str_starts_with($extension, '.') ? substr($extension, 1) : $extension; - $extension = str_ends_with($extension, '.php') ? '.' . rtrim($extension, '.php') : $extension; + $extension = str_ends_with($extension, 'php') ? rtrim($extension, '.php') : $extension; + $extension = str_ends_with($extension, '.') ? rtrim($extension, '.') : $extension; + $extension = $extension != '' ? ".{$extension}" : $extension; return "{$path}/{$file}{$extension}.php"; }