Feature/forms #1110

Merged
merged 101 commits into from May 15, 2012

Conversation

Projects
None yet
4 participants
Owner

weierophinney commented Apr 27, 2012

Core infrastructure of Forms RFC now complete, including:

  • InputFilter component, including:
    • Input and InputFilter interfaces
    • Factory for creating the above
  • Form component, including:
    • Element, Fieldset, and Form interfaces and concrete implementations
    • Factory for creating all of the above
    • View helper implementations for core HTML form functionality

Documentation is not yet complete; I'll be working on this in the next week.

@ghost ghost assigned akrabat May 11, 2012

Owner

weierophinney commented May 11, 2012

Rob, I think we're ready for the review finally!

Member

Maks3w commented May 11, 2012

One Zend\Form test fail with PHP 5.4 (http://travis-ci.org/#!/Maks3w/zf2/builds/1302633)

Member

Maks3w commented May 11, 2012

In fact any option value is not rendered properly with any PHP version.

PHP 5.3
Failed asserting that '<select name="foo" id="foo"><option value="v" selected="selected" disabled="disabled">v</option>
<option value="v" selected="selected" disabled="disabled">v</option>
<option value="v" selected="selected" disabled="disabled">v</option></select>' contains "value="value2"".
PHP 5.4
Failed asserting that '<select name="foo" id="foo"><option value=""></option>
<option value=""></option>
<option value=""></option></select>' contains "value="value2"".
Owner

weierophinney commented May 11, 2012

@Maks3w Can you provide code that makes that happen? I've dumped markup from the tests to see what's happening, and everything is coming out flawlessly for me... which either means (a) you've somehow got an old commit, or (b) I need more test cases -- and hence the request for reproduce code. :)

Owner

weierophinney commented May 11, 2012

@macest I've commented on your Nabble posts. Please subscribe to the contributors list - those posts never actually were delivered, and I just saw them based on your comment above.

Owner

weierophinney commented May 11, 2012

Oh, and @Maks3w -- I setup travis for my repo, and now have green for both PHP 5.3 and 5.4. I disabled Dojo tests, as they rely on the old Form code. I'm thinking we'll either need a complete rewrite, or we'll need to remove it.

Member

Maks3w commented May 11, 2012

weierophinney and others added some commits Mar 30, 2012

[zen-46] Created Input interface and implementation
- Wrote tests describing behavior
- Wrote interface for Inputs
- Wrote implementation for Inputs
- Wrote initial tests for InputFilter
[zen-46] Identified all tests for InputFilter, Factory
- Identified unit tests for InputFilter
- Identified unit tests for InputFilter Factory
[zen-46] InputFilter tests
- InputFilter tests are mostly complete. Incomplete tests include:
  - conditional validation (i.e., only validate if another input
    passed/failed/is present, etc)
  - ability to pass context to validators
  - Skip validation of fields marked required when no data is present
  - skip validation of required fields when allow empty is true and no
    value is passed
  - invalid data on to required fields when allow empty is false and
    no value is passed
Added break-on-failure, error-message fields to Input
- Added breakOnFailure flag
- Added errorMessage string
- Added more tests to InputFilter suite
Created InputFilterInterface
- Created InputFilterInterface based on test cases
- Marked one test with a todo -- questioning whether we should change
  the name on an Input, or simply store a hashtable internally
[zen-46] initial implementation of InputFilter
- adding/retrieving input objects
- setting data to validate
- partial isValid() implementation
  - fails tests
  - raises questions about nesting input filters, how to mark empty,
    required elements as invalid so as to receive a message
[zen-46] completed input retrieval
- Completed get(Raw)?Values?() implementations
- All tests now run; failures are for unimplemented functionality around
  partial validation, contextual validation, and retrieval of
  valid/invalid values and error messages
[zen-46] Allow passing context to validators
- Primarily a change in the ValidatorChain, but also a small signature
  chain to the Callback validator to make it clear that context can be
  provided (implementation would already use it)
[zen-46] Added todo item
- How should we deal with required input when data is missing?  should a
  message be returned? if so, what message? Does any message need to be
  returned, as getInvalidInput() will return this input anyways?
[zen-46] Completed factory implementation
- Allows specifying a default filter chain and/or validator chain for
  elements it creates
- Allows creating input objects from specifications
  - Allows creating filters from specifications
  - Allows creating validators from specifications
- Allows creating input filter objects from specifications
- Allows creating nested input filter objects from specifications
- Updated FilterChain to be Pluggable
- Updated ValidatorChain to be Pluggable
[zen-47] Implemented concrete Element class
- Created test cases for Element behavior
- Created initial concrete implementation of Element
[zen-47] Initial tests for Fieldset
- Created initial round of tests for Fieldset
- Altered interface slightly based on usage desired
[zen-47] Completed Fieldset tests
- Completed all behavior use cases
[zen-47] Fieldset implementation
- Moved set/getMessages to ElementInterface
- Full implementation of Fieldset
[zen-47] Identified various behaviors as test cases
- Most marked incomplete at this time
[zen-47] Form tests (mostly) complete
- Complete except for test detailing that input filter from model will
  be used when model is InputFilterAware
- Added Zend\Stdlib\ArraySerializableInterface
- Added "Hydrator" subclass, per Marco Pivetta's suggestion, to allow
  arbitrary hydration of bound objects
  - Created two initial hydrator types: ObjectProperty (public
    properties of the object), ArraySerializable (classes implementing
    above mentioned ArraySerializableInterface)
[zen-47] Completed Form tests
- Added InputFilterAwareInterface; FormInterface now extends it
- Added TestAsset\ValidatingModel
[zen-47] Tests run
- but do not pass. :)
- Ensured all interfaces are properly defined
- Ensured all test assets are properly defined
- Initial work on concrete Form class
[zen-47] Form implementation
- must setData() before calling isValid()
- must isValid() before calling getData()
- hydration only occurs if data is valid
- populate value attributes of all elements/fieldsets when data is set
- allow binding raw values to bound model
- allow retrieving normalized or raw values with no bound model
- allow forcing retrieval of data as array with bound model
- ensure input filter only returns partial set on partial validation
[zen-47] Initial Factory scaffolding
- Created test case file with incomplete tests
- Created stub class file
[zen-47] Element factory
- Implemented element factory functionality
[zen-47] Fieldset factory
- Implemented fieldset factory (Factory::createFieldset())
  - Allows creation of child elements
  - Allows creation of nested fieldsets
