From aba66479be093a6e3a8aacbf9fa88718eb3be29e Mon Sep 17 00:00:00 2001 From: Dave Mc Nicoll Date: Thu, 2 Feb 2023 19:38:20 +0000 Subject: [PATCH] - Token name and options are now passed through parse() method --- docs/10-ui-form.md | 16 +++++++ src/Common/UiElement.php | 86 +++++-------------------------------- src/Component/UiMessage.php | 2 +- src/Component/UiPopup.php | 2 +- src/Form/Ui.php | 56 ++++++++++++------------ src/Form/UiForm.php | 71 ++++++++++++++++++------------ src/Form/UiImage.php | 2 +- src/Form/UiInput.php | 2 +- src/Form/UiSelect.php | 2 +- src/Form/UiTextarea.php | 21 +++++---- src/Method/Form.php | 2 +- src/Method/Pagination.php | 2 +- 12 files changed, 114 insertions(+), 150 deletions(-) diff --git a/docs/10-ui-form.md b/docs/10-ui-form.md index b5a8173..262d8da 100644 --- a/docs/10-ui-form.md +++ b/docs/10-ui-form.md @@ -15,4 +15,20 @@ and will typically be rendered such as :
+``` + +### Additional options + +You can now remove the enctype attribute `no-enctype` or the CSRF token `no-csrf` using those option +on the form tag : + +```html +{% ui:form.post.no-enctype.no-csrf "my.form" %} {% endform %} +``` + +and would render as such : + +```html +
+
``` \ No newline at end of file diff --git a/src/Common/UiElement.php b/src/Common/UiElement.php index c271ca3..81dcfaa 100644 --- a/src/Common/UiElement.php +++ b/src/Common/UiElement.php @@ -2,7 +2,7 @@ namespace Picea\Ui\Common; -class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { +class UiElement implements \JsonSerializable { static array $config = []; @@ -37,9 +37,9 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { public string $content = ""; - protected ?UiQuery $kwery = null; - - public function __construct(? string $tag = null) { + public function __construct( + ? string $tag = null + ) { if ( ! static::$config ) { static::pushConfigArray( include(dirname(__FILE__) . "/taglist.php") ); } @@ -54,7 +54,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { static::$config = array_replace_recursive(static::$config, $array); } - public static function createStylesheet(string $href, $attributes = [], $options = []) : self + public static function stylesheet(string $href, $attributes = [], $options = []) : self { return static::create('link', $attributes + [ 'href' => $href, @@ -63,7 +63,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { ], [ 'tag-type' => 'single' ] + $options); } - public static function createScript(string $src, array $attributes = [], array $options = []) : self + public static function script(string $src, array $attributes = [], array $options = []) : self { return static::create('script', $attributes + [ 'src' => $src, @@ -71,7 +71,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { ], $options); } - public static function createPhp(array $attributes = [], array $options = []) : self + public static function php(array $attributes = [], array $options = []) : self { return static::create('', $attributes, [ 'force-tag-open' => 'childs as $item ) { if ( is_object($item) ) { $content .= $item->render(); @@ -259,7 +259,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { { return $this->insert( static::INSERT_MODE_PREPEND, ...( is_array($arguments) ? array_reverse($arguments) : $arguments) ); } - + protected function insert(int $mode, ...$elements) : self { foreach($elements as $item) { @@ -267,13 +267,13 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { case static::INSERT_MODE_APPEND: array_push($this->childs, $item); break; - + case static::INSERT_MODE_PREPEND: array_unshift($this->childs, $item); break; } } - + return $this; } @@ -327,7 +327,6 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { */ public function css(...$arguments) { foreach($arguments as $item) { - if ( is_array($item) ) { foreach($item as $key => $value) { $this->css($key, $value); @@ -346,10 +345,6 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { return array_search(strtolower($className), array_map('strtolower', $this->attributes['class']), true); } - public function delete() { - - } - public function count() { return count($this->childs); } @@ -364,65 +359,6 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable { ]; } - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) { - if ( is_numeric($offset) ) { - return $this->selected[$offset] = $value; - } - elseif ( is_null($offset) ) { - return $this->childs[] = $value; - } - else { - return $this->childs[$offset] = $value; - } - } - - public function offsetExists($query) : bool - { - return count($this->kwery()->find($query)) > 0; - } - - public function offsetUnset($query) : void - { - $this->kwery()->find($query)->remove(); - } - - public function offsetGet($query) : self - { - return $this->kwery()->find($query); - } - - public function rewind() : void - { - reset($this->childs); - } - - public function current() : self - { - return current($this->childs); - } - - public function key() : int - { - return key($this->childs); - } - - #[\ReturnTypeWillChange] - public function next() : self - { - return next($this->childs); - } - - public function valid() : bool - { - return ! in_array(key($this->childs), [ NULL, FALSE ], true); - } - - public static function isNode($obj) : bool - { - return $obj instanceof UiElement; - } - public function __toString() : string { return $this->render(); diff --git a/src/Component/UiMessage.php b/src/Component/UiMessage.php index bb23f60..4bf9fa7 100644 --- a/src/Component/UiMessage.php +++ b/src/Component/UiMessage.php @@ -17,7 +17,7 @@ class UiMessage extends UiElement implements Extension { 'class' => 'ui-message', ]; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { return ""; } diff --git a/src/Component/UiPopup.php b/src/Component/UiPopup.php index bbb42ba..0323f7f 100644 --- a/src/Component/UiPopup.php +++ b/src/Component/UiPopup.php @@ -17,7 +17,7 @@ class UiPopup extends UiElement implements Extension { 'class' => 'ui-popup', ]; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { return "buildAttributes($arguments) . '\"' ?>"; } diff --git a/src/Form/Ui.php b/src/Form/Ui.php index df22c23..ca004d4 100644 --- a/src/Form/Ui.php +++ b/src/Form/Ui.php @@ -17,105 +17,103 @@ class Ui extends UiElement implements Extension { protected string $name; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { - $opt = $context->tokenOptions($token); - switch(true) { - case in_array('checkbox', $opt): + case in_array('checkbox', $options): $input = new UiCheckbox(); break; - case in_array('color', $opt): + case in_array('color', $options): $input = new UiColor(); break; - case in_array('date', $opt): + case in_array('date', $options): $input = new UiDate(); break; - case in_array('datetime', $opt): + case in_array('datetime', $options): $input = new UiDatetime(); break; - case in_array('email', $opt): + case in_array('email', $options): $input = new UiEmail(); break; - case in_array('file', $opt): + case in_array('file', $options): $input = new UiFile(); break; - case in_array('form', $opt): - case in_array('endform', $opt): + case in_array('form', $options): + case in_array('endform', $options): $input = new UiForm(); break; - case in_array('hidden', $opt): + case in_array('hidden', $options): $input = new UiHidden(); break; - case in_array('image', $opt): + case in_array('image', $options): $input = new UiImage(); break; - case in_array('input', $opt): + case in_array('input', $options): $input = new UiInput(); break; - case in_array('numeric', $opt): + case in_array('numeric', $options): $input = new UiNumeric(); break; - case in_array('password', $opt): + case in_array('password', $options): $input = new UiPassword(); break; - case in_array('radio', $opt): + case in_array('radio', $options): $input = new UiRadio(); break; - case in_array('range', $opt): + case in_array('range', $options): $input = new UiRange(); break; - case in_array('search', $opt): + case in_array('search', $options): $input = new UiSearch(); break; - case in_array('select', $opt): + case in_array('select', $options): $input = new UiSelect(); break; - case in_array('tel', $opt): + case in_array('tel', $options): $input = new UiTel(); break; - case in_array('text', $opt): + case in_array('text', $options): $input = new UiText(); break; - case in_array('textarea', $opt): + case in_array('textarea', $options): $input = new UiTextarea(); break; - case in_array('time', $opt): + case in_array('time', $options): $input = new UiText(); break; - case in_array('url', $opt): + case in_array('url', $options): $input = new UiUrl(); break; - case in_array('week', $opt): + case in_array('week', $options): $input = new UiWeek(); break; - case in_array('popup', $opt): + case in_array('popup', $options): $input = new UiPopup(); break; - case in_array('message', $opt): + case in_array('message', $options): $input = new UiMessage(); break; } @@ -124,6 +122,6 @@ class Ui extends UiElement implements Extension { throw new \Exception("Missing token ? $token"); } - return $input->parse($context, $arguments, $token); + return $input->parse($context, $arguments, $token, $options); } } diff --git a/src/Form/UiForm.php b/src/Form/UiForm.php index 198b430..c8f5b45 100644 --- a/src/Form/UiForm.php +++ b/src/Form/UiForm.php @@ -11,7 +11,7 @@ class UiForm extends UiElement implements Extension { public string $defaultMethod = "get"; - public array $token = [ "ui:form", "ui:endform" /*, "ui:form.get", "ui:form.post", "ui:form.patch", "ui:form.delete", "ui:form.put"*/ ]; + public array $token = [ "ui:form", "ui:endform" ]; public string $tag = "form"; @@ -19,43 +19,53 @@ class UiForm extends UiElement implements Extension { 'class' => 'ui-form', ]; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function __construct( + public bool $enctype = true, + public bool $csrf = true, + ) { + parent::__construct(null); + } + + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { + $constructor = []; + switch($token) { case 'ui:endform': return ""; } - $opt = $context->tokenOptions($token); + if (in_array('no-enctype', $options)) { + $constructor[] = "enctype: false"; + } - if (in_array('get', $opt)) { + if (in_array('no-csrf', $options)) { + $constructor[] = "csrf: false"; + } + + if (in_array('get', $options)) { $method = "get"; } - elseif (in_array('post', $opt)) { + elseif (in_array('post', $options)) { $method = "post"; } - elseif (in_array('put', $opt)) { + elseif (in_array('put', $options)) { $method = "put"; } - elseif (in_array('delete', $opt)) { + elseif (in_array('delete', $options)) { $method = "delete"; } - elseif (in_array('patch', $opt)) { + elseif (in_array('patch', $options)) { $method = "patch"; } $method ??= $this->defaultMethod; - $opt = var_export($opt, true); + $opt = var_export($options, true); - return "parseOptions($opt)->buildHtml('$method', $arguments) ?>"; - } + $constructor = implode(',', $constructor); - public function parseOptions($options) : self - { - $this->options = $options; - - return $this; + return "buildHtml('$method', $arguments) ?>"; } public function buildHtml(string $method = "get", string $name = "", string $action = "", array $attributes = []) : string @@ -72,21 +82,26 @@ class UiForm extends UiElement implements Extension { $this->attributes([ 'method' => $method, 'action' => $action ] + $attributes); if ( $method !== "get" ) { - $token = md5( $name . microtime()); - $key = "picea-ui:form:{$name}"; - if (count($_SESSION[$key] ?? []) > 100) { - array_shift($_SESSION[$key]); + if ($this->csrf) { + $token = md5($name . microtime()); + $key = "picea-ui:form:{$name}"; + + if (count($_SESSION[$key] ?? []) > 100) { + array_shift($_SESSION[$key]); + } + + $_SESSION[$key][] = $token; + + $this->append((new UiHidden())->attributes([ + 'name' => "picea-ui-form[$name]", + 'value' => $token, + ])); } - $_SESSION[$key][] = $token; - - $this->append( ( new UiHidden() )->attributes([ - 'name' => "picea-ui-form[$name]", - 'value' => $token, - ])); - - $this->attributes([ 'enctype' => "multipart/form-data" ]); + if ($this->enctype) { + $this->attributes([ 'enctype' => "multipart/form-data" ]); + } } return $this->render() . PHP_EOL; diff --git a/src/Form/UiImage.php b/src/Form/UiImage.php index e72ea3c..03f6846 100644 --- a/src/Form/UiImage.php +++ b/src/Form/UiImage.php @@ -21,7 +21,7 @@ class UiImage extends UiElement implements Extension { 'tag-type' => "single", ]; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { return "buildHtml($arguments) ?>"; } diff --git a/src/Form/UiInput.php b/src/Form/UiInput.php index 6646434..f8cd2ce 100644 --- a/src/Form/UiInput.php +++ b/src/Form/UiInput.php @@ -25,7 +25,7 @@ class UiInput extends UiElement implements Extension { protected string $name; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { return "buildHtml($arguments) ?>"; } diff --git a/src/Form/UiSelect.php b/src/Form/UiSelect.php index 70fd69b..3890e87 100644 --- a/src/Form/UiSelect.php +++ b/src/Form/UiSelect.php @@ -17,7 +17,7 @@ class UiSelect extends UiElement implements Extension { 'class' => 'ui-select', ]; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { return "buildHtml($arguments) ?>"; } diff --git a/src/Form/UiTextarea.php b/src/Form/UiTextarea.php index 0c08a9f..6cb5da2 100644 --- a/src/Form/UiTextarea.php +++ b/src/Form/UiTextarea.php @@ -16,22 +16,21 @@ class UiTextarea extends UiInput { protected bool $echoRaw = false; - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string - { - $raw = in_array('raw', $context->tokenOptions($token)) ? 'true' : 'false'; + public function __construct( + public bool $raw = false + ) { + parent::__construct(null); + } - return "echoRaw($raw)->buildHtml($arguments) ?>"; + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string + { + $raw = in_array('raw', $options) ? 'true' : 'false'; + + return "buildHtml($arguments) ?>"; } protected function setValue($value) : void { $this->echoRaw ? $this->html($value) : $this->text($value); } - - public function echoRaw(bool $set) : self - { - $this->echoRaw = $set; - - return $this; - } } diff --git a/src/Method/Form.php b/src/Method/Form.php index b850b2a..c53042e 100644 --- a/src/Method/Form.php +++ b/src/Method/Form.php @@ -25,7 +25,7 @@ class Form implements Extension, FunctionExtension { $this->request = $request; } - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string { } + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { } public function exportFunctions(): array { diff --git a/src/Method/Pagination.php b/src/Method/Pagination.php index 988ba7c..209e01e 100644 --- a/src/Method/Pagination.php +++ b/src/Method/Pagination.php @@ -23,7 +23,7 @@ class Pagination implements Extension, FunctionExtension { $this->request = $request; } - public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string { } + public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { } public function exportFunctions(): array