Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 23dbe80

Browse files
committed
Merge branch 'hotfix/78' into develop
Forward port #78
2 parents c65177a + 911ba5f commit 23dbe80

File tree

4 files changed

+372
-0
lines changed

4 files changed

+372
-0
lines changed
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# File Upload Input
2+
3+
The `Zend\InputFilter\FileInput` class is a special `Input` type for uploaded files found in the
4+
`$_FILES` array.
5+
6+
While `FileInput` uses the same interface as `Input`, it differs in a few ways:
7+
8+
1. It expects the raw value to be in the `$_FILES` array format.
9+
2. The validators are run **before** the filters (which is the opposite behavior of `Input`). This
10+
is so that any `is_uploaded_file()` validation can be run prior to any filters that may
11+
rename/move/modify the file.
12+
3. Instead of adding a `NotEmpty` validator, it will (by default) automatically add a
13+
`Zend\Validator\File\UploadFile` validator.
14+
15+
The biggest thing to be concerned about is that if you are using a `<input type="file">` element in
16+
your form, you will need to use the `FileInput` **instead of** `Input` or else you will encounter
17+
issues.
18+
19+
## Basic Usage
20+
21+
Usage of `FileInput` is essentially the same as `Input`:
22+
23+
```php
24+
use Zend\Http\PhpEnvironment\Request;
25+
use Zend\Filter;
26+
use Zend\InputFilter\InputFilter;
27+
use Zend\InputFilter\Input;
28+
use Zend\InputFilter\FileInput;
29+
use Zend\Validator;
30+
31+
// Description text input
32+
$description = new Input('description'); // Standard Input type
33+
$description->getFilterChain() // Filters are run first w/ Input
34+
->attach(new Filter\StringTrim());
35+
$description->getValidatorChain() // Validators are run second w/ Input
36+
->attach(new Validator\StringLength(array('max' => 140)));
37+
38+
// File upload input
39+
$file = new FileInput('file'); // Special File Input type
40+
$file->getValidatorChain() // Validators are run first w/ FileInput
41+
->attach(new Validator\File\UploadFile());
42+
$file->getFilterChain() // Filters are run second w/ FileInput
43+
->attach(new Filter\File\RenameUpload(array(
44+
'target' => './data/tmpuploads/file',
45+
'randomize' => true,
46+
)));
47+
48+
// Merge $_POST and $_FILES data together
49+
$request = new Request();
50+
$postData = array_merge_recursive($request->getPost()->toArray(), $request->getFiles()->toArray());
51+
52+
$inputFilter = new InputFilter();
53+
$inputFilter->add($description)
54+
->add($file)
55+
->setData($postData);
56+
57+
if ($inputFilter->isValid()) { // FileInput validators are run, but not the filters...
58+
echo "The form is valid\n";
59+
$data = $inputFilter->getValues(); // This is when the FileInput filters are run.
60+
} else {
61+
echo "The form is not valid\n";
62+
foreach ($inputFilter->getInvalidInput() as $error) {
63+
print_r ($error->getMessages());
64+
}
65+
}
66+
```
67+
68+
Also see
69+
70+
- File filter classes&lt;zend.filter.file&gt;
71+
- File validator classes&lt;zend.validator.file&gt;
72+

