Skip to content

Commit

Permalink
Added the documentation to use GitBook format
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Miu committed Apr 27, 2014
1 parent d83dc43 commit 9fe2a0e
Show file tree
Hide file tree
Showing 22 changed files with 760 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ build/
/vendor
/composer.lock
.idea/
book/_book/
41 changes: 41 additions & 0 deletions book/Building_forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Building forms

A **Sirius\Forms** form has a few dependencies

1. the element factory which will construct `Sirius\Forms\Element` objects based on the specifications you provide
2. the validator object which will be used to validate the values provided to the form
3. the filtrator object which will be used to filtrate the data sent to the form

These dependencies have default values that allow you to start building forms ASAP.

```php
use Sirius\Forms\Form;
use Sirius\Forms\ElementFactory;
use Sirius\Validation\Validator;
use Sirius\Filtration\Filtrator;

$elementFactory = new ElementFactory();
$validator = new Validator();
$filtrator = new Filtrator();

$form = new Form($elementFactory, $validator, $filtrator);
```

All of the form's depedencies above have default values so you may choose not to use them but the downside is that you are bound to the default functionality. For example:

* if you have custom validation rules you won't be able to use it because the validator object dependends on a `RuleFactory` where you must register your custom validation rules.
* if your app's forms have custom element types they must be registered in the `ElementFactory` instance


Some of these problems are not a deal-breaker because you can do stuff like

```php
// add a custom validator at any time
$form->getValidator()->getRuleFactory()->register('my_email_validator', 'MyApp\Validator\Email`);

// add a custom element type
$form->getElementFactory()->registerElementType('custom_element', 'MyApp\Forms\Element\Custom');

```

but that is not good practice because these means you will repeat yourself and you'll define your dependencies inside the application code.
163 changes: 163 additions & 0 deletions book/Building_forms/Adding_elements_to_forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Adding elements to forms

Adding elements to a form is as simple as telling the form the name of the element (so it can later be retrieved) and the element' specifications:

```php
use Sirius\Forms\Element;

// provide specs for the element factory
$specs = array(
Element::TYPE => 'text',
Element::LABEL => 'Your email address'
);
$form->add('email', $specs);
```

The `Element` class has a lot of constats that you can use when definining the element specifications.

When you add an element to the form the `ElementFactory` converts the specifications into an `Element` object that you can manipulate.

```php
$email = $form->get('email');
$email->addClass('full-width');
$email->addLabelClass('required');

```

Usually you don't need to do this but if your app uses events (or other mechanism) to alter the forms between their construction and rendering, this is the way to go.

## The `Element` specs and API

The list below contains the specs that are used by the library during the build process, validation and rendering of the form.

The format of the list contains the key of the specs in the definition array, its associated constant (in order help your IDE help you) and its corresponding getter/setter (in paranthesis).

##### `element_type` | Element::ELEMENT_TYPE

This is required only by the ElementFactory to determine the type of element to be instantiated (defaults to 'text').

**Important!** You can change it at any time but that will not change the already instanciated element.

##### `attributes` | Element::ATTRIBUTES (getAttributes/setAttributes, getAttribute/setAttribute)

The HTML attributes of the input field. Example:

```php
$email = $form->getEmail();
$email->setAttributes(array(
'class' => 'required email'
'type' => 'email'
));
$attrs = $email->getAttributes();

