Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
Dave Mc Nicoll | a34ebaf0df | |
Dave Mc Nicoll | 388b2a70f8 | |
Dave Mc Nicoll | 195586a078 | |
Dave Mc Nicoll | 5e9ad29f3c | |
Dave Mc Nicoll | 1991122c32 | |
Dave Mc Nicoll | 0a7b1cdc12 | |
Dave M. | 804deb69a2 | |
Dave Mc Nicoll | 328a4d282c | |
Dave Mc Nicoll | fd4e30bd42 | |
Dave Mc Nicoll | ea780c697e | |
Dave M. | 6aaa05b37d | |
Dave M. | 72940b3615 | |
Dave M. | aba66479be | |
Dave M. | 77d05ae051 | |
Dave M. | d984ddc540 |
|
@ -6,7 +6,7 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Dave Mc Nicoll",
|
||||
"email": "mcndave@gmail.com"
|
||||
"email": "info@mcnd.ca"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
|
@ -22,5 +22,14 @@
|
|||
"psr-4": {
|
||||
"Picea\\Ui\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"lean": {
|
||||
"autoload": {
|
||||
"definitions": [
|
||||
"meta/definitions.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,20 @@ and will typically be rendered such as :
|
|||
<form class="ui-form" enctype="multipart/form-data" action="$action" method="$method">
|
||||
<input class="ui-hidden" type="hidden" name="picea-ui-form[$name]" value="{ random md5 hash }">
|
||||
</form>
|
||||
```
|
||||
|
||||
### 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
|
||||
<form class="ui-form" action="$action" method="$method">
|
||||
</form>
|
||||
```
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Picea\{ Method\Request };
|
||||
|
||||
use Picea\Extension\{ LanguageExtension, TitleExtension, NumberExtension, UrlExtension };
|
||||
|
||||
use Picea\Ui\{ Method, Ui };
|
||||
|
||||
return [
|
||||
Ui::class => autowire(Ui::class),
|
||||
|
||||
'picea.extensions' => function(\Psr\Container\ContainerInterface $c) {
|
||||
return array_merge([
|
||||
$c->get(LanguageExtension::class),
|
||||
$c->get(TitleExtension::class),
|
||||
$c->get(NumberExtension::class),
|
||||
$c->get(UrlExtension::class),
|
||||
$c->get(Method\Form::class),
|
||||
$c->get(Method\Pagination::class),
|
||||
$c->get(Request::class),
|
||||
], class_exists(\Taxus\Picea\Extension::class) ? [ $c->get(\Taxus\Picea\Extension::class) ] : [],
|
||||
array_map(fn($class) => $c->get($class), $c->get(Lean\Lean::class)->getPiceaExtensions())
|
||||
);
|
||||
},
|
||||
];
|
|
@ -2,20 +2,35 @@
|
|||
|
||||
namespace Picea\Ui\Common;
|
||||
|
||||
class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable {
|
||||
enum UiElementInsertMode
|
||||
{
|
||||
case append;
|
||||
case prepend;
|
||||
}
|
||||
|
||||
static array $config = [];
|
||||
|
||||
const INSERT_MODE_APPEND = 1;
|
||||
const INSERT_MODE_PREPEND = 2;
|
||||
|
||||
public string $tag = 'div';
|
||||
|
||||
public array $attributes = [
|
||||
'style' => [],
|
||||
'class' => [],
|
||||
class UiElement implements \JsonSerializable {
|
||||
public const TAG_CONFIG_OPTIONS = [
|
||||
"!doctype" => [ "attributes" => [ "html" ], "options" => [ "tag-type" => "single" ] ],
|
||||
"js" => [ "tag" => "script", "attributes" => [ "type" => "text/javascript" ] ],
|
||||
"css" => [ "tag" => "link", "attributes" => [ "rel" => "stylesheet" , "type" => "text/css" ] ],
|
||||
"document" => [ "options" => [ "no-tag" => true ] ],
|
||||
"link" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"meta" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"img" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"input" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"br" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"hr" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"iframe" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"area" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"col" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"frame" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"param" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"video" => [ "options" => [ "tag-type" => "single" ] ],
|
||||
"wbr" => [ "options" => [ "tag-type" => "single" ] ]
|
||||
];
|
||||
|
||||
public array $attributes = [ 'style' => [], 'class' => [], ];
|
||||
|
||||
public array $childs = [];
|
||||
|
||||
/**
|
||||
|
@ -33,28 +48,13 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable {
|
|||
|
||||
public array $options = [];
|
||||
|
||||
public $selected = null;
|
||||
|
||||
public string $content = "";
|
||||
|
||||
protected ?UiQuery $kwery = null;
|
||||
public function __construct(
|
||||
public string $tag = "div",
|
||||
) {}
|
||||
|
||||
public function __construct(? string $tag = null) {
|
||||
if ( ! static::$config ) {
|
||||
static::pushConfigArray( include(dirname(__FILE__) . "/taglist.php") );
|
||||
}
|
||||
|
||||
if ($tag !== null) {
|
||||
$this->tag = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
public static function pushConfigArray(array $array) : void
|
||||
{
|
||||
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' => '<?php ',
|
||||
|
@ -108,7 +108,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable {
|
|||
$obj->attributes($attributes);
|
||||
}
|
||||
|
||||
if ( false !== ( $custom = static::$config["tags"][$tag] ?? false ) ) {
|
||||
if ( false !== ( $custom = static::TAG_CONFIG_OPTIONS[strtolower($tag)] ?? false ) ) {
|
||||
if ( $custom['tag'] ?? false ) {
|
||||
$obj->tag = $custom['tag'];
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable {
|
|||
}
|
||||
|
||||
$content = "";
|
||||
|
||||
|
||||
foreach ( $this->childs as $item ) {
|
||||
if ( is_object($item) ) {
|
||||
$content .= $item->render();
|
||||
|
@ -252,28 +252,28 @@ class UiElement implements \ArrayAccess, \Iterator, \JsonSerializable {
|
|||
|
||||
public function append( ...$arguments ) : self
|
||||
{
|
||||
return $this->insert( static::INSERT_MODE_APPEND, ...$arguments);
|
||||
return $this->insert( UiElementInsertMode::append, ...$arguments);
|
||||
}
|
||||
|
||||
public function prepend( ...$arguments ) : self
|
||||
{
|
||||
return $this->insert( static::INSERT_MODE_PREPEND, ...( is_array($arguments) ? array_reverse($arguments) : $arguments) );
|
||||
return $this->insert( UiElementInsertMode::prepend, ...( is_array($arguments) ? array_reverse($arguments) : $arguments) );
|
||||
}
|
||||
|
||||
protected function insert(int $mode, ...$elements) : self
|
||||
|
||||
protected function insert(UiElementInsertMode $mode, ...$elements) : self
|
||||
{
|
||||
foreach($elements as $item) {
|
||||
switch($mode) {
|
||||
case static::INSERT_MODE_APPEND:
|
||||
case UiElementInsertMode::append:
|
||||
array_push($this->childs, $item);
|
||||
break;
|
||||
|
||||
case static::INSERT_MODE_PREPEND:
|
||||
|
||||
case UiElementInsertMode::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();
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
@ -11,13 +11,16 @@ class UiPopup extends UiElement implements Extension {
|
|||
|
||||
public string $token = "ui:popup";
|
||||
|
||||
public string $tag = "div";
|
||||
|
||||
public array $attributes = [
|
||||
'class' => 'ui-popup',
|
||||
];
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
public function __construct(
|
||||
public string $tag = "div",
|
||||
) {}
|
||||
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
return "<?php echo 'ui-popup=\"' . ( new \\" . static::class . "() )->buildAttributes($arguments) . '\"' ?>";
|
||||
}
|
||||
|
|
|
@ -17,113 +17,112 @@ 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('img', $options):
|
||||
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):
|
||||
$input = new UiText();
|
||||
case in_array('time', $options):
|
||||
$input = new UiTime();
|
||||
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;
|
||||
}
|
||||
|
||||
if (empty($input)) {
|
||||
throw new \Exception("Missing token ? $token");
|
||||
throw new \Exception("Missing token ? $token $arguments");
|
||||
}
|
||||
|
||||
return $input->parse($context, $arguments, $token);
|
||||
return $input->parse($context, $arguments, $token, $options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,54 +11,65 @@ 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 string $tag = "form";
|
||||
public array $token = [ "ui:form", "ui:endform" ];
|
||||
|
||||
public array $attributes = [
|
||||
'class' => 'ui-form',
|
||||
];
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
public function __construct(
|
||||
public string $tag = "form",
|
||||
public bool $enctype = true,
|
||||
public bool $csrf = true,
|
||||
) {}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
$constructor = [];
|
||||
|
||||
switch($token) {
|
||||
case 'ui.endform': # bw compat
|
||||
case 'ui:endform':
|
||||
return "</form>";
|
||||
}
|
||||
|
||||
$opt = $context->tokenOptions($token, true);
|
||||
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;
|
||||
|
||||
return "<?php echo ( new \\" . static::class . "() )->parseOptions($opt)->buildHtml('$method', $arguments) ?>";
|
||||
}
|
||||
$opt = var_export($options, true);
|
||||
|
||||
public function parseOptions($options) : self
|
||||
{
|
||||
$this->options = $options;
|
||||
$constructor = implode(',', $constructor);
|
||||
|
||||
return $this;
|
||||
return "<?php echo ( new \\" . static::class . "($constructor) )->buildHtml('$method', $arguments) ?>";
|
||||
}
|
||||
|
||||
public function buildHtml(string $method = "get", string $name = "", string $action = "", array $attributes = []) : string
|
||||
{
|
||||
$method = strtolower($method);
|
||||
# Method passed in arguments take precedents over options
|
||||
$method = strtolower($attributes['method'] ?? $method);
|
||||
|
||||
$this->option('tag-type', 'single');
|
||||
|
||||
|
@ -67,24 +78,29 @@ class UiForm extends UiElement implements Extension {
|
|||
unset($this->attributes['class']);
|
||||
}
|
||||
|
||||
$this->attributes([ 'method' => $method, 'action' => $action ] + $attributes);
|
||||
|
||||
if ( $method !== "get" ) {
|
||||
$token = md5( $name . microtime());
|
||||
$key = "picea-ui:form:{$name}";
|
||||
$this->attributes([ 'action' => $action, 'method' => $method, ] + $attributes);
|
||||
|
||||
if (count($_SESSION[$key] ?? []) > 100) {
|
||||
array_shift($_SESSION[$key]);
|
||||
if ( $method !== "get" ) {
|
||||
|
||||
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;
|
||||
|
|
|
@ -11,8 +11,6 @@ class UiImage extends UiElement implements Extension {
|
|||
|
||||
public array $tokens = [ "ui:img", "ui:image" ];
|
||||
|
||||
public string $tag = "img";
|
||||
|
||||
public array $attributes = [
|
||||
'class' => 'ui-image',
|
||||
];
|
||||
|
@ -21,7 +19,11 @@ class UiImage extends UiElement implements Extension {
|
|||
'tag-type' => "single",
|
||||
];
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
public function __construct(
|
||||
public string $tag = "img",
|
||||
) {}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
return "<?php echo ( new \\" . static::class . "() )->buildHtml($arguments) ?>";
|
||||
}
|
||||
|
|
|
@ -3,16 +3,13 @@
|
|||
namespace Picea\Ui\Form;
|
||||
|
||||
use Picea\Ui\Common\UiElement;
|
||||
use Picea\Extension\Extension;
|
||||
use Picea\Extension\ExtensionTrait;
|
||||
use Picea\Extension\{ Extension, FunctionExtension, ExtensionTrait };
|
||||
|
||||
class UiInput extends UiElement implements Extension {
|
||||
class UiInput extends UiElement implements Extension, FunctionExtension {
|
||||
use ExtensionTrait;
|
||||
|
||||
public string $token = "ui:input";
|
||||
|
||||
public string $tag = "input";
|
||||
|
||||
public array $attributes = [
|
||||
'class' => 'ui-input',
|
||||
];
|
||||
|
@ -21,15 +18,32 @@ class UiInput extends UiElement implements Extension {
|
|||
'tag-type' => "single",
|
||||
];
|
||||
|
||||
protected /* ? mixed */ $value;
|
||||
protected mixed $value;
|
||||
|
||||
protected string $name;
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
|
||||
public function __construct(
|
||||
public string $tag = "input",
|
||||
) {}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
return "<?php echo ( new \\" . static::class . "() )->buildHtml($arguments) ?>";
|
||||
}
|
||||
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
if ( null === $type = $this->attributes['type'] ?? null ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$key = str_replace('-', '_', 'ui_'. ( $this->attributes['type'] ?? 'text' ));
|
||||
|
||||
return [
|
||||
$key => fn(string $name, mixed $value = null, array $attributes = [], array $options = []) : string => $this->buildHtml($name, $value, $attributes, $options),
|
||||
];
|
||||
}
|
||||
|
||||
public function buildHtml(string $name, mixed $value = null, array $attributes = [], array $options = []) : string
|
||||
{
|
||||
$this->name = $name;
|
||||
|
|
|
@ -13,7 +13,7 @@ class UiRadio extends UiInput {
|
|||
|
||||
protected function objectAttribute() : array
|
||||
{
|
||||
if ( ( $this->options['value'] ?? false ) && ( $this->options['value'] === $this->value ) ) {
|
||||
if ( isset($this->options['value']) && ( $this->options['value'] === $this->value ) ) {
|
||||
return [
|
||||
'checked' => "checked"
|
||||
];
|
||||
|
|
|
@ -11,13 +11,15 @@ class UiSelect extends UiElement implements Extension {
|
|||
|
||||
public string $token = "ui:select";
|
||||
|
||||
public string $tag = "select";
|
||||
|
||||
public array $attributes = [
|
||||
'class' => 'ui-select',
|
||||
];
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
public function __construct(
|
||||
public string $tag = "select",
|
||||
) {}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
return "<?php echo ( new \\" . static::class . "() )->buildHtml($arguments) ?>";
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ class UiTextarea extends UiInput {
|
|||
|
||||
public array $tokens = [ "ui:textarea" ];
|
||||
|
||||
public string $tag = "textarea";
|
||||
|
||||
public array $attributes = [
|
||||
'class' => "ui-textarea",
|
||||
];
|
||||
|
@ -16,21 +14,25 @@ class UiTextarea extends UiInput {
|
|||
|
||||
protected bool $echoRaw = false;
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
public function __construct(
|
||||
public string $tag = "textarea",
|
||||
public bool $raw = false,
|
||||
) {}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||
{
|
||||
$raw = in_array('raw', $context->tokenOptions($token, true)) ? 'true' : 'false';
|
||||
$raw = in_array('raw', $options) ? 'true' : 'false';
|
||||
|
||||
return "<?php echo ( new \\" . static::class . "() )->echoRaw($raw)->buildHtml($arguments) ?>";
|
||||
return "<?php echo ( new \\" . static::class . "(raw: $raw) )->buildHtml($arguments) ?>";
|
||||
}
|
||||
|
||||
protected function setValue($value) : void
|
||||
{
|
||||
$this->echoRaw ? $this->html($value) : $this->text($value);
|
||||
}
|
||||
|
||||
public function echoRaw(bool $set) : self
|
||||
protected function echoRaw(bool $value) : self
|
||||
{
|
||||
$this->echoRaw = $set;
|
||||
$this->echoRaw = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -7,8 +7,10 @@ use Psr\Http\Message\ServerRequestInterface,
|
|||
|
||||
class FormContext implements FormContextInterface
|
||||
{
|
||||
public string $method;
|
||||
|
||||
public string $formName;
|
||||
|
||||
|
||||
public bool $formSent = false;
|
||||
|
||||
public bool $formExecuted = false;
|
||||
|
@ -22,7 +24,9 @@ class FormContext implements FormContextInterface
|
|||
public array $messages = [];
|
||||
|
||||
public bool $skipCsrf = false;
|
||||
|
||||
|
||||
protected array $catchedMethods = [ 'POST', 'PUT', 'PATCH', 'DELETE', ];
|
||||
|
||||
public ServerRequestInterface $request;
|
||||
|
||||
public ? ResponseInterface $response = null;
|
||||
|
@ -37,16 +41,24 @@ class FormContext implements FormContextInterface
|
|||
|
||||
$this->values = $request->getParsedBody() ?: [];
|
||||
|
||||
$this->method = $this->request->getMethod();
|
||||
|
||||
if ( ! $this->values ) {
|
||||
$content = utf8_encode((string) $request->getBody());
|
||||
$content = mb_convert_encoding((string) $request->getBody(), 'UTF-8');
|
||||
|
||||
if ( $content && ( $json = json_decode($content, true) ) ) {
|
||||
$this->values = $json;
|
||||
}
|
||||
}
|
||||
|
||||
$this->fillValues();
|
||||
|
||||
$this->files = $request->getUploadedFiles() ?: [];
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
public function initialize() : void {}
|
||||
|
||||
public function valid() : bool
|
||||
{
|
||||
|
@ -61,12 +73,12 @@ class FormContext implements FormContextInterface
|
|||
|
||||
public function executed() : bool
|
||||
{
|
||||
return $this->formExecuted;
|
||||
return $this->formExecutionStatus === false ? false : $this->formExecuted;
|
||||
}
|
||||
|
||||
public function formSent() : bool
|
||||
{
|
||||
$valid = in_array($this->request->getMethod(), [ 'POST', 'PUT', 'PATCH', 'DELETE', ]);
|
||||
$valid = in_array($this->method, $this->catchedMethods);
|
||||
|
||||
if ( ! $this->skipCsrf && ($this->formName ?? false) ) {
|
||||
$token = $this->get('picea-ui-form')[$this->formName] ?? false;
|
||||
|
@ -87,6 +99,11 @@ class FormContext implements FormContextInterface
|
|||
return $this->formSent = $valid;
|
||||
}
|
||||
|
||||
public function requestMethod() : string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
return $this->set($key, $value);
|
||||
|
@ -131,4 +148,16 @@ class FormContext implements FormContextInterface
|
|||
{
|
||||
$this->messages[] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
protected function fillValues() : void
|
||||
{
|
||||
# Skipping overrides of this particular class vars as a security measure
|
||||
$skipping = array_keys(array_change_key_case(get_class_vars(FormContext::class), CASE_LOWER));
|
||||
|
||||
foreach($this->values as $property => $value) {
|
||||
if ( ! in_array(strtolower($property), $skipping) && property_exists($this, $property)) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,4 +6,6 @@ interface FormContextInterface {
|
|||
public function valid() : bool;
|
||||
|
||||
public function formSent() : bool;
|
||||
|
||||
public function requestMethod() : string;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue