From: Andrey Kutejko Date: Mon, 18 Aug 2014 19:59:14 +0000 (+0300) Subject: form layout X-Git-Tag: 0.6~192 X-Git-Url: https://git.andy128k.dev/?a=commitdiff_plain;h=9328a36d7ac533ec7164ee9f4fcd379d02873f21;p=ipf.git form layout --- diff --git a/ipf/admin/app.php b/ipf/admin/app.php index 8c74d61..a8651b4 100644 --- a/ipf/admin/app.php +++ b/ipf/admin/app.php @@ -1,5 +1,7 @@ htmlOutput( - '
%2$s %1$s%3$s%4$s
', - '
%s
', - '', - '

%s

', - true, - '
%s
', - false); + return $form->renderLayout(new IPF_Admin_Form_Layout, false); + } +} + +class IPF_Admin_Form_Layout extends IPF_Form_LayoutAdapter +{ + public function startForm($form) + { + $errors = $this->commonErrors($form); + return $this->errors($errors) . + $this->hiddenWidgets($form); + } + + public function startGroup($label) + { + if ($label) + return Tag::div(array('class' => 'form-group-title'), $label)->html(); + else + return ''; + } + + public function field($boundField, $label) + { + if ($boundField->help_text) { + $help_text = Tag::p(array('class' => 'help')) + ->raw($boundField->help_text); + } else { + $help_text = ''; + } + + return $this->errors($boundField->errors) . + Tag::div(array('class' => 'form-row'), + Tag::div() + ->raw($label) + ->raw(' ') + ->raw($boundField->render_w()) + ->append($help_text)); + } + + private function errors($errors) + { + if (!count($errors)) + return ''; + + $ul = Tag::ul(array('class' => 'errorlist')); + foreach ($errors as $err) + $ul->append(Tag::li(null, $err)); + return Tag::div(null, $ul); } } diff --git a/ipf/form.php b/ipf/form.php index 2a803a7..f034d43 100644 --- a/ipf/form.php +++ b/ipf/form.php @@ -1,5 +1,7 @@ errors['__all__'])) ? $this->errors['__all__'] : array(); - array_walk($top_errors, 'IPF_Form_htmlspecialcharsArray'); - return new IPF_Template_SafeString(IPF_Form::renderErrorsAsHTML($top_errors), true); + $hidden = array(); + foreach ($this->fields as $name => $field) + if ($field->widget->is_hidden) + $hidden[] = $name; + return $hidden; } - public function get_top_errors() + public function render_top_errors($raw=false) { - return (isset($this->errors['__all__'])) ? $this->errors['__all__'] : array(); + $errors = IPF_Form::renderErrorsAsHTML($this->get_top_errors()); + if ($raw) + return $errors; + else + return new IPF_Template_SafeString($errors, true); } - - public function htmlOutput($normal_row, $error_row, $row_ender, - $help_text_html, $errors_on_separate_row, $group_title=null, - $extra_js=true) + + public function get_top_errors() { - $top_errors = (isset($this->errors['__all__'])) ? $this->errors['__all__'] : array(); - array_walk($top_errors, 'IPF_Form_htmlspecialcharsArray'); - $output = array(); - $hidden_fields = array(); + return \PFF\Arr::get($this->errors, '__all__', array()); + } + public function renderLayout($layout, $raw=false) + { foreach ($this->field_groups as $field_group) { if (!$field_group['fields']) throw new IPF_Exception('Empty field group.'); @@ -146,31 +152,20 @@ abstract class IPF_Form implements Iterator ); } - if (count($groups)) { - $render_group_title = $group_title ? true : false; - } else { + if (!count($groups)) { $groups = array(array('fields' => $this->fields)); - $render_group_title = false; } + $output = $layout->startForm($this); foreach ($groups as $group) { - if ($render_group_title && isset($group['label'])) - $output[] = sprintf($group_title, $group['label']); + $groupLabel = \PFF\Arr::get($group, 'label', ''); + $output .= $layout->startGroup($groupLabel); foreach ($group['fields'] as $name=>$field) { $bf = new IPF_Form_BoundField($this, $field, $name); - $bf_errors = $bf->errors; - array_walk($bf_errors, 'IPF_Form_htmlspecialcharsArray'); - if ($field->widget->is_hidden) { - foreach ($bf_errors as $_e) { - $top_errors[] = sprintf(__('(Hidden field %1$s) %2$s'), - $name, $_e); - } - $hidden_fields[] = $bf; // Not rendered - } else { - if ($errors_on_separate_row and count($bf_errors)) { - $output[] = sprintf($error_row, IPF_Form::renderErrorsAsHTML($bf_errors)); - } + + if (!$field->widget->is_hidden) { + if (strlen($bf->label) > 0) { $label = htmlspecialchars($bf->label, ENT_COMPAT, 'UTF-8'); if ($this->label_suffix) { @@ -183,49 +178,22 @@ abstract class IPF_Form implements Iterator $label_attrs = array('class'=>'required'); else $label_attrs = array(); - $label = $bf->labelTag($label,$label_attrs); + $label = $bf->labelTagRaw($label, $label_attrs); } else { $label = ''; } - if ($bf->help_text) { - // $bf->help_text can contains HTML and is not - // escaped. - $help_text = sprintf($help_text_html, $bf->help_text); - } else { - $help_text = ''; - } - $errors = ''; - if (!$errors_on_separate_row and count($bf_errors)) { - $errors = IPF_Form::renderErrorsAsHTML($bf_errors); - } - $output[] = sprintf($normal_row, $errors, $label, - $bf->render_w(), $help_text); + + $output .= $layout->field($bf, $label); } } + $output .= $layout->endGroup($groupLabel); } - if (count($top_errors)) { - $errors = sprintf($error_row, IPF_Form::renderErrorsAsHTML($top_errors)); - array_unshift($output, $errors); - } - if (count($hidden_fields)) { - $_tmp = ''; - foreach ($hidden_fields as $hd) { - $_tmp .= $hd->render_w(); - } - if (count($output)) { - $last_row = array_pop($output); - $last_row = substr($last_row, 0, -strlen($row_ender)).$_tmp - .$row_ender; - $output[] = $last_row; - } else { - $output[] = $_tmp; - } - } + $output .= $layout->endForm($this); - if ($extra_js) - $output = array_merge($output, $this->extra_js()); + if (!$raw) + $output = new IPF_Template_SafeString($output, true); - return new IPF_Template_SafeString($this->before_render . implode("\n", $output) . $this->after_render, true); + return $output; } public function extra_js() @@ -236,35 +204,24 @@ abstract class IPF_Form implements Iterator return array_unique($extra_js); } - public function render_p() + public function render_p($raw=false) { - return $this->htmlOutput('

