XML element that describes the form field.
*
* @var SimpleXMLElement
* @since 11.1
*/
protected $element;
/**
* The JForm object of the form attached to the form field.
*
* @var JForm
* @since 11.1
*/
protected $form;
/**
* The form control prefix for field names from the JForm object attached to the form field.
*
* @var string
* @since 11.1
*/
protected $formControl;
/**
* The hidden state for the form field.
*
* @var boolean
* @since 11.1
*/
protected $hidden = false;
/**
* True to translate the field label string.
*
* @var boolean
* @since 11.1
*/
protected $translateLabel = true;
/**
* True to translate the field description string.
*
* @var boolean
* @since 11.1
*/
protected $translateDescription = true;
/**
* The document id for the form field.
*
* @var string
* @since 11.1
*/
protected $id;
/**
* The input for the form field.
*
* @var string
* @since 11.1
*/
protected $input;
/**
* The label for the form field.
*
* @var string
* @since 11.1
*/
protected $label;
/**
* The multiple state for the form field. If true then multiple values are allowed for the
* field. Most often used for list field types.
*
* @var boolean
* @since 11.1
*/
protected $multiple = false;
/**
* The name of the form field.
*
* @var string
* @since 11.1
*/
protected $name;
/**
* The name of the field.
*
* @var string
* @since 11.1
*/
protected $fieldname;
/**
* The group of the field.
*
* @var string
* @since 11.1
*/
protected $group;
/**
* The required state for the form field. If true then there must be a value for the field to
* be considered valid.
*
* @var boolean
* @since 11.1
*/
protected $required = false;
/**
* The form field type.
*
* @var string
* @since 11.1
*/
protected $type;
/**
* The validation method for the form field. This value will determine which method is used
* to validate the value for a field.
*
* @var string
* @since 11.1
*/
protected $validate;
/**
* The value of the form field.
*
* @var mixed
* @since 11.1
*/
protected $value;
/**
* The label's CSS class of the form field
*
* @var mixed
* @since 11.1
*/
protected $labelClass;
/**
* The count value for generated name field
*
* @var integer
* @since 11.1
*/
protected static $count = 0;
/**
* The string used for generated fields names
*
* @var string
* @since 11.1
*/
protected static $generated_fieldname = '__field';
/**
* Method to instantiate the form field object.
*
* @param JForm $form The form to attach to the form field object.
*
* @since 11.1
*/
public function __construct($form = null)
{
// If there is a form passed into the constructor set the form and form control properties.
if ($form instanceof JForm)
{
$this->form = $form;
$this->formControl = $form->getFormControl();
}
// Detect the field type if not set
if (!isset($this->type))
{
$parts = JStringNormalise::fromCamelCase(get_called_class(), true);
if ($parts[0] == 'J')
{
$this->type = JString::ucfirst($parts[count($parts) - 1], '_');
}
else
{
$this->type = JString::ucfirst($parts[0], '_') . JString::ucfirst($parts[count($parts) - 1], '_');
}
}
}
/**
* Method to get certain otherwise inaccessible properties from the form field object.
*
* @param string $name The property name for which to the the value.
*
* @return mixed The property value or null.
*
* @since 11.1
*/
public function __get($name)
{
switch ($name)
{
case 'description':
case 'formControl':
case 'hidden':
case 'id':
case 'multiple':
case 'name':
case 'required':
case 'type':
case 'validate':
case 'value':
case 'labelClass':
case 'fieldname':
case 'group':
return $this->$name;
case 'input':
// If the input hasn't yet been generated, generate it.
if (empty($this->input))
{
$this->input = $this->getInput();
}
return $this->input;
case 'label':
// If the label hasn't yet been generated, generate it.
if (empty($this->label))
{
$this->label = $this->getLabel();
}
return $this->label;
case 'title':
return $this->getTitle();
}
return null;
}
/**
* Method to attach a JForm object to the field.
*
* @param JForm $form The JForm object to attach to the form field.
*
* @return JFormField The form field object so that the method can be used in a chain.
*
* @since 11.1
*/
public function setForm(JForm $form)
{
$this->form = $form;
$this->formControl = $form->getFormControl();
return $this;
}
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object representing the tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
*
* @return boolean True on success.
*
* @since 11.1
*/
public function setup(SimpleXMLElement $element, $value, $group = null)
{
// Make sure there is a valid JFormField XML element.
if ((string) $element->getName() != 'field')
{
return false;
}
// Reset the input and label values.
$this->input = null;
$this->label = null;
// Set the XML element object.
$this->element = $element;
// Get some important attributes from the form field element.
$class = (string) $element['class'];
$id = (string) $element['id'];
$multiple = (string) $element['multiple'];
$name = (string) $element['name'];
$required = (string) $element['required'];
// Set the required and validation options.
$this->required = ($required == 'true' || $required == 'required' || $required == '1');
$this->validate = (string) $element['validate'];
// Add the required class if the field is required.
if ($this->required)
{
if ($class)
{
if (strpos($class, 'required') === false)
{
$this->element['class'] = $class . ' required';
}
}
else
{
$this->element['class'] = 'required';
}
}
// Set the multiple values option.
$this->multiple = ($multiple == 'true' || $multiple == 'multiple');
// Allow for field classes to force the multiple values option.
if (isset($this->forceMultiple))
{
$this->multiple = (bool) $this->forceMultiple;
}
// Set the field description text.
$this->description = (string) $element['description'];
// Set the visibility.
$this->hidden = ((string) $element['type'] == 'hidden' || (string) $element['hidden'] == 'true');
// Determine whether to translate the field label and/or description.
$this->translateLabel = !((string) $this->element['translate_label'] == 'false' || (string) $this->element['translate_label'] == '0');
$this->translateDescription = !((string) $this->element['translate_description'] == 'false'
|| (string) $this->element['translate_description'] == '0');
// Set the group of the field.
$this->group = $group;
// Set the field name and id.
$this->fieldname = $this->getFieldName($name);
$this->name = $this->getName($this->fieldname);
$this->id = $this->getId($id, $this->fieldname);
// Set the field default value.
$this->value = $value;
// Set the CSS class of field label
$this->labelClass = (string) $element['labelclass'];
return true;
}
/**
* Method to get the id used for the field input tag.
*
* @param string $fieldId The field element id.
* @param string $fieldName The field element name.
*
* @return string The id to be used for the field input tag.
*
* @since 11.1
*/
protected function getId($fieldId, $fieldName)
{
$id = '';
// If there is a form control set for the attached form add it first.
if ($this->formControl)
{
$id .= $this->formControl;
}
// If the field is in a group add the group control to the field id.
if ($this->group)
{
// If we already have an id segment add the group control as another level.
if ($id)
{
$id .= '_' . str_replace('.', '_', $this->group);
}
else
{
$id .= str_replace('.', '_', $this->group);
}
}
// If we already have an id segment add the field id/name as another level.
if ($id)
{
$id .= '_' . ($fieldId ? $fieldId : $fieldName);
}
else
{
$id .= ($fieldId ? $fieldId : $fieldName);
}
// Clean up any invalid characters.
$id = preg_replace('#\W#', '_', $id);
return $id;
}
/**
* Method to get the field input markup.
*
* @return string The field input markup.
*
* @since 11.1
*/
abstract protected function getInput();
/**
* Method to get the field title.
*
* @return string The field title.
*
* @since 11.1
*/
protected function getTitle()
{
$title = '';
if ($this->hidden)
{
return $title;
}
// Get the label text from the XML element, defaulting to the element name.
$title = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
$title = $this->translateLabel ? JText::_($title) : $title;
return $title;
}
/**
* Method to get the field label markup.
*
* @return string The field label markup.
*
* @since 11.1
*/
protected function getLabel()
{
$label = '';
if ($this->hidden)
{
return $label;
}
// Get the label text from the XML element, defaulting to the element name.
$text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
$text = $this->translateLabel ? JText::_($text) : $text;
// Build the class for the label.
$class = !empty($this->description) ? 'hasTooltip' : '';
$class = $this->required == true ? $class . ' required' : $class;
$class = !empty($this->labelClass) ? $class . ' ' . $this->labelClass : $class;
// Add the opening label tag and main attributes attributes.
$label .= '';
}
else
{
$label .= '>' . $text . '';
}
return $label;
}
/**
* Method to get the name used for the field input tag.
*
* @param string $fieldName The field element name.
*
* @return string The name to be used for the field input tag.
*
* @since 11.1
*/
protected function getName($fieldName)
{
$name = '';
// If there is a form control set for the attached form add it first.
if ($this->formControl)
{
$name .= $this->formControl;
}
// If the field is in a group add the group control to the field name.
if ($this->group)
{
// If we already have a name segment add the group control as another level.
$groups = explode('.', $this->group);
if ($name)
{
foreach ($groups as $group)
{
$name .= '[' . $group . ']';
}
}
else
{
$name .= array_shift($groups);
foreach ($groups as $group)
{
$name .= '[' . $group . ']';
}
}
}
// If we already have a name segment add the field name as another level.
if ($name)
{
$name .= '[' . $fieldName . ']';
}
else
{
$name .= $fieldName;
}
// If the field should support multiple values add the final array segment.
if ($this->multiple)
{
switch (strtolower((string) $this->element['type']))
{
case 'text':
case 'textarea':
case 'email':
case 'password':
case 'radio':
case 'calendar':
case 'editor':
case 'hidden':
break;
default:
$name .= '[]';
}
}
return $name;
}
/**
* Method to get the field name used.
*
* @param string $fieldName The field element name.
*
* @return string The field name
*
* @since 11.1
*/
protected function getFieldName($fieldName)
{
if ($fieldName)
{
return $fieldName;
}
else
{
self::$count = self::$count + 1;
return self::$generated_fieldname . self::$count;
}
}
}