$email->setAttribute('class', 'required email');
$email->getAttribute('class');
```

##### `label` | Element::LABEL (getLabel/setLabel)

The label of the input field. Example:

```php
$email->setLabel('Your email');
$email->getLabel(); // Your email
```

##### `label_attributes` | Element::LABEL_ATTRIBUTES (getLabelAttributes/setLabelAttributes , getLabelAttribute/setLabelAttributes)

The HTML attributes of the label element

##### `hint` | Element::HINT (getHint/setHint)

Information text to help the user fill out the form

##### `hint_attributes` | Element::HINT_ATTRIBUTES (getHintAttributes/setHintAttributes , getHintAttribute/setHintAttribute)

The HTML attributes of the hint element

##### `priority` | Element::PRIORITY (getPriority/setPriority)

The display order of the form element. This allows decouples the element definition order in time from its order in the rendered form

##### `group` | Element::GROUP (getGroup/setGroup)

Sometimes you want to visually group certain elements. The value of this attribute is the name of the element that will group other elements

##### `widge` | Element::WIDGET

This is will instruct the renderer to display the form element in a certain way. You may choose to display a date as a single field or a group of selects, there is no need to tie the form element type to its visual representation

##### `validation_rules` | Element::VALIDATION_RULES (getValidationRules/setValidationRules)

Contains an array of validation rules in a format that is understandable by the Validator object

##### `filters` | Element::FILTERS (getFilters/setFilters)

Contains an array of filters to be applied to incoming data in a format that is undestandable by the filtrator object

##### `upload_container` | Element::UPLOAD_CONATAINER (getUploadContainer/setUploadContainer)

The upload container (something that is an acceptable parameter by the upload handler library)

##### `upload_options` | Element::UPLOAD_OPTIONS (getUploadOptions/setUploadOptions)

Configuration options for the upload handler

##### `upload_rules` | Element::UPLOAD_RULES (getUploadRules/setUploadRules)

Validation rules for the file uploads

##### `options` | Element::OPTIONS (getOptions/setOptions)

A set of options to be used by SELECT elements, checkbox/radio groups

##### `first_option` | Element::FIRST_OPTION (getFirstOption/setFirstOption)

The empty option to be displayed in the list (eg: 'select from list...')

#### `data` | Element::DATA (getData/setData)

Similarly to jQuery you can add random data to your elements.

```php
$email->setData(array(
'multiple items' => true,
'set in one go' => true
));
$email->setData('key', 'value')
$email->getData('key'); //value
$email->getData(); // get everything
```

### Other magic methods

As you can see from the above list there are some properties of an element which get 2 getters and 2 setters. The `attributes` and any property that ends with `_attributes` will get this special behaviour. This allows you to do something like:

```php
// get the class attribute of the input field
$cssClass = $form->get('email')->getAttribute('class');
// set a custom attribute for the label
$form->get('email')->setLabelAttribute('data-custom-attribute', 'value');
```

Besides these nice utilities there are 3 more methods that can be used to alter the element specs

- `addXXXClass()` - example: `addClass()`, `addLabelClass()`, `addHintClass()`
- `removeXXXClass()` - example: `removeClass()`, `removeLabelClass()`, `removeHintClass()`
- `toggleXXXClass()` - example: `toggleClass()`, `toggleLabelClass()`, `toggleHintClass()`

These magic methods are also available to any property that ends with `_attributes`.

### Custom element specs

You can set any other properties to an element and you will get access to a getter and a setter. If your custom render engine can interpret an attribute like `autocomplete_url` the Sirius\Forms library will construct the element which will have the `getAutocompleteUrl()` and `setAutocompleteUrl()` methods.

These custom specification will be added to the `data` container.

```php
$element->setAutoCompleteUrl('controller/action.json');
// is the same as
$element->setData('auto_complete_url', 'controller/action.json');
```

**Note!** Unless you define these methods on your custom elements, you don't get IDE support.
35 changes: 35 additions & 0 deletions book/Building_forms/Creating_forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Creating a form

Once you have your dependencies in place creating forms is as easy as:


```php
$form = new Form($elementFactory, $validator, $filtrator);
```

The `Form` class extends the `Specs` class (which is an augmented `\ArrayObject`) which allows you to alter the form's properties

```php
$form->setAttribute('method', 'post')
->setAttribute('action', '/controller/action')
->addClass('form-inline')
->removeClass('row');

// or using array object notation if you're more comfortable and you know what you're doing :)

$form->attributes['method'] = 'post';
$form->attributes['class'] = 'form-inline';
```

You can extend the **Sirius\Forms** forms for your application

```php
class MyForm extends \Sirius\Forms\Form
{
function init()
{
// here you can do stuff specific to your form like adding elements
// or adding specific attributes to the form (classes, data attributes etc)
}
}
```
19 changes: 19 additions & 0 deletions book/Form_data_processing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Form data processing

Use the `populate()` method to attach data on the form

```php
$form->populate(array_merge($_POST, $_FILES));
```

When the populate method is executed the following operations are executed

1. **data is filtrated**. The unfiltered data is still accessible.
2. **uploaded files** are processed. Valid uploads are passed on the proper fields (you'll see later what that means)
3. **data is validated**. After the data is validated, the upload errors are added to the form's validation error messages

This means that if the form is populated with invalid data the form will have error messages. Sometimes this is not the behaviour you want (eg: the use gets a form populated with data from the database and you don't want to show the errors immediately). To do that you must clear the validator's messages

```php
$form->getValidator()->clearMessages();
```
27 changes: 27 additions & 0 deletions book/Form_data_processing/Filtration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Filtration

The **Sirius\Forms** library uses the [Sirius\Filtration](http://github.com/siriusphp/filtration) library.

The `filters` property of an element specs is an array of filters. For each filter 2 parameters are needed

- name of the filter
- options for the filter (optional)

These are the parameters required by the `Sirius\Validation\Filtrator::add()` method and they can be provided in a format that is recognizable by the **Sirius\Filtration** library.

```php
$form->add('date', array(
'label' => 'Date'
'filters' => array(
// simple filter that uses the default options
'stringtrim',
// usual definition of filter
array('normalizedate', ['format' => 'd/m/Y'])
// filter that uses all options
array('xss_prevention', [], true /* apply the filter recursively */, 1000 /* the priority*/)
),
));

```

[Learn more about Sirius\Filtration](http://github.com/siriusphp/filtration)
36 changes: 36 additions & 0 deletions book/Form_data_processing/Uploads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Uploads

The **Sirius\Forms** library uses the [Sirius\Upload](http://github.com/siriusphp/upload) library.

For each element that is of type `file` the library will construct an __"upload handler"__. For this reason, the element specs need to contain:

- the container
- upload options
- upload validation rules

```php
$form->add('picture', array(
'label' => 'Picture'
'upload_container' => 'images/products/'
'upload_rules' => array(
['image', ['type' = > ['jpg', 'png'], 'File must be a JPG or PNG']
['width', ['max' => 1000], 'No more than {max} pixels wide please']
),
'upload_options' => [
// prefix for the uploaded file
'prefix' => time(),
// overwrite if a file with the same name is already there
'overwrite' => true,
]
));

```

The container can be a local folder or an instance of `Sirius\Upload\Container\ContainerInterface`.

**Important!** Files are uploaded under a name that is equal to: `__upload_` + the form's element name. So, in the example above the `$_FILES` array should contain a `__upload_picture` entry.

This is done to prevent name collisions in modern apps that use Javascript upload. In such apps an Ajax uploader will populate the field `picture` with the result of the successful upload which is actually the desired end result (to populate the user's `picture` attribute with the uploaded file).


[Learn more about Sirius\Upload](http://github.com/siriusphp/upload)
30 changes: 30 additions & 0 deletions book/Form_data_processing/Validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Validation

The **Sirius\Forms** library uses the [Sirius\Validation](http://github.com/siriusphp/validation) library.

The `validation_rules` property of an input specs is an array of validation rules. For each validation rule 3 parameters are needed

- name of the rule
- options for the rule (optional)
- error message template (optional)

These are the parameters required by the `Sirius\Validation\Validator::add()` method and they can be provided in a format that is recognizable by that library.

```php
$form->add('name', array(
'label' => 'Name'
'validation_rules' => array(
// simple rule that uses the default error message
'required',
// normal definition of validation rule
array('minlength', ['min' => 20], '{label} must have at least {min} characters'),
// validation options as a QUERY string
array('maxlength', 'max=200', 'Field must have less than {max} characters')
),
));

```

Input validation rules are attached to the form's validator object during the preparation of the form. Until then you are free to change the validation rules attached to the input.

[Learn more about Sirius\Validation](http://github.com/siriusphp/validation).
27 changes: 27 additions & 0 deletions book/Form_element_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Form element types

Before looking at the form's element types you must understand that **form elements are not widgets!**

_Ideally_, all the data that a user sends to your app should be in a format that is understandable by the system without any additional preparation. But there are many situations when that is not going to happen

1. You want to allow the user to send localized data (eg: dates, numbers)
2. You want to make it easier to the user to provide data (eg: use day, month and year fields for entering a date or use autocomplete widgets)

**Important!** From **Sirius\Forms**' point of view there is no connection between the type of the element (ie: the value of the `Element::TYPE` attribute) and how that element is rendered to the user (ie: the value of the `Element::WIDGET` attribute).

This means that when you define a form element you must be aware of how it is going to be displayed and add additional properties.

In the case of the date input that is displayed as a 3 selects you must:

1. add a filter to convert that array into a string
2. make sure your renderer will be able to extract construct an array from the string date.

**Sirius\Forms** has only a few basic built-in form elements and you need to create your own fields according to your application's needs. Don't be scared, it's very easy to create custom input fields. Check out the [examples](https://github.com/siriusphp/forms/tree/master/examples) folder to see how to create localized dates, autocomplete elements and much more.

The **Sirius\Forms** library contains a few base elements that can be extended for your particular needs. Some of these base elements are already extended by the library to cover anybody's basic needs out-of-the-box.

* [Input](Form_element_types/Input.md)
* [Button](Form_element_types/Button.md)
* [Group](Form_element_types/Group.md)
* [Fielset](Form_element_types/Fielset.md)
* [Collection](Form_element_types/Collection.md)

0 comments on commit 9fe2a0e

Please sign in to comment.