doc/book/zend.input-filter.intro.md

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Introduction
2+
3+
The `Zend\InputFilter` component can be used to filter and validate generic sets of input data. For
4+
instance, you could use it to filter `$_GET` or `$_POST` values, CLI arguments, etc.
5+
6+
To pass input data to the `InputFilter`, you can use the `setData()` method. The data must be
7+
specified using an associative array. Below is an example on how to validate the data coming from a
8+
form using the *POST* method.
9+
10+
```php
11+
use Zend\InputFilter\InputFilter;
12+
use Zend\InputFilter\Input;
13+
use Zend\Validator;
14+
15+
$email = new Input('email');
16+
$email->getValidatorChain()
17+
->attach(new Validator\EmailAddress());
18+
19+
$password = new Input('password');
20+
$password->getValidatorChain()
21+
->attach(new Validator\StringLength(8));
22+
23+
$inputFilter = new InputFilter();
24+
$inputFilter->add($email)
25+
->add($password)
26+
->setData($_POST);
27+
28+
if ($inputFilter->isValid()) {
29+
echo "The form is valid\n";
30+
} else {
31+
echo "The form is not valid\n";
32+
foreach ($inputFilter->getInvalidInput() as $error) {
33+
print_r($error->getMessages());
34+
}
35+
}
36+
```
37+
38+
In this example we validated the email and password values. The email must be a valid address and
39+
the password must be composed with at least 8 characters. If the input data are not valid, we report
40+
the list of invalid input using the `getInvalidInput()` method.
41+
42+
You can add one or more validators to each input using the `attach()` method for each validator. It
43+
is also possible to specify a "validation group", a subset of the data to be validated; this may be
44+
done using the `setValidationGroup()` method. You can specify the list of the input names as an
45+
array or as individual parameters.
46+
47+
```php
48+
// As individual parameters
49+
$inputFilter->setValidationGroup('email', 'password');
50+
51+
// or as an array of names
52+
$inputFilter->setValidationGroup(array('email', 'password'));
53+
```
54+
55+
You can validate and/or filter the data using the `InputFilter`. To filter data, use the
56+
`getFilterChain()` method of individual `Input` instances, and attach filters to the returned filter
57+
chain. Below is an example that uses filtering without validation.
58+
59+
```php
60+
use Zend\InputFilter\Input;
61+
use Zend\InputFilter\InputFilter;
62+
63+
$input = new Input('foo');
64+
$input->getFilterChain()
65+
->attachByName('stringtrim')
66+
->attachByName('alpha');
67+
68+
$inputFilter = new InputFilter();
69+
$inputFilter->add($input)
70+
->setData(array(
71+
'foo' => ' Bar3 ',
72+
));
73+
74+
echo "Before:\n";
75+
echo $inputFilter->getRawValue('foo') . "\n"; // the output is ' Bar3 '
76+
echo "After:\n";
77+
echo $inputFilter->getValue('foo') . "\n"; // the output is 'Bar'
78+
```
79+
80+
The `getValue()` method returns the filtered value of the 'foo' input, while `getRawValue()` returns
81+
the original value of the input.
82+
83+
We provide also `Zend\InputFilter\Factory`, to allow initialization of the `InputFilter` based on a
84+
configuration array (or `Traversable` object). Below is an example where we create a password input
85+
value with the same constraints proposed before (a string with at least 8 characters):
86+
87+
```php
88+
use Zend\InputFilter\Factory;
89+
90+
$factory = new Factory();
91+
$inputFilter = $factory->createInputFilter(array(
92+
'password' => array(
93+
'name' => 'password',
94+
'required' => true,
95+
'validators' => array(
96+
array(
97+
'name' => 'not_empty',
98+
),
99+
array(
100+
'name' => 'string_length',
101+
'options' => array(
102+
'min' => 8
103+
),
104+
),
105+
),
106+
),
107+
));
108+
109+
$inputFilter->setData($_POST);
110+
echo $inputFilter->isValid() ? "Valid form" : "Invalid form";
111+
```
112+
113+
The factory may be used to create not only `Input` instances, but also nested `InputFilter`s,
114+
allowing you to create validation and filtering rules for hierarchical data sets.
115+
116+
Finally, the default `InputFilter` implementation is backed by a `Factory`. This means that when
117+
calling `add()`, you can provide a specification that the `Factory` would understand, and it will
118+
create the appropriate object. You may create either `Input` or `InputFilter` objects in this
119+
fashion.
120+
121+
```php
122+
use Zend\InputFilter\InputFilter;
123+
124+
$filter = new InputFilter();
125+
126+
// Adding a single input
127+
$filter->add(array(
128+
'name' => 'username',
129+
'required' => true,
130+
'validators' => array(
131+
array(
132+
'name' => 'not_empty',
133+
),
134+
array(
135+
'name' => 'string_length',
136+
'options' => array(
137+
'min' => 5
138+
),
139+
),
140+
),
141+
));
142+
143+
// Adding another input filter what also contains a single input. Merging both.
144+
$filter->add(array(
145+
'type' => 'Zend\InputFilter\InputFilter',
146+
'password' => array(
147+
'name' => 'password',
148+
'required' => true,
149+
'validators' => array(
150+
array(
151+
'name' => 'not_empty',
152+
),
153+
array(
154+
'name' => 'string_length',
155+
'options' => array(
156+
'min' => 8
157+
),
158+
),
159+
),
160+
),
161+
));
162+
```
163+
164+
The `merge()` method may be used on an `InputFilterInterface` in order to add two or more filters to
165+
each other, effectively allowing you to create chains of filters. This is especially useful in
166+
object hierarchies whereby we may define a generic set of validation rules on the base object and
167+
build these up to more specific rules along the way.
168+
169+
In the example below an `InputFilter` is built up for the name property as well as for the email
170+
property allowing them to be re-used elsewhere. When the `isValid()` method is called on the object,
171+
all of the merged filters are run against the calling object in order to validate the internal
172+
properties based on our compound set of filters.
173+
174+
```php
175+
use Zend\InputFilter\InputFilter;
176+
```
177+
178+
> /*\** Filter to ensure a name property is set and &gt; 8 characters
179+
*/ class NameInputFilter extends InputFilter { /*\* Filter body goes here \*\*/ }
180+
/*\** Filter to ensure an email property is set and &gt; 8 characters and is valid
181+
\*/
182+
class EmailInputFilter extends InputFilter { /*\* Filter body goes here*\*/ }
183+
class SimplePerson { /*\* Member variables ommitted for berevity*\*/
184+
/*\* @var InputFilter*/ protected $inputFilter;
185+
/*\** Retrieve input filter
186+
\* \* @return InputFilter \*/
187+
public function getInputFilter() { if (!$this-&gt;inputFilter) { // Create a new input filter
188+
$this-&gt;inputFilter = new InputFilter(); // Merge our inputFilter in for the email property
189+
$this-&gt;inputFilter-&gt;merge(new EmailInputFilter()); // Merge our inputFilter in for the name
190+
property $this-&gt;inputFilter-&gt;merge(new NameInputFilter()); } return $this-&gt;inputFilter; }
191+
/*\** Set input filter
192+
\* \* @param InputFilterInterface $inputFilter \* @return SimplePerson \*/
193+
public function setInputFilter(InputFilterInterface $inputFilter) { $this-&gt;inputFilter =
194+
$inputFilter;
195+
return $this;
196+
}
197+
}
198+
Also see
199+
200+
- Zend\\\\Filter&lt;zend.filter.introduction&gt;
201+
- Zend\\\\Validator&lt;zend.validator.introduction&gt;
202+

