joomla-framework icon indicating copy to clipboard operation
joomla-framework copied to clipboard

Decouple xml loader from Form

Open florianv opened this issue 11 years ago • 15 comments

The xml format as form definition is hardcoded in the current Form implementation. It should be decoupled so it's possible for example to define forms in json or yaml format.

florianv avatar Dec 03 '13 00:12 florianv

I worked on an implementation that would allow you to use any Registry supported format, but it's hard, because the registry XML format is lacking in many areas.

dongilbert avatar Dec 03 '13 00:12 dongilbert

Also some other classes must be changed, for example https://github.com/joomla/joomla-framework/blob/staging/src/Joomla/Form/Rule.php#L61 depends on SimpleXMLElement

florianv avatar Dec 03 '13 00:12 florianv

:+1:

I guess there are a couple of steps:

  1. Define an internal data structure for a "form".
  2. Devise importers for different data structures.

I'd also argue that we should separate validation out into a new package. I've done a little work on it but I'm not completely happy with it.

eddieajau avatar Dec 03 '13 00:12 eddieajau

A simple interface like this could replace the Rule class I think

<?php

interface RuleInterface
{
    public function isValid($data);
}

Also the Rule class should be called RegexRule

florianv avatar Dec 03 '13 00:12 florianv

@dongilbert @eddieajau Also we need to add the ability to load namespaced fields and rules maybe with a '.' as separator ?

<field type="MyProject.Fields.Integer" />

florianv avatar Dec 03 '13 00:12 florianv

This is what I've used so far:

/**
 * Validator interface.
 *
 * @since  1.0
 */
interface ValidatorInterface
{
    /**
     * Gets the errors if the value was invalid.
     *
     * @return  array[]  An associative array of "Error Code" => "Error Data" values, where "data" is an array.
     *
     * @since   1.0
     */
    public function getErrors();

    /**
     * Checks that the value is valid.
     *
     * @param   scalar  $value  The value to validate.
     *
     * @return  boolean
     *
     * @since   1.0
     */
    public function isValid($value);
}

eddieajau avatar Dec 03 '13 00:12 eddieajau

A good feature would be to be able to retrieve the validation error per field (which is currently impossible). It can be handy to display the error message close to the field.

florianv avatar Dec 03 '13 00:12 florianv

@eddieajau I like this interface. Also, we need translatable error messages.

florianv avatar Dec 03 '13 00:12 florianv

A XSD schema for the xml files could be handy. It would greatly simplify the validation when loading the form and provide autocompletion in most IDE when writing your forms.

florianv avatar Dec 03 '13 00:12 florianv

We have XSD's for our manifests, I think it would be easy to build one for the forms.

dongilbert avatar Dec 03 '13 00:12 dongilbert

Yes. I know PHPStorm can generate a schema from an xml file (it will just need some quick adjustments).

florianv avatar Dec 03 '13 00:12 florianv

So, a sample rule looks like this:

class RangeValidator extends AbstractValidator
{
    /**
     * Error code if the value is invalid.
     *
     * @var    string
     * @since  1.0
     */
    const INVALID = 'RangeInvalid';

    /**
     * Error code for a number that is too low.
     *
     * @var    string
     * @since  1.0
     */
    const TOO_LOW = 'RangeTooLow';

    /**
     * Error code for a number that is too high.
     *
     * @var    string
     * @since  1.0
     */
    const TOO_HIGH = 'RangeTooHigh';

    /**
     * Validates the value.
     *
     * @param   scalar  $value  The value to validate.
     *
     * @return  boolean
     *
     * @since   1.0
     */
    protected function doIsValid($value)
    {
        if (!is_numeric($value))
        {
            $this->addError(self::INVALID);

            return false;
        }

        $min = $this->getOption('min');
        $max = $this->getOption('max');

        if ($min && $value < $min)
        {
            $this->addError(self::TOO_LOW);

            return false;
        }
        elseif ($max && $value > $max)
        {
            $this->addError(self::TOO_HIGH);

            return false;
        }

        return true;
    }
}

You get fixed error strings but it would be trivial for your L10N package to convert them.

eddieajau avatar Dec 03 '13 01:12 eddieajau

It looks nice. :+1:

florianv avatar Dec 03 '13 01:12 florianv

For information there is this library https://github.com/Respect/Validation which has already a lot of rules. https://github.com/Respect/Validation/tree/develop/library/Respect/Validation/Rules It also provides an adapter for zend framework rules.

florianv avatar Dec 08 '13 16:12 florianv

What do you think about having an interface for errors. We could use for Form/ Field or Model

/**
 * Describes an error-aware interface
 */
interface ErrorAwareInterface
{
    /**
     * Set the error.
     *
     * @param  object|Exception
     */
    public function addError($error);

    /**
     * Get the error.
     *
     * @return  object|Exception
     */
    public function popError();
}

piotr-cz avatar Dec 10 '13 14:12 piotr-cz