Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foundation 5 Adaptation &co. #8

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
229 changes: 156 additions & 73 deletions src/Stevenmaguire/Foundation/FormBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class FormBuilder extends \Illuminate\Html\FormBuilder
{

protected $local_errors;
protected $foundation_labels = [];
protected static $checkbox_count = [];
protected static $radio_count = [];

public function __construct($html, $url, $token, $translator, $errors = null)
{
Expand Down Expand Up @@ -35,164 +38,244 @@ private function getError($name = null)
}

/**
* Create a text input field.
* Create a form input field.
*
* @param string $type
* @param string $name
* @param string $value
* @param array $options
* @return string
*/
public function text($name, $value = NULL, $options = array())
public function input($type, $name, $value = null, $options = array())
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::text($name, $value, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::input($type, $name, $value, $options);
$tags['error'] = $this->getErrorTag($name);
$is_checkable = in_array($type, ['checkbox', 'radio']);
$id = $this->getIdAttribute($name, $options, $is_checkable);

return $this->renderWithLabel(implode(' ',$tags), $name, $id, $is_checkable);
}

/**
* Create a password input field.
* Create a form textarea field.
*
* @param string $name
* @param string $value
* @param array $options
* @return string
*/
public function password($name, $value = NULL, $options = array())
public function textarea($name, $value = null, $options = array())
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::password($name, $options);
$tags['input'] = parent::textarea($name, $value, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
return $this->renderWithLabel(implode(' ',$tags), $name);
}

/**
* Create a email input field.
* Create a select box field.
*
* @param string $name
* @param string $value
* @param array $list
* @param string $selected
* @param array $options
* @return string
*/
public function email($name, $value = NULL, $options = array())
public function select($name, $list = array(), $selected = null, $options = array())
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::email($name, $value, $options);
$tags['input'] = parent::select($name, $list, $selected, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
return $this->renderWithLabel(implode(' ',$tags), $name);
}

/**
* Create a textarea input.
* Create a label.
*
* @param string $name
* @param string $value
* @param array $options
* @return string
*/
public function textarea($name, $value = null, $options = array())
public function label($name, $value = NULL, $options = array())
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::textarea($name, $value, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
return parent::label($name, $value, $options);
}

/**
* Create a select box field.
* Insert 'error' class in $options array, if error found in session
*
* @param string $name
* @param array $list
* @param string $selected
* @param array $options
* @return string
* @param array $attributes ref
* @return void
*/
public function select($name, $list = array(), $selected = null, $options = array())
private function getErrorClass($name, &$attributes)
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::select($name, $list, $selected, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
// If no error is set we don't need to do anything else
if ( $this->hasError($name) ) {
if ( isset($attributes['class']) )
$attributes['class'] .= ' error';
else
$attributes['class'] = 'error';
}
}

/**
* Create a select range field.
* Create Foundation 5 "error" label.
*
* @param string $name
* @param string $begin
* @param string $end
* @param string $selected
* @param array $options
* @return string
*/
public function selectRange($name, $begin, $end, $selected = null, $options = array())
private function getErrorTag($name)
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::selectRange($name, $begin, $end, $selected, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
return ($this->hasError($name) ? '<span class="error">'.implode(' ', $this->getError($name)).'</span>' :'' );
}

/**
* Create a select month field.
* Create a checkable input field (checkbox/radio).
*
* @param string $type
* @param string $name
* @param string $selected
* @param mixed $value
* @param bool $checked
* @param array $options
* @return string
*/
public function selectMonth($name, $selected = null, $options = array(), $format = '')
protected function checkable($type, $name, $value, $checked, $options)
{
$this->getErrorClass($name,$options);
$tags = array();
$tags['input'] = parent::selectMonth($name, $selected, $options);
$tags['error'] = $this->getErrorTag($name);
return implode('',$tags);
$this->setCheckableAttributeID($type, $name, $options);

return parent::checkable($type, $name, $value, $checked, $options);
}

/**
* Generates an unique ID for a checkable fields, if not already defined,
* this is useful for having a "clickable" label for every checkbox or radio
* item in a group.
*
* @param string $type
* @param string $name
* @param array $attributes ref
*/
private static function setCheckableAttributeID($type, $name, &$attributes)
{
// Do nothing if ID already defined
if ( !empty($attributes['id']) ) {
return;
}

switch ( $type ) {
case 'checkbox':
$id = $name.'-'.self::checkboxCounter($name);
break;

case 'radio':
$id = $name.'-'.self::radioCounter($name);
break;
}

$attributes['id'] = $id;
}

/**
* Create a label.
* Returns the number of checboxes for a given group name
*
* @param string $name
* @param string $value
* @param array $options
* @return string
* @return int
*/
public function label($name, $value = NULL, $options = array())
private static function checkboxCounter($name)
{
$this->getErrorClass($name,$options);
return parent::label($name, $value, $options);
if ( !array_key_exists( $name, self::$checkbox_count ) ) {
self::$checkbox_count[$name] = 0;
}

return self::$checkbox_count[$name]++;
}

/**
* Insert 'error' class in $options array, if error found in session
* Returns the number of radios for a given group name
*
* @param string $name
* @param array $options ref
* @return void
* @return int
*/
private function getErrorClass($name,&$options = array())
private static function radioCounter($name)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have you decided to make these methods static?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because those methods are going to be called from other static methods and the counters need to be shared among all the instances of Form.

{
if (isset($options['class']))
$options['class'] .= ($this->hasError($name) ? ' error' : '');
else if ($this->hasError($name))
$options['class'] = 'error';
if ( !array_key_exists( $name, self::$radio_count ) ) {
self::$radio_count[$name] = 0;
}

return self::$radio_count[$name]++;
}

/**
* Create Foundation 4 "error" label.
* Get the ID attribute for a field name.
*
* @param string $name
* @param array $attributes
* @return string
*/
private function getErrorTag($name)
public function getIdAttribute($name, $options, $checkable_type = null)
{
if ( $checkable_type ) {
self::setCheckableAttributeID($checkable_type, $name, $options);
return $options['id'];
}

return parent::getIdAttribute($name, $options);
}


/**
* Calling method **before** generating the item sets the desired label for
* a form item. *This method is chainable.*
*
* @param string $name
* @param string $value
* @param array $options
* @return FormBuilder
*/
public function withLabel($name, $value = null, $options = array())
{
return ($this->hasError($name) ? '<small class="error">'.implode(' ',$this->getError($name)).'</small>' :'' );
// Comatibility with the old implementation.
$this->labels[] = $name;

$this->foundation_labels[$name] = [
'value' => e($value),
'options' => $options
];

return $this;
}

/**
* Renders an element adding a wrapper label. As suggested Foundation 5:
* [ http://foundation.zurb.com/docs/components/forms.html ]
*/
private function renderWithLabel($html, $name, $id = null, $checkable = FALSE)
{
if ( array_key_exists($name, $this->foundation_labels) ) {
$label_data = $this->foundation_labels[$name];

$this->getErrorClass($name, $label_data['options']);
$rendered_options = $this->html->attributes( $label_data['options'] );
$label = $this->formatLabel($name, $label_data['value'] );

if ($id == null) {
$id = self::getIdAttribute($name, $label_data['options'], $checkable);
}

if ( $checkable ) {
return "<label for='{$id}' {$rendered_options}>{$html}&nbsp;{$label}</label>";
} else {
return "<label for='{$id}' {$rendered_options}>{$label}{$html}</label>";
}
} else {
return $html;
}
}
}