[zen-47] Form factory implementation
- Implemented form factory (Factory::createForm())
  - Added accessors for input filter factory, to allow creating the
    input factory attached to a form
  - Allows elements, nested fieldsets, input filter attachment/creation,
    and hydrator specification
[zen-48] Form view helper
- Created base form view helper
  - Handles doctype, escaping
- Created base form view helper testcase
  - Tests doctype, escaping
  - ensures helper broker is seeded correctly
- Created Form view helper
  - includes openTag(FormInterface $form = null) and closeTag() methods
[zen-48] Ensure "id" attribute is present
- If we have a "name" but no "id", set the "id" to the "name"
[zen-47] Rename element to alias
- If providing an alias in the flags when adding an element/fieldset,
  set its name to that alias. This is the only way we can ensure
  rendering will follow the structure provided in the form hierarchy
[zen-48] Created FormLabel view helper tests
- Suggested use cases:
  - echo $this->formLabel()->openTag() . $this->translate('Label for
    element') . $this->formElement($element) .
    $this->formLabel()->closeTag();
  - echo $this->formLabel()->openTag($element) . $this->translate('Label for
    element') . $this->formLabel()->closeTag();
  - echo $this->formLabel($element, $this->translate('Label for element'))
  - echo $this->formLabel($element, $this->formText($element),
    'append')
  - Basic idea is to allow each of the following styles of markup:
    - <label>This is a label:<input type="text" id="foo" /></label>
    - <label for="foo">This is a label:</label> ... <input ... />
    - <label for="foo"><input ... />This is a label:</label>
[zen-48] FormLabel view helper implementation
- Wrote implementation to follow usage defined in tests
- Added getId(ElementInterface $element) to AbstractHelper
[zen-48] Created TODO list
- Shows must haves for beta4
- Details roadmap for additional view helpers in the future
[zen-48] FormInput view helper tests
- Created full test case for FormInput view helper
[zen-48] working FormInput view helper implementation
- Added feature to AbstractHelper to scrub unknown/unwanted attributes
- Added feature to AbstractHelper to cast boolean attribute values to
  appropriate strings
- Added feature to AbstractHelper for retrieving inline tag close string
- Fully working FormInput implementation
- Known issue: changes in AbstractHelper break existing helpers
[zen-48] Added attributes for form, label
- Added accept-charset, action, enctype, for, method, novalidate, target
  to list of valid attributes; fixes failures in Form and FormLabel
  tests
[zen-48] update helper list
- Updated Zend\Form\View\HelperLoader to provide FormInput and FormLabel
[zen-48] Refactored attribute support
- Two lists: validGlobalAttributes, and validTagAttributes
  - validGlobalAttributes are valid for all tag types
  - validTagAttributes will be set by individual extensions to indicate
    additional attributes valid for that tag
- Updated Form, FormLabel, and FormInput implementations and tests
[zen-48] Implemented FormElementErrors view helper
- Creates flat list of all validation messages present in an element
- Allows modifying the markup
[zen-48] Created FormMultiCheckbox helper
- Allows custom separators
- Allows specifying position of label in relation to checkbox
- Will mark boxes checked based on element value
[zen-48] Added FormRadio view helper
- Extends FormMultiCheckbox, and simply redefines getInputType()
[zen-48] Completed FormSelect view helper
- Can create <select> elements with <option> and <optgroup> children
- Labels are rendered as content of an option
- allows disable, selected, and multiple
[zen-48] Updated HelperLoader for Form view helpers
- Added radio, select, and multi-checkbox helpers
Created CSRF validator
- handles session injection and expiration hops
- performs validation against stored session value
Initial refactor of Zend\Captcha
- Renamed interfaces
- Modified interface: s/getDecorator/getHelperName/, removed render()
- Working Captcha\Dumb tests
- Need to complete other captcha tests
Refactored Zend\Captcha
- Removed all rendering capabilities
  - however, has a "getHelperName" to hint to the renderer what helper
    to use
- Created form-specific captcha view helpers for rendering captchas from
  elements
Added FormCaptcha view helper
- Delegates to the view helper returned by $captcha->getHelperName()
[ZF2-290] Do not render false boolean attribute values
- unless "false" is indicated by something other than an empty string
Added Captcha\Factory
- Created to make creating captcha element from factory possible
Created captcha element
- Defines accessor/mutator for captcha adapter (proxying to attribute)
- Allows defining captcha adapter via factory
[zen-12] Created input/filter provider interfaces
- Zend\InputFilter\InputProviderInterface -- to return a specification
  that can be used to create an input for the given object
- Zend\InputFilter\InputFilterProviderInterface -- to return a specification
  that can be used to create an input filter for the given object
[zen-12] loosened type restriction on FieldsetInterface::add()
- Removed typehint of ElementInterface, in order to allow a
  factory-backed fieldset/form implementation
[zen-12] Create factory-backed form implementation
- Moved base form implementation to BaseForm
- Added "create()" method to Factory; allows creating elements,
  fieldsets, or forms, based on "type" parameter provided
- Created FormFactoryAwareInterface, for composing form factories
- Created new "Form" implementation that is factory-backed
  - implements FormFactoryAwareInterface
  - overrides add() to create elements/fieldsets from specs before
    attaching
[zen-12] Initial input marshalling
- Updated InputFilterInterface to define has()
- Form now defines attachInputFilterDefaults(), called from
  getInputFilter()
  - iterates through elements
  - if element implements InputProviderInterface, and input filter does
    not have an input by that name, generates an input from the returned
    specification and attaches to the input filter
- TODO: similar logic for fieldsets (InputFilerProviderInterface)
[zen-12] Developed algorithm for scanning fieldsets for input filters
- If fieldset implements InputFilterProvider
  - do nothing if input filter already has an input/filter for that
    fieldset
  - otherwise, create an input filter from the provided spec and attach
    it to the form input filter with the fieldset name
- If fieldset does not implement InputFilterProvider
  - if there is no input/filter for the fieldset, do nothing
  - if the input for the fieldset is not an input filter, do nothing
  - otherwise, attempt to attach defaults for the elements of the
    fieldset to the input filter for this fieldset
[zen-12] Completed tests for input filter seeding
- will use input specification from element in input filter if no
  matching input found
- will use input filter specification from fieldset in input filter if
  no matching input filter found
- will populate sub-input filter from input specifications on fieldset
  elements
[zen-12] Moved Hydrator from Form to Stdlib component
- Not necessarily specific to forms
[zen-12] Completed Captcha element
- Added InputProviderInterface implementation
  - adds StringTrim filter
  - marks as required
  - adds captcha as validator, if present
[zen-12] Created CSRF element
- Implements InputProviderInterface, attaching its validator
- Uses CSRF validator's hash as value
[zen-12] Created generic FormElement view helper
- introspects element to determine which view helper to delegate
  rendering to.
[zen-12][ZF2-290] Modified tests
- Verify that disabled does not appear anywhere in the markup
  - Also verify this when no disabled attribute is provided at all
[zen-12] Bi-directional bind support
- HydratorInterface now defines extract($object), expecting it to return
  an array of data
- BaseForm::bind() now extracts data from the object and uses it to
  populateValues()
- todo: use bound data as data for validation if setData() has not been
  called
[zen-12] Completed bind() bi-directional support
- If setData() has not been called, but bind() has, use the data from
  the bound model in validations
[zen-12] Fixes based on functional testing
- BaseForm should set $filter to the object's filter, instead of just returning
  it; ensures Form is using the same instance
- Typehint on ValidatorInterface in InputFilter factory, not Validator
[zen-12] allow using populate()
- Allows it to work with Zend\Db row population
[zen-12] added prepare() to Form implementation
- Ensures that any automated scanning that needs to be done is complete;
  currently, this simply means that any scanning for default input is
  performed (thus ensuring validators are attached -- which may be
  necessary for elements like the csrf and captcha elements).
[zen-12] Removed InputFilterAwareInterface from FormInterface
- Instead, define setter/getter for InputFilter (fixes issues with DI)
[zen-12] Working CSRF element
- Use session hash to validate
- Do not initialize CSRF token and session until element value attribute is
  retrieved (either via getAttribute('value') or getAttributes()) -- typically,
  this will only happen when rendering.
[zen-12] Fixes to Captchas
- removed constructor from AbstractAdapter -- let it inherit from
  AbstractValidator to ensure the messages and other information are correctly
  marshalled
[zen-12] Rename InputFilter to BaseInputFilter
- in preparation for a factory-based input filter implementation
[zen-12] Created factory-backed InputFilter implementation
- Composes Factory (lazily, or explicitly)
- add() will create an input using the spec given before passing on to parent
  implementation
[zen-12] Remove old test
- Removed test for render() method of Dumb captcha adapter; render is no
  longer part of the interface or implementation
[zen-12] Removed Dojo from test suite
- Dojo integration largely relied on integration with Zend\Form; removing from
  testing for now, as it has not been refactored to work with the new Zend\Form
  code.
[zen-12] Fix test asset
- Test asset was not in sync with Zend\Session\ManagerInterface
[zen-12] Removed FormCsrf view helper
- Depended on old Zend\Form code
[zen-12] Added test for checked status
- Added a test to ensure no checked attribute is rendered if no radios
  are selected
[zen-12] Fix 5.4 related issue
- Was checking against a key that may not exist; use pre-initialized
  $value instead (more appropriate anyways)
[zen-12] Inject not-empty validator in input
- Injected if required or allow_empty is false; prepended to validator
  chain
Member

Maks3w commented May 12, 2012

@weierophinney please add this assert $this->assertContains('value="value1"', $markup); to this test testRendersMultiElementsAsExpected in ZendTest\Form\View\Helper\FormElementTest

As you can notice this code:

$element->setAttribute('options', array(
            'option' => 'value1',
            'label'  => 'value2',
            'last'   => 'value3',
        ));

should render this output

<option value="value1">option</option>

but render this other output

<option value=""></option>

weierophinney added some commits May 14, 2012

[ZF2-299] allow combining callback options and context
- If we have $context, it should appear immediately following the $value
  when passed to the callback.
[zen-12] Fixes issue with duplicated IDs
- Do not generate id by default, except for form
- If "id" attribute is present in a radio or multi-checkbox, only render
  it for the first in the set
[zen-12] Fixed select rendering
- Allow options of key/value pairs in FormSelect
[zen-12] MultiCheckbox names should append []
- in order to denote array value
[zen-12] Fixes captcha element rendering and validation
- StringTrim no longer attempts to filter non-string values
- word-based captchas now ensure that the id input has the value set to
  the captcha ID
- word-based captchas do not attempt to render the input
[zen-12] BIND_ON_VALIDATE and bindValues()
- Created new method, bindValues(); used to bind values to the bound
  object. It takes the place of hydrate(), and is public. It will fail
  if the form is in an invalid state.
- New flag, bindOnValidate, with two states: BIND_ON_VALIDATE and
  BIND_MANUAL. By default, the former is true, meaning that during
  isValid(), if validation is successful, bindValues() will be called.
  If the flag is set to BIND_MANUAL, you will need to call bindValues()
  yourself.
[zen-12] Ensure ID is rendered once for radio, multi-checkbox
- Ensures ID is rendered exactly once for radio and multi-checkbox
  elements, when present

@akrabat akrabat merged commit 8beb200 into zendframework:master May 15, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment