Skip to content

Commit

Permalink
Support for repeatable elements
Browse files Browse the repository at this point in the history
  • Loading branch information
bittrframework committed Jul 3, 2019
1 parent 26ef193 commit 3df7a83
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 62 deletions.
14 changes: 10 additions & 4 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
echo (new Form('index.php'))
->persistWith($_POST) // data to repopulate
->shortTags(['pl' => 'placeholder']) // replace all pl in element attribute as placeholder
->checkbox($name, 'Check', $attributes_arr)
->checkbox($name, $attributes_arr, 'Check')
->hidden($name, $attributes_arr)
->email($name, $attributes_arr, $label)->val('foo@bar.com')
->email('email_address', $attributes_arr, $label)->val('foo@bar.com')
->password($name, $attributes_arr, $label)
->text($name, $attributes_arr, $label)
->color($name, $attributes_arr, $label)
Expand All @@ -40,7 +40,7 @@
->image($name, $source, $attributes_arr, $label)
->month($name, $attributes_arr, $label)
->number($name, $attributes_arr, $label)
->radio($name, 'Click', $attributes_arr)
->radio($name, $attributes_arr, 'Click')
->range($name, $attributes_arr, $label)
->reset($attributes_arr)
->search($name, $attributes_arr, $label)
Expand All @@ -52,8 +52,14 @@
->datalist($name, range(1, 10), $attributes_arr)
->textarea($name, $attributes_arr, $label)
->output($name, $attributes_arr, $label)
->repeatable(2, function (Form $form) {
$form->html('<div class="sdsd">')
->text('name[]')
->select('range[]', range(1, 3), [], true, true)
->html('</div>');
})
->label('custom', 'your custom input')
->text('remove')
->progress($value, $max_val)->move('email')
->progress($value, $max_val)->move('email_address')
->remove('remove')
->bSubmit("Submit");
193 changes: 135 additions & 58 deletions src/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@

namespace Bittr;

use Closure;
use Exception;
use Throwable;