%1$s%2$s %3$s%4$s

', '%s', '

', ' %s', true); + return $form->renderLayout(new IPF_Form_ParagraphLayout, $raw); } - public function render_ul() + public function render_ul($raw=false) { - return $this->htmlOutput('
  • %1$s%2$s %3$s%4$s
  • ', '
  • %s
  • ', '', ' %s', false); + return $form->renderLayout(new IPF_Form_ListLayout, $raw); } - public function render_table() + public function render_table($raw=false) { - return $this->htmlOutput( - '%2$s%1$s%3$s%4$s', - '%s', - '', - '
    %s', - false); + return $form->renderLayout(new IPF_Form_TableLayout, $raw); } - public function render_admin() + public function render_admin($raw=false) { - return $this->htmlOutput( - '
    %2$s %1$s%3$s%4$s
    ', - '
    %s
    ', - '', - '

    %s

    ', - true, - '
    %s
    '); + return $form->renderLayout(new IPF_Admin_Form_Layout, $raw); } function __get($prop) @@ -309,13 +266,12 @@ abstract class IPF_Form implements Iterator public static function renderErrorsAsHTML($errors) { - if (count($errors)==0) + if (!count($errors)) return ''; - $tmp = array(); - foreach ($errors as $err) { - $tmp[] = '
  • '.$err.'
  • '; - } - return ''; + $ul = Tag::ul(array('class' => 'errorlist')); + foreach ($errors as $err) + $ul->append(Tag::li(null, $err)); + return $ul; } } diff --git a/ipf/form/boundfield.php b/ipf/form/boundfield.php index 5794474..df6908f 100644 --- a/ipf/form/boundfield.php +++ b/ipf/form/boundfield.php @@ -1,5 +1,7 @@ render($this->html_name, $this->value(), $attrs); } - public function labelTag($contents=null, $attrs=array()) + public function labelTag($contents=null, $attrs=array(), $raw=false) { - $contents = ($contents) ? $contents : htmlspecialchars($this->label); + $label = Tag::label($attrs); + + if ($contents) + $label->raw($contents); + else + $label->append($this->label); + $widget = $this->field->widget; $id = (isset($widget->attrs['id'])) ? $widget->attrs['id'] : $this->autoId(); - $_tmp = array(); - $class_found = false; - foreach ($attrs as $attr=>$val) { - $_tmp[] = $attr.'="'.$val.'"'; - if ($attr=='class') - $class_found = true; - } - if ( (!$class_found) && ($this->field->required==1)) - $_tmp[] = 'class="req"'; - if (count($_tmp)) { - $attrs = ' '.implode(' ', $_tmp); - } else { - $attrs = ''; - } - return new IPF_Template_SafeString(sprintf('', - $widget->idForLabel($id), $attrs, $contents), true); + + $label->attr('for', $widget->idForLabel($id)); + + if ($this->field->required) + $label->addClass('req'); + + if ($raw) + return $label; + else + return new IPF_Template_SafeString($label, true); } public function autoId() @@ -82,9 +84,13 @@ class IPF_Form_BoundField return ''; } - public function fieldErrors() + public function fieldErrors($raw=false) { - return new IPF_Template_SafeString(IPF_Form::renderErrorsAsHTML($this->errors), true); + $errors = IPF_Form::renderErrorsAsHTML($this->errors); + if ($raw) + return $errors; + else + return new IPF_Template_SafeString($errors, true); } public function __get($prop) diff --git a/ipf/form/layout.php b/ipf/form/layout.php new file mode 100644 index 0000000..fab7043 --- /dev/null +++ b/ipf/form/layout.php @@ -0,0 +1,178 @@ +get_top_errors(); + foreach ($form->hiddenFields() as $field_name) + foreach (\PFF\Arr::get($form->errors, $field_name, array()) as $error) + $commonErrors[] = sprintf(__('(Hidden field %1$s) %2$s'), $field_name, $error); + return $commonErrors; + } + + protected function hiddenWidgets($form) + { + $hiddenWidgets = ''; + foreach ($form->hiddenFields() as $field_name) + $hiddenWidgets .= $form->field($field_name)->render_w(); + return $hiddenWidgets; + } + + private $deferred = ''; + + protected function defer($code) + { + $this->deferred .= $code; + } + + protected function takeDeferred() + { + $deferred = $this->deferred; + $this->deferred = ''; + return $deferred; + } + + protected function errorList($errors) + { + if (!count($errors)) + return ''; + + $ul = Tag::ul(array('class' => 'errorlist')); + foreach ($errors as $err) + $ul->append(Tag::li(null, $err)); + return $ul; + } +} + + +class IPF_Form_ParagraphLayout extends IPF_Form_LayoutAdapter +{ + public function startForm($form) + { + $o = $this->hiddenWidgets($form) . $form->extra_js(); + + $errors = $this->commonErrors($form); + if (count($errors)) + $o .= $this->errorList($errors); + + return $o; + } + + public function field($boundField, $label) + { + return + $this->errorList($boundField->errors) . + Tag::p() + ->raw($label) + ->raw(' ') + ->raw($boundField->render_w()) + ->raw(' ') + ->raw($boundField->help_text); + } +} + + +class IPF_Form_ListLayout extends IPF_Form_LayoutAdapter +{ + public function startForm($form) + { + $this->defer($this->hiddenWidgets($form) . $form->extra_js()); + + $errors = $this->commonErrors($form); + if (count($errors)) + return Tag::li() + ->raw($this->errorList($errors)) + ->raw($this->takeDeferred()); + else + return ''; + } + + public function field($boundField, $label) + { + if ($boundField->help_text) + $help_text = '
    '.$boundField->help_text.''; + else + $help_text = ''; + + return Tag::li() + ->raw($this->takeDeferred()) + ->raw($this->errorList($boundField->errors)) + ->raw($label) + ->raw(' ') + ->raw($boundField->render_w()) + ->raw($help_text); + } + + public function endForm($form) + { + $deferred = $this->deferred(); + if ($deferred) + return Tag::li()->raw($deferred); + else + return ''; + } +} + + +class IPF_Form_TableLayout extends IPF_Form_LayoutAdapter +{ + public function startForm($form) + { + $this->defer($this->hiddenWidgets($form) . $form->extra_js()); + + $errors = $this->commonErrors($form); + if (count($errors)) + return Tag::tr(null, + Tag::td()->attr('colspan', 2) + ->raw($this->errorList($errors)) + ->raw($this->deferred())); + else + return ''; + } + + public function field($boundField, $label) + { + if ($boundField->help_text) + $help_text = '
    '.$boundField->help_text.''; + else + $help_text = ''; + + return Tag::tr(null, + Tag::th() + ->raw($label), + Tag::td() + ->raw($this->takeDeferred()) + ->raw($this->errorList($boundField->errors)) + ->raw($boundField->render_w()) + ->raw($help_text)); + } + + public function endForm($form) + { + $deferred = $this->takeDeferred(); + if ($deferred) + return Tag::tr(null, + Tag::td() + ->raw($deferred)); + else + return ''; + } +} +