doc/book/zend.input-filter.specs.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Input filter specifications
2+
3+
`Zend\InputFilter` allows configuration-driven creation of input filters via
4+
`Zend\InputFilter\InputFilterAbstractServiceFactory`. This abstract factory is responsible for
5+
creating and returning an appropriate input filter given named configuration under the top-level
6+
configuration key `input_filter_specs`.
7+
8+
It is registered with `Zend\InputFilter\InputFilterPluginManager`, allowing you to pull the input
9+
filter via that plugin manager. A side effect is that forms pulled from
10+
`Zend\Form\FormElementManager` can use these named input filters.
11+
12+
## Setup
13+
14+
This functionality is disabled by default.
15+
16+
To enable it, you must add the `Zend\InputFilter\InputFilterAbstractServiceFactory` abstract factory
17+
to the `Zend\InputFilter\InputFilterPluginManager` configuration, which is unser the `input_filters`
18+
configuration key.
19+
20+
```php
21+
return array(
22+
'input_filters' => array(
23+
'abstract_factories' => array(
24+
'Zend\InputFilter\InputFilterAbstractServiceFactory'
25+
),
26+
),
27+
);
28+
```
29+
30+
## Example
31+
32+
In the following code, we define configuration for an input filter named `foobar`:
33+
34+
```php
35+
return array(
36+
'input_filter_specs' => array(
37+
'foobar' => array(
38+
0 => array(
39+
'name' => 'name',
40+
'required' => true,
41+
'filters' => array(
42+
0 => array(
43+
'name' => 'Zend\Filter\StringTrim',
44+
'options' => array(),
45+
),
46+
),
47+
'validators' => array(),
48+
'description' => 'Hello to name',
49+
'allow_empty' => false,
50+
'continue_if_empty' => false,
51+
),
52+
),
53+
);
54+
```
55+
56+
When creating a controller, we might then pull the `InputFilterManager`, and retrieve the `foobar`
57+
input filter we've defined in order to inject it:
58+
59+
```php
60+
use Zend\ServiceManager\FactoryInterface;
61+
use Zend\ServiceManager\ServiceLocatorInterface;
62+
63+
class MyValidatingControllerFactory implements FactoryInterface
64+
{
65+
public function createService(ServiceLocatorInterface $controllers)
66+
{
67+
// Retrieve the application service manager
68+
$services = $controllers->getServiceLocator();
69+
70+
// Retrieve the InputFilterManager
71+
$filters = $services->get('InputFilterManager');
72+
73+
// Instantiate the controller and pass it the foobar input filter
74+
return new MyValidatingController($filters->get('foobar'));
75+
}
76+
}
77+
```
78+
79+
And you can use it, as you already did with other input filters:
80+
81+
```php
82+
$inputFilter->setData(array(
83+
'name' => 'test',
84+
));
85+
86+
if (! $inputFilter->isValid()) {
87+
echo 'Data invalid';
88+
}
89+
```

doc/bookdown.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"title": "Zend\\Input-filter",
3+
"target": "html/",
4+
"content": [
5+
"book/zend.input-filter.intro.md",
6+
"book/zend.input-filter.specs.md",
7+
"book/zend.input-filter.file-input.md"
8+
]
9+
}

0 commit comments

Comments
 (0)