class Form
{
/** @var array */
Expand Down Expand Up @@ -90,7 +94,7 @@ public function __construct(string $action = null, string $method = null, array
* Set behaviour attributes.
*
* @param array $persist_value
* @return \Form
* @return Form
*/
public function persistWith(array $persist_value): Form
{
Expand Down Expand Up @@ -317,7 +321,7 @@ public function month(string $name, array $attr = [], bool $label = true): Form
* @param array $options
* @param array $attr
* @param bool $label
* @return \Form
* @return Form
*/
public function datalist(string $name, array $options, array $attr = [], bool $label = true): Form
{
Expand Down Expand Up @@ -478,6 +482,7 @@ public function week(string $name, array $attr = [], bool $label = true): Form
* @param array $options
* @param array $attr
* @param bool $label
* @param bool $use_key_as_value
* @return Form
*/
public function select(
Expand All @@ -503,11 +508,11 @@ public function select(
}

$this->buffer[] = $attr + [
'name' => $name,
'tag' => 'select',
'options' => [$options, $selected, $disabled, $use_key_as_value],
'l' => $label
];
'name' => $name,
'tag' => 'select',
'options' => [$options, $selected, $disabled, $use_key_as_value],
'l' => $label
];

return $this;
}
Expand Down Expand Up @@ -674,7 +679,7 @@ public function html(string $element): Form
* Adds short replacement for HTML attributes.
*
* @param array $array
* @return \Form
* @return Form
*/
public function shortTags(array $array): Form
{
Expand All @@ -683,6 +688,23 @@ public function shortTags(array $array): Form
return $this;
}

/**
* Repeats a set of methods for a giving multiplier.
*
* @param int $multiplier
* @param \Closure $repeat
* @return Form
*/
public function repeatable(int $multiplier, Closure $repeat): Form
{
while ($multiplier--)
{
$repeat($this);
}

return $this;
}

/**
* Make defined selected option attribute from array.
*
Expand All @@ -702,10 +724,11 @@ private function makeOpt(array $params): string
}

$attr .= "\n\t<option value=\"{$val}\"";
if ($selected == $val)
if ($selected === $val)
{
$attr .= ' selected';
}

if (in_array($val, $disabled))
{
$attr .= ' disabled';
Expand All @@ -717,6 +740,47 @@ private function makeOpt(array $params): string
}


/**
* Extracts value from persistent post.
*
* @param string $name
* @param mixed $value A reference to new value.
* @return bool false if name does not exist in post array
*/
private function extractValue(string $name, &$value)
{
$nesting = 0;
if (preg_match('/(\w+)(\[.*\])/', $name, $matches))
{
$name = $matches[1];
$nesting = strlen($matches[2]);
}

if (isset($this->post[$name]))
{
if ($nesting == 2)
{
$value = array_shift($this->post[$name]);
}
elseif ($nesting == 4)
{
foreach ($this->post[$name] as $key => $value)
{
$value = array_shift($this->post[$name][$key]);
}
}
else
{
$value = $this->post[$name];
}

return true;
}

return false;
}


/**
* Create element attributes from array.
*
Expand All @@ -729,10 +793,9 @@ private function makeAttr(array $attributes, bool $val = true): string
$attr = '';
if ($val && ! $this->val && isset($attributes['name']))
{
$name = $attributes['name'];
if (isset($this->post[$name]))
$value = '';
if ($this->extractValue($attributes['name'], $value))
{
$value = $this->post[$name];
$typed = isset($attributes['type']);
if ($typed && $attributes['type'] == 'radio')
{
Expand Down Expand Up @@ -798,7 +861,8 @@ public function token(array $attr, string $name, string $value): Form
*
* @param string $before
* @param int|null $index
* @return \Bittr\Form
* @return Form
* @throws \Exception
*/
public function move(string $before = null, int $index = null): Form
{
Expand All @@ -814,6 +878,11 @@ public function move(string $before = null, int $index = null): Form
}
}

if (! $index || ! isset($this->buffer[$index]))
{
throw new Exception('Invalid move index');
}

$last = array_pop($this->buffer);
array_splice($this->buffer, $index, 0, [$last]);

Expand Down Expand Up @@ -851,65 +920,73 @@ public function remove(string $name = null, int $index = null): Form
*/
public function __toString(): string
{
$form = '';
$this->val = empty($this->post);

foreach ($this->buffer as $el)
try
{
if (! empty($el['l']))
{
unset($el['l']);
$name = str_replace(['[', ']'], '', $el['name']);
$label = implode(' ', array_map('ucfirst', explode('_', $name)));
$form .= "<label>{$label}</label>";
}
$form = '';
$this->val = empty($this->post);

if (! isset($el['tag']))
foreach ($this->buffer as $el)
{
$form .= "<input{$this->makeAttr($el)}/>\n";
}
elseif ($el['tag'] == 'select' || $el['tag'] == 'datalist')
{
$opts = $el['options'];
$tag = $el['tag'];
unset($el['tag'], $el['options']);
if (isset($el['name']) && ! $this->val && isset($this->post[$el['name']]))
if (! empty($el['l']))
{
$opts[1] = $this->post[$el['name']];
unset($el['l']);
$name = str_replace(['[', ']'], '', $el['name']);
$label = implode(' ', array_map('ucfirst', explode('_', $name)));
$form .= "<label>{$label}</label>";
}

$form .= "<{$tag}{$this->makeAttr($el, false)}>{$this->makeOpt($opts)}</{$tag}>\n";
}
elseif (isset($el['content']))
{
$tag = $el['tag'];
$cont = $el['content'];
unset($el['tag'], $el['content']);
if (isset($el['name']) && ! $this->val && isset($this->post[$el['name']]))
if (! isset($el['tag']))
{
$cont = $this->post[$el['name']];
$form .= "<input{$this->makeAttr($el)}/>\n";
}
elseif ($el['tag'] == 'select' || $el['tag'] == 'datalist')
{
$opts = $el['options'];
$tag = $el['tag'];
unset($el['tag'], $el['options']);

$form .= "<{$tag}{$this->makeAttr($el, false)}>{$cont}</{$tag}>\n";
}
elseif ($el['tag'] == 'raw')
{
$form .= "{$el[0]}\n";
if (isset($el['name']) && ! $this->val)
{
$this->extractValue($el['name'], $opts[1]);
}

$form .= "<{$tag}{$this->makeAttr($el, false)}>{$this->makeOpt($opts)}</{$tag}>\n";
}
elseif (isset($el['content']))
{
$tag = $el['tag'];
$cont = $el['content'];
unset($el['tag'], $el['content']);
if (isset($el['name']) && ! $this->val && isset($this->post[$el['name']]))
{
$cont = $this->post[$el['name']];
}

$form .= "<{$tag}{$this->makeAttr($el, false)}>{$cont}</{$tag}>\n";
}
elseif ($el['tag'] == 'raw')
{
$form .= "{$el[0]}\n";
}
else
{
$tag = $el['tag'];
unset($el['tag']);
$form .= "<{$tag}{$this->makeAttr($el)} />\n";
}
}
else

if (isset($this->form))
{
$tag = $el['tag'];
unset($el['tag']);
$form .= "<{$tag}{$this->makeAttr($el)} />\n";
$form = "<form{$this->makeAttr($this->form)}>{$form}</form>";
}
}
unset($this->buffer);

if (isset($this->form))
return $form;
}
catch (Throwable $throwable)
{
$form = "<form{$this->makeAttr($this->form)}>{$form}</form>";
return $throwable->__toString();
}
unset($this->buffer);

return $form;
}
}

0 comments on commit 3df7a83

Please sign in to comment.