diff --git a/docs/book/v3/file.md b/docs/book/v3/file.md
new file mode 100644
index 00000000..5df36d49
--- /dev/null
+++ b/docs/book/v3/file.md
@@ -0,0 +1,341 @@
+# File Filters
+
+laminas-filter also comes with a set of classes for filtering file contents, and
+performing file operations such as renaming.
+
+> ## $_FILES
+>
+> All file filter `filter()` implementations support either a file path string
+> *or* a `$_FILES` array as the supplied argument. When a `$_FILES` array is
+> passed in, the `tmp_name` is used for the file path.
+
+## Lowercase
+
+`Laminas\Filter\File\Lowercase` can be used to convert all file contents to
+lowercase.
+
+### Supported Options
+
+The following set of options are supported:
+
+- `encoding`: Set the encoding to use during conversion.
+
+### Basic Usage
+
+```php
+use Laminas\Filter\File\LowerCase;
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$filter = new LowerCase();
+$filter->filter($files['my-upload']);
+```
+
+This example converts the contents of an uploaded file to lowercase. After this
+process, you can use the [Rename](#rename) or [RenameUpload](#renameupload)
+filter to replace this file with your original file, or read directly from file.
+But, don't forget, if you upload a file and send your `$_FILES` array to a
+filter method, the `LowerCase` filter will only change the temporary file
+(`tmp_name` index of array), not the original file. Let's check following
+example:
+
+```php
+use Laminas\Filter\File\LowerCase;
+use Laminas\Filter\File\Rename;
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$lowercaseFilter = new LowerCase();
+$file = $lowercaseFilter->filter($files['userfile']);
+$renameFilter = new Rename([
+ 'target' => '/tmp/newfile.txt',
+ 'randomize' => true,
+]);
+$filename = $renameFilter->filter($file['tmp_name']);
+```
+
+With this example, the final, stored file on the server will have the lowercased
+content.
+
+If you want to use a specific encoding when converting file content, you should
+specify the encoding when instantiating the `LowerCase` filter, or use the
+`setEncoding` method to change it.
+
+```php
+use Laminas\Filter\File\LowerCase;
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$filter = new LowerCase();
+$filter->setEncoding('ISO-8859-1');
+$filter->filter($files['my-upload']);
+```
+
+The `LowerCase` filter extends from the `StringToLower` filter; read the
+[`StringToLower` documentation](/laminas-filter/standard-filters/#stringtolower)
+for more information about encoding and its exceptions.
+
+## Rename
+
+`Laminas\Filter\File\Rename` can be used to rename a file and/or move a file to a new path.
+
+### Supported Options
+
+The following set of options are supported:
+
+- `target` (string; default: `*`): Target filename or directory; the new name
+ of the source file.
+- `source` (string; default: `*`): Source filename or directory which will be
+ renamed. Used to match the filtered file with an options set.
+- `overwrite` (boolean; default: `false`): Shall existing files be overwritten?
+ If the file is unable to be moved into the target path, a
+ `Laminas\Filter\Exception\RuntimeException` will be thrown.
+- `randomize` (boolean; default: `false`): Shall target files have a random
+ postfix attached? The random postfix will generated with `uniqid('_')` after
+ the file name and before the extension. For example, `file.txt` might be
+ randomized to `file_4b3403665fea6.txt`.
+
+An array of option sets is also supported, where a single `Rename` filter
+instance can filter several files using different options. The options used for
+the filtered file will be matched from the `source` option in the options set.
+
+### Usage Examples
+
+Move all filtered files to a different directory:
+
+```php
+// 'target' option is assumed if param is a string
+$filter = new \Laminas\Filter\File\Rename('/tmp/');
+echo $filter->filter('./myfile.txt');
+// File has been moved to '/tmp/myfile.txt'
+```
+
+Rename all filtered files to a new name:
+
+```php
+$filter = new \Laminas\Filter\File\Rename('/tmp/newfile.txt');
+echo $filter->filter('./myfile.txt');
+// File has been renamed to '/tmp/newfile.txt'
+```
+
+Move to a new path, and randomize file names:
+
+```php
+$filter = new \Laminas\Filter\File\Rename([
+ 'target' => '/tmp/newfile.txt',
+ 'randomize' => true,
+]);
+echo $filter->filter('./myfile.txt');
+// File has been renamed to '/tmp/newfile_4b3403665fea6.txt'
+```
+
+Configure different options for several possible source files:
+
+```php
+$filter = new \Laminas\Filter\File\Rename([
+ [
+ 'source' => 'fileA.txt'
+ 'target' => '/dest1/newfileA.txt',
+ 'overwrite' => true,
+ ],
+ [
+ 'source' => 'fileB.txt'
+ 'target' => '/dest2/newfileB.txt',
+ 'randomize' => true,
+ ],
+]);
+echo $filter->filter('fileA.txt');
+// File has been renamed to '/dest1/newfileA.txt'
+echo $filter->filter('fileB.txt');
+// File has been renamed to '/dest2/newfileB_4b3403665fea6.txt'
+```
+
+### Public Methods
+
+The `Rename` filter defines the following public methods in addition to `filter()`:
+follows:
+
+- `getFile() : array`: Returns the files to rename along with their new name and location.
+- `setFile(string|array $options) : void`: Sets the file options for renaming.
+ Removes any previously set file options.
+- `addFile(string|array $options) : void`: Adds file options for renaming to
+ the current list of file options.
+
+## RenameUpload
+
+`Laminas\Filter\File\RenameUpload` can be used to rename or move an uploaded file to a new path.
+
+### Supported Options
+
+The following set of options are supported:
+
+- `target` (string; default: `*`): Target directory or full filename path.
+- `overwrite` (boolean; default: `false`): Shall existing files be overwritten?
+ If the file is unable to be moved into the target path, a
+ `Laminas\Filter\Exception\RuntimeException` will be thrown.
+- `randomize` (boolean; default: `false`): Shall target files have a random
+ postfix attached? The random postfix will generated with `uniqid('_')` after
+ the file name and before the extension. For example, `file.txt` might be
+ randomized to `file_4b3403665fea6.txt`.
+- `use_upload_name` (boolean; default: `false`): When true, this filter will
+ use `$_FILES['name']` as the target filename. Otherwise, the default `target`
+ rules and the `$_FILES['tmp_name']` will be used.
+- `use_upload_extension` (boolean; default: `false`): When true, the uploaded
+ file will maintains its original extension if not specified. For example, if
+ the uploaded file is `file.txt` and the target is `mynewfile`, the upload
+ will be renamed to `mynewfile.txt`.
+- `stream_factory` (`Psr\Http\Message\StreamFactoryInterface`; default: `null`):
+ Required when passing a [PSR-7 UploadedFileInterface](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface)
+ to the filter; used to create a new stream representing the renamed file.
+ (Since 2.9.0)
+- `upload_file_factory` (`Psr\Http\Message\UploadedFileFactoryInterface`; default:
+ `null`): Required when passing a [PSR-7 UploadedFileInterface](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface)
+ to the filter; used to create a new uploaded file representation of the
+ renamed file. (Since 2.9.0)
+
+> ### Using the upload Name is unsafe
+>
+> Be **very** careful when using the `use_upload_name` option. For instance,
+> extremely bad things could happen if you were to allow uploaded `.php` files
+> (or other CGI files) to be moved into the `DocumentRoot`.
+>
+> It is generally a better idea to supply an internal filename to avoid
+> security risks.
+
+`RenameUpload` does not support an array of options like the`Rename` filter.
+When filtering HTML5 file uploads with the `multiple` attribute set, all files
+will be filtered with the same option settings.
+
+### Usage Examples
+
+Move all filtered files to a different directory:
+
+```php
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+// i.e. $files['my-upload']['name'] === 'myfile.txt'
+
+// 'target' option is assumed if param is a string
+$filter = new \Laminas\Filter\File\RenameUpload('./data/uploads/');
+echo $filter->filter($files['my-upload']);
+// File has been moved to './data/uploads/php5Wx0aJ'
+
+// ... or retain the uploaded file name
+$filter->setUseUploadName(true);
+echo $filter->filter($files['my-upload']);
+// File has been moved to './data/uploads/myfile.txt'
+```
+
+Rename all filtered files to a new name:
+
+```php
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$filter = new \Laminas\Filter\File\RenameUpload('./data/uploads/newfile.txt');
+echo $filter->filter($files['my-upload']);
+// File has been renamed to './data/uploads/newfile.txt'
+```
+
+Move to a new path and randomize file names:
+
+```php
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$filter = new \Laminas\Filter\File\RenameUpload([
+ 'target' => './data/uploads/newfile.txt',
+ 'randomize' => true,
+]);
+echo $filter->filter($files['my-upload']);
+// File has been renamed to './data/uploads/newfile_4b3403665fea6.txt'
+```
+
+Handle a PSR-7 uploaded file:
+
+```php
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Message\UploadedFileFactoryInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use Laminas\Filter\File\RenameUpload;
+
+$filter = new \Laminas\Filter\File\RenameUpload([
+ 'target' => './data/uploads/',
+ 'randomize' => true,
+ // @var StreamFactoryInterface $streamFactory
+ 'stream_factory' => $streamFactory,
+ // @var UploadedFileFactoryInterface $uploadedFileFactory
+ 'upload_file_factory' => $uploadedFileFactory,
+]);
+
+// @var ServerRequestInterface $request
+foreach ($request->getUploadedFiles() as $uploadedFile) {
+ // @var UploadedFileInterface $uploadedFile
+ // @var UploadedFileInterface $movedFile
+ $movedFile = $filter->filter($uploadedFile);
+ echo $movedFile->getClientFilename();
+ // File has been renamed to './data/uploads/newfile_4b3403665fea6.txt'
+}
+```
+
+> ### PSR-7 Support
+>
+> PSR-7/PSR-17 support has only been available since 2.9.0, and requires a valid
+> [psr/http-factory-implementation](https://packagist.org/providers/psr/http-factory-implementation)
+> in your application, as it relies on the stream and uploaded file factories in
+> order to produce the final `UploadedFileInterface` artifact representing the
+> filtered file.
+>
+> PSR-17 itself requires PHP 7, so your application will need to be running on
+> PHP 7 in order to use this feature.
+>
+> [laminas/laminas-diactoros 2.0](https://docs.laminas.dev/laminas-diactoros/)
+> provides a PSR-17 implementation, but requires PHP 7.1. If you are still on
+> PHP 7.0, either upgrade, or find a compatible psr/http-factory-implementation.
+
+## Uppercase
+
+`Laminas\Filter\File\Uppercase` can be used to convert all file contents to
+uppercase.
+
+### Supported Options
+
+The following set of options are supported:
+
+- `encoding`: Set the encoding to use during conversion.
+
+### Basic Usage
+
+```php
+use Laminas\Filter\File\UpperCase;
+use Laminas\Http\PhpEnvironment\Request;
+
+$request = new Request();
+$files = $request->getFiles();
+// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ'
+
+$filter = new UpperCase();
+$filter->filter($files['my-upload']);
+```
+
+See the documentation on the [`LowerCase`](#lowercase) filter, above, for more
+information.
diff --git a/docs/book/v3/filter-chains.md b/docs/book/v3/filter-chains.md
new file mode 100644
index 00000000..7d9cef8e
--- /dev/null
+++ b/docs/book/v3/filter-chains.md
@@ -0,0 +1,85 @@
+# Filter Chains
+
+Often, multiple filters should be applied to some value in a particular order.
+For example, a login form accepts a username that should be lowercase and
+contain only alphabetic characters.
+
+`Laminas\Filter\FilterChain` provides a simple method by which filters may be
+chained together. The following code illustrates how to chain together two
+filters for the submitted username and fulfill the above requirements:
+
+```php
+// Create a filter chain and add filters to the chain
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain
+ ->attach(new Laminas\I18n\Filter\Alpha())
+ ->attach(new Laminas\Filter\StringToLower());
+
+// Filter the username
+$username = $filterChain->filter($_POST['username']);
+```
+
+Filters are run in the order they are added to the filter chain. In the above
+example, the username is first removed of any non-alphabetic characters, and
+then any uppercase characters are converted to lowercase.
+
+Any object that implements `Laminas\Filter\FilterInterface` may be used in a
+filter chain.
+
+## Setting Filter Chain Order
+
+For each filter added to the `FilterChain`, you can set a priority to define
+the chain order. Higher values indicate higher priority (execute first), while
+lower and/or negative values indicate lower priority (execute last). The default value is `1000`.
+
+In the following example, any uppercase characters are converted to lowercase
+before any non-alphabetic characters are removed.
+
+```php
+// Create a filter chain and add filters to the chain
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain
+ ->attach(new Laminas\I18n\Filter\Alpha())
+ ->attach(new Laminas\Filter\StringToLower(), 500);
+```
+
+## Using the Plugin Manager
+
+A `FilterPluginManager` is attached to every `FilterChain` instance. Every filter
+that is used in a `FilterChain` must be known to the `FilterPluginManager`.
+
+To add a filter to the `FilterChain`, use the `attachByName()` method. The
+first parameter is the name of the filter within the `FilterPluginManager`. The
+second parameter takes any options for creating the filter instance. The third
+parameter is the priority.
+
+```php
+// Create a filter chain and add filters to the chain
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain
+ ->attachByName('alpha')
+ ->attachByName('stringtolower', ['encoding' => 'utf-8'], 500);
+```
+
+The following example shows how to add a custom filter to the `FilterPluginManager` and the
+`FilterChain`:
+
+```php
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain
+ ->getPluginManager()
+ ->setInvokableClass('myNewFilter', 'MyCustom\Filter\MyNewFilter');
+$filterChain
+ ->attachByName('alpha')
+ ->attachByName('myNewFilter');
+```
+
+You can also add your own `FilterPluginManager` implementation:
+
+```php
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain->setPluginManager(new MyFilterPluginManager());
+$filterChain
+ ->attach(new Laminas\I18n\Filter\Alpha())
+ ->attach(new MyCustom\Filter\MyNewFilter());
+```
diff --git a/docs/book/v3/inflector.md b/docs/book/v3/inflector.md
new file mode 100644
index 00000000..320ca2e5
--- /dev/null
+++ b/docs/book/v3/inflector.md
@@ -0,0 +1,317 @@
+# String Inflection
+
+`Laminas\Filter\Inflector` is a general purpose tool for rules-based inflection of
+strings to a given target.
+
+As an example, you may find you need to transform MixedCase or camelCasedWords
+into a path; for readability, OS policies, or other reasons, you also need to
+lower case this; and finally, you want to separate the words using a dash
+(`-`). An inflector can do this for you.
+
+`Laminas\Filter\Inflector` implements `Laminas\Filter\FilterInterface`; you perform
+inflection by calling `filter()` on the object instance.
+
+## Transforming MixedCase and CamelCaseText to another Format
+
+```php
+$inflector = new Laminas\Filter\Inflector('pages/:page.:suffix');
+$inflector->setRules([
+ ':page' => ['Word\CamelCaseToDash', 'StringToLower'],
+ 'suffix' => 'html',
+]);
+
+$string = 'camelCasedWords';
+$filtered = $inflector->filter(['page' => $string]);
+// pages/camel-cased-words.html
+
+$string = 'this_is_not_camel_cased';
+$filtered = $inflector->filter(['page' => $string]);
+// pages/this_is_not_camel_cased.html
+```
+
+## Operation
+
+An inflector requires a **target** and one or more **rules**. A target is
+basically a string that defines placeholders for variables you wish to
+substitute. These are specified by prefixing with a `:`: `:script`.
+
+When calling `filter()`, you then pass in an array of key and value pairs
+corresponding to the variables in the target.
+
+Each variable in the target can have zero or more rules associated with them.
+Rules may be either **static** or refer to a laminas-filter class. Static rules
+will replace with the text provided. Otherwise, a class matching the rule
+provided will be used to inflect the text. Classes are typically specified
+using a short name indicating the filter name stripped of any common prefix.
+
+As an example, you can use any laminas-filter concrete implementations; however,
+instead of referring to them as `Laminas\I18n\Filter\Alpha` or
+`Laminas\Filter\StringToLower`, you'd specify only `Alpha` or `StringToLower`.
+
+### Using Custom Filters
+
+`Laminas\Filter\Inflector` uses `Laminas\Filter\FilterPluginManager` to manage
+loading filters to use with inflection. By default, filters registered with
+`Laminas\Filter\FilterPluginManager` are available. To access filters with that
+prefix but which occur deeper in the hierarchy, such as the various `Word`
+filters, simply strip off the `Laminas\Filter` prefix:
+
+```php
+// use Laminas\Filter\Word\CamelCaseToDash as a rule
+$inflector->addRules(['script' => 'Word\CamelCaseToDash']);
+```
+
+To use custom filters, you have two choices: reference them by fully qualified
+class name (e.g., `My\Custom\Filter\Mungify`), or manipulate the composed
+`FilterPluginManager` instance.
+
+```php
+$filters = $inflector->getPluginManager();
+$filters->addInvokableClass('mungify', 'My\Custom\Filter\Mungify');
+```
+
+### Setting the Inflector Target
+
+The inflector target is a string with some placeholders for variables.
+Placeholders take the form of an identifier, a colon (`:`) by default, followed
+by a variable name: `:script`, `:path`, etc. The `filter()` method looks for
+the identifier followed by the variable name being replaced.
+
+You can change the identifier using the `setTargetReplacementIdentifier()`
+method, or passing it as the fourth argument to the constructor:
+
+```php
+// Via constructor:
+$inflector = new Laminas\Filter\Inflector('#foo/#bar.#sfx', array(), null, '#');
+
+// Via accessor:
+$inflector->setTargetReplacementIdentifier('#');
+```
+
+Typically, you will set the target via the constructor. However, you may want
+to re-set the target later. `setTarget()` can be used for this purpose:
+
+```php
+$inflector->setTarget('layouts/:script.phtml');
+```
+
+Additionally, you may wish to have a class member for your class that you can
+use to keep the inflector target updated — without needing to directly update
+the target each time (thus saving on method calls). `setTargetReference()`
+allows you to do this:
+
+```php
+class Foo
+{
+ /**
+ * @var string Inflector target
+ */
+ protected $target = 'foo/:bar/:baz.:suffix';
+
+ /**
+ * Constructor
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->inflector = new Laminas\Filter\Inflector();
+ $this->inflector->setTargetReference($this->target);
+ }
+
+ /**
+ * Set target; updates target in inflector
+ *
+ * @param string $target
+ * @return Foo
+ */
+ public function setTarget($target)
+ {
+ $this->target = $target;
+ return $this;
+ }
+}
+```
+
+## Inflection Rules
+
+As mentioned in the introduction, there are two types of rules: static and filter-based.
+
+> ### Order is important
+>
+> It is important to note that regardless of the method in which you add rules
+> to the inflector, either one-by-one, or all-at-once; the order is very
+> important. More specific names, or names that might contain other rule names,
+> must be added before least specific names. For example, assuming the two rule
+> names `moduleDir` and `module`, the `moduleDir` rule should appear before
+> module since `module` is contained within `moduleDir`. If `module` were added
+> before `moduleDir`, `module` will match part of `moduleDir` and process it
+> leaving `Dir` inside of the target uninflected.
+
+### Static Rules
+
+Static rules do simple string substitution; use them when you have a segment in
+the target that will typically be static, but which you want to allow the
+developer to modify. Use the `setStaticRule()` method to set or modify the
+rule:
+
+```php
+$inflector = new Laminas\Filter\Inflector(':script.:suffix');
+$inflector->setStaticRule('suffix', 'phtml');
+
+// change it later:
+$inflector->setStaticRule('suffix', 'php');
+```
+
+Much like the target itself, you can also bind a static rule to a reference,
+allowing you to update a single variable instead of require a method call; this
+is often useful when your class uses an inflector internally, and you don't
+want your users to need to fetch the inflector in order to update it. The
+`setStaticRuleReference()` method is used to accomplish this:
+
+```php
+class Foo
+{
+ /**
+ * @var string Suffix
+ */
+ private $suffix = 'phtml';
+
+ /**
+ * Constructor
+ * @return void
+ */
+ public function construct()
+ {
+ $this->inflector = new Laminas\Filter\Inflector(':script.:suffix');
+ $this->inflector->setStaticRuleReference('suffix', $this->suffix);
+ }
+
+ /**
+ * Set suffix; updates suffix static rule in inflector
+ *
+ * @param string $suffix
+ * @return Foo
+ */
+ public function setSuffix($suffix)
+ {
+ $this->suffix = $suffix;
+ return $this;
+ }
+}
+```
+
+### Filter-Based Inflector Rules
+
+`Laminas\Filter` filters may be used as inflector rules as well. Just like static
+rules, these are bound to a target variable; unlike static rules, you may
+define multiple filters to use when inflecting. These filters are processed in
+order, so be careful to register them in an order that makes sense for the data
+you receive.
+
+Rules may be added using `setFilterRule()` (which overwrites any previous rules
+for that variable) or `addFilterRule()` (which appends the new rule to any
+existing rule for that variable). Filters are specified in one of the following
+ways:
+
+- **String**. The string may be a filter class name, or a class name segment
+ minus any prefix set in the inflector's plugin loader (by default, minus the
+ '`Laminas\Filter`' prefix).
+- **Filter object**. Any object instance implementing
+ `Laminas\Filter\FilterInterface` may be passed as a filter.
+- **Array**. An array of one or more strings or filter objects as defined above.
+
+```php
+$inflector = new Laminas\Filter\Inflector(':script.:suffix');
+
+// Set rule to use Laminas\Filter\Word\CamelCaseToDash filter
+$inflector->setFilterRule('script', 'Word\CamelCaseToDash');
+
+// Add rule to lowercase string
+$inflector->addFilterRule('script', new Laminas\Filter\StringToLower());
+
+// Set rules en-masse
+$inflector->setFilterRule('script', [
+ 'Word\CamelCaseToDash',
+ new Laminas\Filter\StringToLower()
+]);
+```
+
+## Setting many Rules at once
+
+Typically, it's easier to set many rules at once than to configure a single
+variable and its inflection rules one at a time. `Laminas\Filter\Inflector`'s
+`addRules()` and `setRules()` methods allow this.
+
+Each method takes an array of variable and rule pairs, where the rule may be
+whatever the type of rule accepts (string, filter object, or array). Variable
+names accept a special notation to allow setting static rules and filter rules,
+according to the following notation:
+
+- **`:` prefix**: filter rules.
+- **No prefix**: static rule.
+
+As an example:
+
+```php
+// Could also use setRules() with this notation:
+$inflector->addRules([
+ // Filter rules:
+ ':controller' => ['Word\CamelCaseToUnderscore','StringToLower'],
+ ':action' => ['Word\CamelCaseToUnderscore','StringToLower'],
+
+ // Static rule:
+ 'suffix' => 'phtml',
+]);
+```
+
+## Utility Methods
+
+`Laminas\Filter\Inflector` has a number of utility methods for retrieving and
+setting the plugin loader, manipulating and retrieving rules, and controlling
+if and when exceptions are thrown.
+
+- `setPluginManager()` can be used when you have configured your own
+ `Laminas\Filter\FilterPluginManager` instance and wish to use it with
+ `Laminas\Filter\Inflector`; `getPluginManager()` retrieves the currently set
+ one.
+- `setThrowTargetExceptionsOn()` can be used to control whether or not
+ `filter()` throws an exception when a given replacement identifier passed to
+ it is not found in the target. By default, no exceptions are thrown.
+ `isThrowTargetExceptionsOn()` will tell you what the current value is.
+- `getRules($spec = null)` can be used to retrieve all registered rules for all
+ variables, or just the rules for a single variable.
+- `getRule($spec, $index)` fetches a single rule for a given variable; this can
+ be useful for fetching a specific filter rule for a variable that has a
+ filter chain. `$index` must be passed.
+- `clearRules()` will clear all currently registered rules.
+
+## Using a Traversable or an Array
+
+You can use a `Traversable` or an array to set rules and other object state in
+your inflectors, by passing either type to either the constructor or the
+`setOptions()` method. The following settings may be specified:
+
+- `target` specifies the inflection target.
+- `pluginManager` specifies the `Laminas\Filter\FilterPluginManager` instance or
+ extension to use for obtaining plugins; alternately, you may specify a class
+ name of a class that extends the `FilterPluginManager`.
+- `throwTargetExceptionsOn` should be a boolean indicating whether or not to
+ throw exceptions when a replacement identifier is still present after
+ inflection.
+- `targetReplacementIdentifier` specifies the character to use when identifying
+ replacement variables in the target string.
+- `rules` specifies an array of inflection rules; it should consist of keys
+ that specify either values or arrays of values, consistent with `addRules()`.
+
+As examples:
+
+```php
+// $options implements Traversable:
+
+// With the constructor:
+$inflector = new Laminas\Filter\Inflector($options);
+
+// Or with setOptions():
+$inflector = new Laminas\Filter\Inflector();
+$inflector->setOptions($options);
+```
diff --git a/docs/book/v3/intro.md b/docs/book/v3/intro.md
new file mode 100644
index 00000000..ef6e4a3f
--- /dev/null
+++ b/docs/book/v3/intro.md
@@ -0,0 +1,106 @@
+# Introduction
+
+laminas-filter provides a set of commonly needed data filters. It also provides a
+simple filter chaining mechanism by which multiple filters may be applied to a
+single datum in a user-defined order.
+
+## What is a filter?
+
+In the physical world, a filter is typically used for removing unwanted portions
+of input, and the desired portion of the input passes through as filter output
+(e.g., coffee). In such scenarios, a filter is an operator that produces a
+subset of the input. This type of filtering is useful for web applications:
+removing illegal input, trimming unnecessary white space, etc.
+
+This basic definition of a filter may be extended to include generalized
+transformations upon input. A common transformation applied in web applications
+is the escaping of HTML entities. For example, if a form field is automatically
+populated with untrusted input (e.g., from a web browser), this value should
+either be free of HTML entities or contain only escaped HTML entities, in order
+to prevent undesired behavior and security vulnerabilities. To meet this
+requirement, HTML entities that appear in the input must either be removed or
+escaped. Of course, which approach is more appropriate depends on the situation.
+A filter that removes the HTML entities operates within the scope of the first
+definition of filter - an operator that produces a subset of the input. A filter
+that escapes the HTML entities, however, transforms the input (e.g., `&` is
+transformed to `&`). Supporting such use cases for web developers is
+important, and “to filter”, in the context of using laminas-filter, means to
+perform some transformations upon input data.
+
+## Basic usage of filters
+
+Having this filter definition established provides the foundation for
+`Laminas\Filter\FilterInterface`, which requires a single method named `filter()`
+to be implemented by a filter class.
+
+Following is a basic example of using a filter upon two input data, the
+ampersand (`&`) and double quote (`"`) characters:
+
+```php
+$htmlEntities = new Laminas\Filter\HtmlEntities();
+
+echo $htmlEntities->filter('&'); // &
+echo $htmlEntities->filter('"'); // "
+```
+
+Also, if a filter inherits from `Laminas\Filter\AbstractFilter` (as do all of the
+out-of-the-box filters), you can also use them as invokables:
+
+```php
+$strtolower = new Laminas\Filter\StringToLower;
+
+echo $strtolower('I LOVE Laminas!'); // i love laminas!
+$laminaslove = $strtolower('I LOVE Laminas!');
+```
+
+## Double filtering
+
+When using two filters in succession, you have to keep in mind that it is
+often not possible to get the original output by using the opposite filter. Take
+the following example:
+
+```php
+$original = 'my_original_content';
+
+// Attach a filter
+$filter = new Laminas\Filter\Word\UnderscoreToCamelCase();
+$filtered = $filter->filter($original);
+
+// Use it's opposite
+$filter2 = new Laminas\Filter\Word\CamelCaseToUnderscore();
+$filtered = $filter2->filter($filtered)
+```
+
+The above code example could lead to the impression that you will get the
+original output after the second filter has been applied. But thinking logically
+this is not the case. After applying the first filter, `my_original_content` will
+be changed to `MyOriginalContent`. But after applying the second filter, the result
+is `My_Original_Content`.
+
+As you can see it is not always possible to get the original output by using a
+filter which seems to be the opposite. It depends on the filter and also on the
+given input.
+
+## Providing filters via modules
+
+If you wish to indicate that your laminas-mvc module provides filters, have your
+`Module` class implement `Laminas\Filter\FilterProviderInterface`, which defines
+the method:
+
+```php
+/**
+ * @return array
+ */
+public function getFilterConfig();
+```
+
+The method should return an array of configuration following the
+[laminas-servicemanager configuration format](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/).
+
+If you are not using laminas-mvc, but are using a dependency injection container
+(e.g., if you are using Mezzio), you can also provide filters using the
+top-level `filters` configuration key; the value of that key should be
+laminas-servicemanager configuration, as linked above.
+
+(laminas-mvc users may also provide configuration in the same way, and omit
+implementation of the `FilterProviderInterface`.)
diff --git a/docs/book/v3/migration/v2-to-v3.md b/docs/book/v3/migration/v2-to-v3.md
new file mode 100644
index 00000000..7f56df11
--- /dev/null
+++ b/docs/book/v3/migration/v2-to-v3.md
@@ -0,0 +1,49 @@
+# Migration from Version 2 to 3
+
+laminas-filter version 3 makes a number of changes that may affect your application.
+This document details those changes, and provides suggestions on how to update your application to work with version 3.
+
+## Removed Filters
+
+The following filters were deprecated in the 2.0.x series of releases and have now been removed:
+
+### Encryption and Decryption related filters
+
+These filters had become outdated. We recommend that you make use of a maintained encryption library and [write your own filters](../writing-filters.md) if you need to encrypt or decrypt content using the `FilterInterface` contract.
+
+- `Laminas\Filter\File\Decrypt`
+- `Laminas\Filter\File\Encrypt`
+- `Laminas\Filter\Decrypt`
+- `Laminas\Filter\Encrypt`
+
+### Static Filter
+
+`Laminas\Filter\StaticFilter` has been removed without replacement. Most filters are "new-able" so similar behaviour can be accomplished with:
+
+```php
+$filtered = (new \Laminas\Filter\HtmlEntities())('Nuts & Bolts');
+```
+
+For filters requiring more complex construction, we encourage you to make use of dependency injection and compose the filter itself, or the `FilterPluginManager`, for example:
+
+```php
+$pluginManager = $container->get(\Laminas\Filter\FilterPluginManager::class);
+$filter = $pluginManager->get(\Laminas\Filter\HtmlEntities::class);
+$filtered = $filter->filter('A String');
+```
+
+### Whitelist & Blacklist Filters
+
+- `Laminas\Filter\Whitelist` has been replaced by [`Laminas\Filter\AllowList`](../standard-filters.md#allowlist)
+- `Laminas\Filter\Blacklist` has been replaced by [`Laminas\Filter\DenyList`](../standard-filters.md#denylist)
+
+## Removed Features
+
+`Laminas\Filter\Compress` no longer supports the compression formats `Lzf`, `Rar` and `Snappy`.
+Support for these formats has been removed so the following classes are no longer available:
+
+- `Laminas\Filter\Compress\Lzf`
+- `Laminas\Filter\Compress\Rar`
+- `Laminas\Filter\Compress\Snappy`
+
+The following compression formats are still available: `Bz2`, `Gz`, `Tar` and `Zip`
diff --git a/docs/book/v3/standard-filters.md b/docs/book/v3/standard-filters.md
new file mode 100644
index 00000000..665bcf2d
--- /dev/null
+++ b/docs/book/v3/standard-filters.md
@@ -0,0 +1,1490 @@
+# Standard Filters
+
+laminas-filter comes with a standard set of filters, available for immediate use.
+
+## AllowList
+
+This filter will return `null` if the value being filtered is not present the
+filter's allowed list of values. If the value is present, it will return that
+value.
+
+For the opposite functionality see the [DenyList](#denylist) filter.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\AllowList`:
+
+- `strict`: Uses strict mode for comparisons; passed to `in_array()`'s third argument.
+- `list`: An array of allowed values.
+
+### Basic Usage
+
+```php
+$allowList = new \Laminas\Filter\AllowList([
+ 'list' => ['allowed-1', 'allowed-2']
+]);
+echo $allowList->filter('allowed-2'); // => 'allowed-2'
+echo $allowList->filter('not-allowed'); // => null
+```
+
+## Alnum
+
+The `Alnum` filter can be used to return only alphabetic characters and digits
+in the unicode "letter" and "number" categories, respectively. All other
+characters are suppressed.
+
+This filter is part of the laminas-i18n package; you will need to include that
+package in your application to use it.
+
+### Supported Options
+
+The following options are supported for `Alnum`:
+
+```php
+Alnum([ boolean $allowWhiteSpace [, string $locale ]])
+```
+
+- `$allowWhiteSpace`: If set to true, then whitespace characters are allowed.
+ Otherwise they are suppressed. Default is `false` (whitespace is not allowed).
+ Methods for getting/setting the `allowWhiteSpace` option are also available:
+ `getAllowWhiteSpace()` and `setAllowWhiteSpace()`.
+
+- `$locale`: The locale string used in identifying the characters to filter
+ (locale name, e.g. `en_US`). If unset, it will use the default locale
+ (`Locale::getDefault()`). Methods for getting/setting the locale are also
+ available: `getLocale()` and `setLocale()`.
+
+### Basic Usage
+
+```php
+// Default settings, deny whitespace
+$filter = new \Laminas\I18n\Filter\Alnum();
+echo $filter->filter('This is (my) content: 123');
+// Returns 'Thisismycontent123'
+
+// First param in constructor is $allowWhiteSpace
+$filter = new \Laminas\I18n\Filter\Alnum(true);
+echo $filter->filter('This is (my) content: 123');
+// Returns 'This is my content 123'
+```
+
+> ### Supported Languages
+>
+> `Alnum` works on almost all languages, except: Chinese, Japanese and Korean.
+> Within these languages, the english alphabet is used instead of the characters
+> from these languages. The language itself is detected using the `Locale`
+> class.
+
+## Alpha
+
+The `Alpha` filter can be used to return only alphabetic characters in the unicode "letter"
+category. All other characters are suppressed.
+
+This filter is part of the laminas-i18n package; you will need to include that
+package in your application to use it.
+
+### Supported Options
+
+The following options are supported for `Alpha`:
+
+```php
+Alpha([ boolean $allowWhiteSpace [, string $locale ]])
+```
+
+- `$allowWhiteSpace`: If set to true then whitespace characters are allowed.
+ Otherwise they are suppressed. Default is `false` (whitespace is not allowed).
+ Methods for getting/setting the allowWhiteSpace option are also available:
+ `getAllowWhiteSpace()` and `setAllowWhiteSpace()`.
+
+- `$locale`: The locale string used in identifying the characters to filter
+ (locale name, e.g. `en_US`). If unset, it will use the default locale
+ (`Locale::getDefault()`). Methods for getting/setting the locale are also
+ available: `getLocale()` and `setLocale()`.
+
+### Basic Usage
+
+```php
+// Default settings, deny whitespace
+$filter = new \Laminas\I18n\Filter\Alpha();
+echo $filter->filter('This is (my) content: 123');
+// Returns 'Thisismycontent'
+
+// Allow whitespace
+$filter = new \Laminas\I18n\Filter\Alpha(true);
+echo $filter->filter('This is (my) content: 123');
+// Returns 'This is my content '
+```
+
+> ### Supported Languages
+>
+> `Alpha` works on almost all languages, except: Chinese, Japanese and Korean.
+> Within these languages, the english alphabet is used instead of the characters
+> from these languages. The language itself is detected using the `Locale`
+> class.
+
+## BaseName
+
+`Laminas\Filter\BaseName` allows you to filter a string which contains the path to
+a file, and it will return the base name of this file.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\BaseName`.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\BaseName();
+
+print $filter->filter('/vol/tmp/filename');
+```
+
+This will return 'filename'.
+
+```php
+$filter = new Laminas\Filter\BaseName();
+
+print $filter->filter('/vol/tmp/filename.txt');
+```
+
+This will return '`filename.txt`'.
+
+## Boolean
+
+This filter changes a given input to be a `BOOLEAN` value. This is often useful when working with
+databases or when processing form values.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Boolean`:
+
+- `casting`: When this option is set to `TRUE`, then any given input will be
+ cast to boolean. This option defaults to `TRUE`.
+- `translations`: This option sets the translations which will be used to detect localized input.
+- `type`: The `type` option sets the boolean type which should be used. Read
+ the following for details.
+
+### Default Behavior
+
+By default, this filter works by casting the input to a `BOOLEAN` value; in other words, it operates
+in a similar fashion to calling `(boolean) $value`.
+
+```php
+$filter = new Laminas\Filter\Boolean();
+$value = '';
+$result = $filter->filter($value);
+// returns false
+```
+
+This means that without providing any configuration, `Laminas\Filter\Boolean` accepts all input types
+and returns a `BOOLEAN` just as you would get by type casting to `BOOLEAN`.
+
+### Changing the Default Behavior
+
+Sometimes, casting with `(boolean)` will not suffice. `Laminas\Filter\Boolean`
+allows you to configure specific types to convert, as well as which to omit.
+
+The following types can be handled (in this precedence order):
+
+- `localized`: Converts any string as mapped (case sensitive) in the `translations` option.
+- `false`: Converts a string equal to the word "false" (case insensitive) to boolean `FALSE`.
+- `null`: Converts a `NULL` value to `FALSE`.
+- `array`: Converts an empty `array` to `FALSE`.
+- `zero`: Converts a string to `FALSE` if it equates to `'0'` after type juggling.
+- `string`: Converts an empty string `''` to `FALSE`.
+- `float`: Converts a float `0.0` value to `FALSE`.
+- `integer`: Converts an integer `0` value to `FALSE`.
+- `boolean`: Returns a boolean value as is.
+
+There are 2 additional special types:
+
+- `all`: Converts all above types to `BOOLEAN`. The same as setting all above types.
+- `php`: Converts all above types to `BOOLEAN` except `localized` or `false`. The same as setting all above types except `localized` or `false`.
+
+All other given values will return `TRUE` by default.
+
+There are several ways to select which of the above types are filtered. You can
+give one or multiple types and add them, you can give an array, you can use
+constants, or you can give a textual string. See the following examples:
+
+```php
+// converts 0 to false
+$filter = new Laminas\Filter\Boolean(Laminas\Filter\Boolean::TYPE_INTEGER);
+
+// converts 0 and '0' to false
+$filter = new Laminas\Filter\Boolean(
+ Laminas\Filter\Boolean::TYPE_INTEGER + Laminas\Filter\Boolean::TYPE_ZERO_STRING
+);
+
+// converts 0 and '0' to false
+$filter = new Laminas\Filter\Boolean([
+ 'type' => [
+ Laminas\Filter\Boolean::TYPE_INTEGER,
+ Laminas\Filter\Boolean::TYPE_ZERO_STRING,
+ ],
+]);
+
+// converts 0 and '0' to false
+$filter = new Laminas\Filter\Boolean([
+ 'type' => [
+ 'integer',
+ 'zero',
+ ],
+]);
+```
+
+You can also give an instance of `Laminas\Config\Config` to set the desired types.
+To set types after instantiation, use the `setType()` method.
+
+### Localized Booleans
+
+As mentioned previously, `Laminas\Filter\Boolean` can also recognise localized "yes" and "no" strings.
+This means that you can ask your customer in a form for "yes" or "no" within his native language and
+`Laminas\Filter\Boolean` will convert the response to the appropriate boolean value.
+
+To set the translation and the corresponding value, you can use the `translations` option or the
+method `setTranslations`. The translations must be set for any values you wish to map to boolean values.
+
+```php
+$filter = new Laminas\Filter\Boolean([
+ 'type' => Laminas\Filter\Boolean::TYPE_LOCALIZED,
+ 'translations' => [
+ 'ja' => true,
+ 'nein' => false,
+ 'yes' => true,
+ 'no' => false,
+ ],
+]);
+
+// returns false
+$result = $filter->filter('nein');
+
+// returns true
+$result = $filter->filter('yes');
+```
+
+### Disable Casting
+
+Sometimes it is necessary to recognise only `TRUE` or `FALSE` and return all
+other values without changes. `Laminas\Filter\Boolean` allows you to do this by
+setting the `casting` option to `FALSE`.
+
+In this case `Laminas\Filter\Boolean` will work as described in the following
+table, which shows which values return `TRUE` or `FALSE`. All other given values
+are returned without change when `casting` is set to `FALSE`
+
+Type Constant | Type String | True | False
+---- | ---- | ---- | -----
+`Laminas\Filter\Boolean::TYPE_BOOLEAN` | `boolean` | `TRUE` | `FALSE`
+`Laminas\Filter\Boolean::TYPE_EMPTY_ARRAY` | `array` | | `[]`
+`Laminas\Filter\Boolean::TYPE_FALSE_STRING` | `false` | `'true'` (case insensitive) | `'false'` (case insensitive)
+`Laminas\Filter\Boolean::TYPE_FLOAT` | `float` | `1.0` | `0.0`
+`Laminas\Filter\Boolean::TYPE_INTEGER` | `integer` | `1` | `0`
+`Laminas\Filter\Boolean::TYPE_NULL` | `null` | | `NULL`
+`Laminas\Filter\Boolean::TYPE_STRING` | `string` | | `''`
+`Laminas\Filter\Boolean::TYPE_ZERO_STRING` | `zero` | `'1'` | `'0'`
+
+The following example shows the behavior when changing the `casting` option:
+
+```php
+$filter = new Laminas\Filter\Boolean([
+ 'type' => Laminas\Filter\Boolean::TYPE_ALL,
+ 'casting' => false,
+]);
+
+// returns false
+$result = $filter->filter(0);
+
+// returns true
+$result = $filter->filter(1);
+
+// returns the value
+$result = $filter->filter(2);
+```
+
+## Callback
+
+This filter allows you to use own methods in conjunction with `Laminas\Filter`. You
+don't have to create a new filter when you already have a method which does the
+job.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Callback`:
+
+- `callback`: This sets the callback which should be used.
+- `callback_params`: This property sets the options which are used when the
+ callback is processed.
+
+### Basic Usage
+
+The usage of this filter is quite simple. In this example, we want to create a
+filter which reverses a string:
+
+```php
+$filter = new Laminas\Filter\Callback('strrev');
+
+print $filter->filter('Hello!');
+// returns "!olleH"
+```
+
+As you can see it's really simple to use a callback to define custom filters. It
+is also possible to use a method, which is defined within a class, by giving an
+array as the callback:
+
+```php
+class MyClass
+{
+ public static function reverse($param);
+}
+
+// The filter definition
+$filter = new Laminas\Filter\Callback(array('MyClass', 'reverse'));
+print $filter->filter('Hello!');
+```
+
+As of PHP 5.5 you can use ::class resolution for given callback class:
+
+```php
+class MyClass
+{
+ public function __invoke($param);
+}
+
+// The filter definition
+$filter = new Laminas\Filter\Callback(MyClass::class);
+print $filter->filter('Hello!');
+```
+
+To get the actual set callback use `getCallback()` and to set another callback
+use `setCallback()`.
+
+> ### Possible Exceptions
+>
+> You should note that defining a callback method which can not be called will
+> raise an exception.
+
+### Default Parameters within a Callback
+
+It is also possible to define default parameters, which are given to the called
+method as an array when the filter is executed. This array will be concatenated
+with the value which will be filtered.
+
+```php
+$filter = new Laminas\Filter\Callback([
+ 'callback' => 'MyMethod',
+ 'options' => ['key' => 'param1', 'key2' => 'param2']
+]);
+$filter->filter(['value' => 'Hello']);
+```
+
+Calling the above method definition manually would look like this:
+
+```php
+$value = MyMethod('Hello', 'param1', 'param2');
+```
+
+## Compress and Decompress
+
+These two filters are capable of compressing and decompressing strings, files, and directories.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Compress` and `Laminas\Filter\Decompress`:
+
+- `adapter`: The compression adapter which should be used. It defaults to `Gz`.
+- `options`: Additional options which are given to the adapter at initiation.
+ Each adapter supports its own options.
+
+### Supported Compression Adapters
+
+The following compression formats are supported by their own adapter:
+
+- **Bz2**
+- **Gz**
+- **Tar**
+- **Zip**
+
+Each compression format has different capabilities as described below. All
+compression filters may be used in approximately the same ways, and differ
+primarily in the options available and the type of compression they offer (both
+algorithmically as well as string vs. file vs. directory)
+
+### Generic Handling
+
+To create a compression filter, you need to select the compression format you want to use. The
+following example takes the **Bz2** adapter. Details for all other adapters are described after
+this section.
+
+The two filters are basically identical, in that they utilize the same backends.
+`Laminas\Filter\Compress` should be used when you wish to compress items, and `Laminas\Filter\Decompress`
+should be used when you wish to decompress items.
+
+For instance, if we want to compress a string, we have to initialize `Laminas\Filter\Compress` and
+indicate the desired adapter:
+
+```php
+$filter = new Laminas\Filter\Compress('Bz2');
+```
+
+To use a different adapter, you simply specify it to the constructor.
+
+You may also provide an array of options or a `Traversable` object. If you do,
+provide minimally the key "adapter", and then either the key "options" or
+"adapterOptions", both of which should be an array of options to provide to the
+adapter on instantiation.
+
+```php
+$filter = new Laminas\Filter\Compress([
+ 'adapter' => 'Bz2',
+ 'options' => [
+ 'blocksize' => 8,
+ ],
+]);
+```
+
+> ### Default compression Adapter
+>
+> When no compression adapter is given, then the **Gz** adapter will be used.
+
+Decompression is essentially the same usage; we simply use the `Decompress`
+filter instead:
+
+```php
+$filter = new Laminas\Filter\Decompress('Bz2');
+```
+
+To get the compressed string, we have to give the original string. The filtered value is the
+compressed version of the original string.
+
+```php
+$filter = new Laminas\Filter\Compress('Bz2');
+$compressed = $filter->filter('Uncompressed string');
+// Returns the compressed string
+```
+
+Decompression works in reverse, accepting the compressed string, and returning
+the original:
+
+```php
+$filter = new Laminas\Filter\Decompress('Bz2');
+$compressed = $filter->filter('Compressed string');
+// Returns the original, uncompressed string
+```
+
+### Creating an Archive
+
+Creating an archive file works almost the same as compressing a string. However, in this case we
+need an additional parameter which holds the name of the archive we want to create.
+
+```php
+$filter = new Laminas\Filter\Compress([
+ 'adapter' => 'Bz2',
+ 'options' => [
+ 'archive' => 'filename.bz2',
+ ],
+]);
+$compressed = $filter->filter('Uncompressed string');
+// Returns true on success, and creates the archive file
+```
+
+In the above example, the uncompressed string is compressed, and is then written
+into the given archive file.
+
+> ### Existing Archives will be overwritten
+>
+> The content of any existing file will be overwritten when the given filename
+> of the archive already exists.
+
+When you want to compress a file, then you must give the name of the file with its path:
+
+```php
+$filter = new Laminas\Filter\Compress([
+ 'adapter' => 'Bz2',
+ 'options' => [
+ 'archive' => 'filename.bz2'
+ ],
+]);
+$compressed = $filter->filter('C:\temp\compressme.txt');
+// Returns true on success and creates the archive file
+```
+
+You may also specify a directory instead of a filename. In this case the whole
+directory with all its files and subdirectories will be compressed into the
+archive:
+
+```php
+$filter = new Laminas\Filter\Compress([
+ 'adapter' => 'Bz2',
+ 'options' => [
+ 'archive' => 'filename.bz2'
+ ],
+]);
+$compressed = $filter->filter('C:\temp\somedir');
+// Returns true on success and creates the archive file
+```
+
+> ### Do not compress large or base Directories
+>
+> You should never compress large or base directories like a complete partition.
+> Compressing a complete partition is a very time consuming task which can lead
+> to massive problems on your server when there is not enough space or your
+> script takes too much time.
+
+### Decompressing an Archive
+
+Decompressing an archive file works almost like compressing it. You must specify either the
+`archive` parameter, or give the filename of the archive when you decompress the file.
+
+```php
+$filter = new Laminas\Filter\Decompress('Bz2');
+$decompressed = $filter->filter('filename.bz2');
+// Returns true on success and decompresses the archive file
+```
+
+Some adapters support decompressing the archive into another subdirectory. In
+this case you can set the `target` parameter:
+
+```php
+$filter = new Laminas\Filter\Decompress([
+ 'adapter' => 'Zip',
+ 'options' => [
+ 'target' => 'C:\temp',
+ ]
+]);
+$decompressed = $filter->filter('filename.zip');
+// Returns true on success, and decompresses the archive file
+// into the given target directory
+```
+
+> ### Directories to extract to must exist
+>
+> When you want to decompress an archive into a directory, then the target
+> directory must exist.
+
+### Bz2 Adapter
+
+The Bz2 Adapter can compress and decompress:
+
+- Strings
+- Files
+- Directories
+
+This adapter makes use of PHP's Bz2 extension.
+
+To customize compression, this adapter supports the following options:
+
+- `archive`: This parameter sets the archive file which should be used or created.
+- `blocksize`: This parameter sets the blocksize to use. It can be from '0' to
+ '9'. The default value is '4'.
+
+All options can be set at instantiation or by using a related method; for example, the related
+methods for 'blocksize' are `getBlocksize()` and `setBlocksize()`. You can also use the
+`setOptions()` method, which accepts an array of all options.
+
+### Gz Adapter
+
+The Gz Adapter can compress and decompress:
+
+- Strings
+- Files
+- Directories
+
+This adapter makes use of PHP's Zlib extension.
+
+To customize the compression this adapter supports the following options:
+
+- `archive`: This parameter sets the archive file which should be used or created.
+- `level`: This compression level to use. It can be from '0' to '9'. The default
+ value is '9'.
+- `mode`: There are two supported modes. `compress` and `deflate`. The default
+ value is `compress`.
+
+All options can be set at initiation or by using a related method. For example, the related methods
+for `level` are `getLevel()` and `setLevel()`. You can also use the `setOptions()` method which
+accepts an array of all options.
+
+### Tar Adapter
+
+The Tar Adapter can compress and decompress:
+
+- Files
+- Directories
+
+> ### Tar does not support Strings
+>
+> The Tar Adapter can not handle strings.
+
+This adapter makes use of PEAR's `Archive_Tar` component.
+
+To customize compression, this adapter supports the following options:
+
+- `archive`: This parameter sets the archive file which should be used or created.
+- `mode`: A mode to use for compression. Supported are either `NULL`, which
+ means no compression at all; `Gz`, which makes use of PHP's Zlib extension;
+ and `Bz2`, which makes use of PHP's Bz2 extension. The default value is `NULL`.
+- `target`: The target where the decompressed files will be written to.
+
+All options can be set at instantiation or by using a related method. For
+example, the related methods for `target` are `getTarget()` and `setTarget()`.
+You can also use the `setOptions()` method which accepts an array of all
+options.
+
+> ### Directory Usage
+>
+> When compressing directories with Tar, the complete file path is used. This
+> means that created Tar files will not only have the subdirectory, but the
+> complete path for the compressed file.
+
+### Zip Adapter
+
+The Zip Adapter can compress and decompress:
+
+- Strings
+- Files
+- Directories
+
+> ### Zip does not support String Decompression
+>
+> The Zip Adapter can not handle decompression to a string; decompression will
+> always be written to a file.
+
+This adapter makes use of PHP's `Zip` extension.
+
+To customize compression, this adapter supports the following options:
+
+- `archive`: This parameter sets the archive file which should be used or created.
+- `target`: The target where the decompressed files will be written to.
+
+All options can be set at instantiation or by using a related method. For example, the related
+methods for `target` are `getTarget()` and `setTarget()`. You can also use the `setOptions()` method
+which accepts an array of all options.
+
+## DenyList
+
+This filter will return `null` if the value being filtered is present in the filter's list of
+values. If the value is not present, it will return that value.
+
+For the opposite functionality, see the [`AllowList` filter](#allowlist).
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\DenyList`:
+
+- `strict`: Uses strict mode when comparing; passed to `in_array()`'s third argument.
+- `list`: An array of forbidden values.
+
+### Basic Usage
+
+```php
+$denyList = new \Laminas\Filter\DenyList([
+ 'list' => ['forbidden-1', 'forbidden-2']
+]);
+echo $denyList->filter('forbidden-1'); // => null
+echo $denyList->filter('allowed'); // => 'allowed'
+```
+
+## Digits
+
+Returns the string `$value`, removing all but digits.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Digits`.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Digits();
+
+print $filter->filter('October 2012');
+```
+
+This returns "2012".
+
+```php
+$filter = new Laminas\Filter\Digits();
+
+print $filter->filter('HTML 5 for Dummies');
+```
+
+This returns "5".
+
+## Dir
+
+Given a string containing a path to a file, this function will return the name of the directory.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Dir`.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Dir();
+
+print $filter->filter('/etc/passwd');
+```
+
+This returns `/etc`.
+
+```php
+$filter = new Laminas\Filter\Dir();
+
+print $filter->filter('C:/Temp/x');
+```
+
+This returns `C:/Temp`.
+
+## HtmlEntities
+
+Returns the string `$value`, converting characters to their corresponding HTML
+entity equivalents when possible.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\HtmlEntities`:
+
+- `quotestyle`: Equivalent to the PHP `htmlentities()` native function parameter
+ `quote_style`. This allows you to define what will be done with 'single' and
+ "double" quotes. The following constants are accepted: `ENT_COMPAT`,
+ `ENT_QUOTES`, and `ENT_NOQUOTES`, with the default being `ENT_COMPAT`.
+- `charset`: Equivalent to the PHP `htmlentities()` native function parameter
+ `charset`. This defines the character set to be used in filtering. Unlike the
+ PHP native function, the default is 'UTF-8'. See the [PHP htmlentities
+ manual](http://php.net/htmlentities) for a list of supported character sets.
+
+ This option can also be set via the `$options` parameter as a Traversable
+ object or array. The option key will be accepted as either `charset` or
+ `encoding`.
+- `doublequote`: Equivalent to the PHP `htmlentities()` native function
+ parameter `double_encode`. If set to `false`, existing HTML entities will not
+ be encoded. The default is to convert everything (`true`).
+
+ This option must be set via the `$options` parameter or the
+ `setDoubleEncode()` method.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\HtmlEntities();
+
+print $filter->filter('<');
+```
+
+### Quote Style
+
+`Laminas\Filter\HtmlEntities` allows changing the quote style used. This can be useful when you want to
+leave double, single, or both types of quotes un-filtered.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_QUOTES]);
+
+$input = "A 'single' and " . '"double"';
+print $filter->filter($input);
+```
+
+The above example returns `A 'single' and "double"`. Notice
+that 'single' as well as "double" quotes are filtered.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_COMPAT]);
+
+$input = "A 'single' and " . '"double"';
+print $filter->filter($input);
+```
+
+The above example returns `A 'single' and "double"`. Notice that
+"double" quotes are filtered while 'single' quotes are not altered.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_NOQUOTES]);
+
+$input = "A 'single' and " . '"double"';
+print $filter->filter($input);
+```
+
+The above example returns `A 'single' and "double"`. Notice that neither
+"double" or 'single' quotes are altered.
+
+### Helper Methods
+
+To change or retrieve the `quotestyle` after instantiation, the two methods
+`setQuoteStyle()` and `getQuoteStyle()` may be used respectively.
+`setQuoteStyle()` accepts one parameter, `$quoteStyle`, which accepts one of the
+constants `ENT_COMPAT`, `ENT_QUOTES`, or `ENT_NOQUOTES`.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities();
+
+$filter->setQuoteStyle(ENT_QUOTES);
+print $filter->getQuoteStyle(ENT_QUOTES);
+```
+
+To change or retrieve the `charset` after instantiation, the two methods
+`setCharSet()` and `getCharSet()` may be used respectively. `setCharSet()`
+accepts one parameter, `$charSet`. See the [PHP htmlentities manual
+page](http://php.net/htmlentities) for a list of supported character sets.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities();
+
+$filter->setQuoteStyle(ENT_QUOTES);
+print $filter->getQuoteStyle(ENT_QUOTES);
+```
+
+To change or retrieve the `doublequote` option after instantiation, the two methods
+`setDoubleQuote()` and `getDoubleQuote()` may be used respectively. `setDoubleQuote()` accepts one
+boolean parameter, `$doubleQuote`.
+
+```php
+$filter = new Laminas\Filter\HtmlEntities();
+
+$filter->setQuoteStyle(ENT_QUOTES);
+print $filter->getQuoteStyle(ENT_QUOTES);
+```
+
+## ToFloat
+
+- Since 2.9.0
+
+`Laminas\Filter\ToFloat` allows you to transform a scalar value into a float.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\ToFloat`.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\ToFloat();
+
+print $filter->filter('-4.4');
+```
+
+This will return `-4.4` (as a float).
+
+## ToInt
+
+`Laminas\Filter\ToInt` allows you to transform a scalar value into an integer.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\ToInt`.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\ToInt();
+
+print $filter->filter('-4 is less than 0');
+```
+
+This will return '-4'.
+
+### Migration from 2.0-2.3 to 2.4+
+
+Version 2.4 adds support for PHP 7. In PHP 7, `int` is a reserved keyword, which required renaming
+the `Int` filter. If you were using the `Int` filter directly previously, you will now receive an
+`E_USER_DEPRECATED` notice on instantiation. Please update your code to refer to the `ToInt` class
+instead.
+
+Users pulling their `Int` filter instance from the filter plugin manager receive a `ToInt` instance
+instead starting in 2.4.0.
+
+## ToNull
+
+This filter will change the given input to be `NULL` if it meets specific
+criteria. This is often necessary when you work with databases and want to have
+a `NULL` value instead of a boolean or any other type.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\ToNull`:
+
+- `type`: The variable type which should be supported.
+
+### Default Behavior
+
+Per default this filter works like PHP's `empty()` method; in other words, if
+`empty()` returns a boolean `TRUE`, then a `NULL` value will be returned.
+
+```php
+$filter = new Laminas\Filter\ToNull();
+$value = '';
+$result = $filter->filter($value);
+// returns null instead of the empty string
+```
+
+This means that without providing any configuration, `Laminas\Filter\ToNull` will
+accept all input types and return `NULL` in the same cases as `empty()`.
+
+Any other value will be returned as is, without any changes.
+
+### Changing the Default Behavior
+
+Sometimes it's not enough to filter based on `empty()`. Therefore
+`Laminas\Filter\ToNull` allows you to configure which types will be converted, and
+which not.
+
+The following types can be handled:
+
+- `boolean`: Converts a boolean `FALSE` value to `NULL`.
+- `integer`: Converts an integer `0` value to `NULL`.
+- `empty_array`: Converts an empty `array` to `NULL`.
+- `float`: Converts an float `0.0` value to `NULL`.
+- `string`: Converts an empty string `''` to `NULL`.
+- `zero`: Converts a string containing the single character zero (`'0'`) to `NULL`.
+- `all`: Converts all above types to `NULL`. (This is the default behavior.)
+
+There are several ways to select which of the above types are filtered. You can
+give one or multiple types and add them, you can give an array, you can use
+constants, or you can give a textual string. See the following examples:
+
+```php
+// converts false to null
+$filter = new Laminas\Filter\ToNull(Laminas\Filter\ToNull::BOOLEAN);
+
+// converts false and 0 to null
+$filter = new Laminas\Filter\ToNull(
+ Laminas\Filter\ToNull::BOOLEAN + Laminas\Filter\ToNull::INTEGER
+);
+
+// converts false and 0 to null
+$filter = new Laminas\Filter\ToNull([
+ Laminas\Filter\ToNull::BOOLEAN,
+ Laminas\Filter\ToNull::INTEGER
+]);
+
+// converts false and 0 to null
+$filter = new Laminas\Filter\ToNull([
+ 'boolean',
+ 'integer',
+]);
+```
+
+You can also give a `Traversable` or an array to set the wished types. To set
+types afterwards use `setType()`.
+
+### Migration from 2.0-2.3 to 2.4+
+
+Version 2.4 adds support for PHP 7. In PHP 7, `null` is a reserved keyword, which required renaming
+the `Null` filter. If you were using the `Null` filter directly previously, you will now receive an
+`E_USER_DEPRECATED` notice on instantiation. Please update your code to refer to the `ToNull` class
+instead.
+
+Users pulling their `Null` filter instance from the filter plugin manager receive a `ToNull`
+instance instead starting in 2.4.0.
+
+## NumberFormat
+
+The `NumberFormat` filter can be used to return locale-specific number and percentage strings. It
+extends the `NumberParse` filter, which acts as wrapper for the `NumberFormatter` class within the
+Internationalization extension (Intl).
+
+This filter is part of the laminas-i18n package; you will need to include that
+package in your application to use it.
+
+### Supported Options
+
+The following options are supported for `NumberFormat`:
+
+```php
+NumberFormat([ string $locale [, int $style [, int $type ]]])
+```
+
+- `$locale`: (Optional) Locale in which the number would be formatted (locale
+ name, e.g. `en_US`). If unset, it will use the default locale
+ (`Locale::getDefault()`). Methods for getting/setting the locale are also
+ available: `getLocale()` and `setLocale()`.
+
+- `$style`: (Optional) Style of the formatting, one of the
+ [format style constants](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.unumberformatstyle).
+ If unset, it will use `NumberFormatter::DEFAULT_STYLE` as the default style.
+ Methods for getting/setting the format style are also available: `getStyle()`
+ and `setStyle()`.
+
+- `$type`: (Optional) The [formatting type](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.types)
+ to use. If unset, it will use `NumberFormatter::TYPE_DOUBLE` as the default
+ type. Methods for getting/setting the format type are also available:
+ `getType()` and `setType()`.
+
+### Basic Usage
+
+```php
+$filter = new \Laminas\I18n\Filter\NumberFormat('de_DE');
+echo $filter->filter(1234567.8912346);
+// Returns '1.234.567,891'
+
+$filter = new \Laminas\I18n\Filter\NumberFormat('en_US', NumberFormatter::PERCENT);
+echo $filter->filter(0.80);
+// Returns '80%'
+
+$filter = new \Laminas\I18n\Filter\NumberFormat('fr_FR', NumberFormatter::SCIENTIFIC);
+echo $filter->filter(0.00123456789);
+// Returns '1,23456789E-3'
+```
+
+## NumberParse
+
+The `NumberParse` filter can be used to parse a number from a string. It acts as
+a wrapper for the `NumberFormatter` class within the Internationalization
+extension (Intl).
+
+This filter is part of the laminas-i18n package; you will need to include that
+package in your application to use it.
+
+### Supported Options
+
+The following options are supported for `NumberParse`:
+
+```php
+NumberParse([ string $locale [, int $style [, int $type ]]])
+```
+
+- `$locale`: (Optional) Locale in which the number would be parsed (locale name,
+ e.g. `en_US`). If unset, it will use the default locale
+ (`Locale::getDefault()`). Methods for getting/setting the locale are also
+ available: `getLocale()` and `setLocale()`.
+
+- `$style`: (Optional) Style of the parsing, one of the
+ [format style constants](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.unumberformatstyle).
+ If unset, it will use `NumberFormatter::DEFAULT_STYLE` as the default style.
+ Methods for getting/setting the parse style are also available: `getStyle()`
+ and `setStyle()`.
+
+- `$type`: (Optional) The [parsing type](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.types)
+ to use. If unset, it will use `NumberFormatter::TYPE_DOUBLE` as the default
+ type. Methods for getting/setting the parse type are also available:
+ `getType()` and `setType()`.
+
+### Basic Usage
+
+```php
+$filter = new \Laminas\I18n\Filter\NumberParse('de_DE');
+echo $filter->filter('1.234.567,891');
+// Returns 1234567.8912346
+
+$filter = new \Laminas\I18n\Filter\NumberParse('en_US', NumberFormatter::PERCENT);
+echo $filter->filter('80%');
+// Returns 0.80
+
+$filter = new \Laminas\I18n\Filter\NumberParse('fr_FR', NumberFormatter::SCIENTIFIC);
+echo $filter->filter('1,23456789E-3');
+// Returns 0.00123456789
+```
+
+## PregReplace
+
+`Laminas\Filter\PregReplace` performs a search using regular expressions and replaces all found
+elements.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\PregReplace`:
+
+- `pattern`: The pattern to search for.
+- `replacement`: The string which to use as a replacement for the matches; this
+ can optionally contain placeholders for matched groups in the search pattern.
+
+### Basic Usage
+
+To use this filter properly, you must give both options listed above.
+
+The `pattern` option has to be given to set the pattern to search for. It can be
+a string for a single pattern, or an array of strings for multiple patterns.
+
+The `replacement` option indicates the string to replace matches with, and can
+contain placeholders for matched groups from the search `pattern`. The value may
+be a string replacement, or an array of string replacements.
+
+```php
+$filter = new Laminas\Filter\PregReplace([
+ 'pattern' => '/bob/',
+ 'replacement' => 'john',
+]);
+$input = 'Hi bob!';
+
+$filter->filter($input);
+// returns 'Hi john!'
+```
+
+You can also use `setPattern()` to set the pattern(s), and `setReplacement()` set
+the replacement(s).
+
+```php
+$filter = new Laminas\Filter\PregReplace();
+$filter
+ ->setPattern(array('bob', 'Hi'))
+ ->setReplacement(array('john', 'Bye'));
+$input = 'Hi bob!';
+
+$filter->filter($input);
+// returns 'Bye john!'
+```
+
+For more complex usage, read the
+[PCRE Pattern chapter of the PHP manual](http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php).
+
+## RealPath
+
+This filter will resolve given links and pathnames, and returns the canonicalized
+absolute pathnames.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\RealPath`:
+
+- `exists`: This option defaults to `TRUE`, which validates that the given path
+ really exists.
+
+### Basic Usage
+
+For any given link or pathname, its absolute path will be returned. References
+to `/./`, `/../` and extra `/` sequences in the input path will be stripped. The
+resulting path will not have any symbolic links, `/./`, or `/../` sequences.
+
+`Laminas\Filter\RealPath` will return `FALSE` on failure, e.g. if the file does not exist. On BSD
+systems `Laminas\Filter\RealPath` doesn't fail if only the last path component doesn't exist, while
+other systems will return `FALSE`.
+
+```php
+$filter = new Laminas\Filter\RealPath();
+$path = '/www/var/path/../../mypath';
+$filtered = $filter->filter($path);
+
+// returns '/www/mypath'
+```
+
+### Non-Existing Paths
+
+Sometimes it is useful to get paths to files that do n0t exist; e.g., when you
+want to get the real path for a path you want to create. You can then either
+provide a `FALSE` `exists` value at initiation, or use `setExists()` to set it.
+
+```php
+$filter = new Laminas\Filter\RealPath(false);
+$path = '/www/var/path/../../non/existing/path';
+$filtered = $filter->filter($path);
+
+// returns '/www/non/existing/path'
+// even when file_exists or realpath would return false
+```
+
+## StringPrefix
+
+- Since 2.9.0
+
+This filter will add the provided prefix to scalar values.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StringPrefix`:
+
+- `prefix`: The string prefix to add to values.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StringPrefix([
+ 'prefix' => 'PHP-',
+]);
+
+echo $filter->filter('MidCentral');
+```
+
+The above results in the string `PHP-MidCentral`.
+
+## StringSuffix
+
+- Since 2.9.0
+
+This filter will add the provided suffix to scalar values.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StringSuffix`:
+
+- `suffix`: The string suffix to append to values.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StringSuffix([
+ 'suffix' => '-PHP',
+]);
+
+echo $filter->filter('MidCentral');
+```
+
+The above results in the string `MidCentral-PHP`.
+
+## StringToLower
+
+This filter converts any input to lowercase.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StringToLower`:
+
+- `encoding`: This option can be used to set an encoding to use.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StringToLower();
+
+print $filter->filter('SAMPLE');
+// returns "sample"
+```
+
+### Handling alternate Encoding
+
+By default, `StringToLower` will only handle characters from the locale of your
+server; characters from other charsets will be ignored. If you have the mbstring
+extension, however, you can use the filter with other encodings. Pass the
+desired encoding when initiating the `StringToLower` filter, or use the
+`setEncoding()` method to change it.
+
+```php
+// using UTF-8
+$filter = new Laminas\Filter\StringToLower('UTF-8');
+
+// or give an array which can be useful when using a configuration
+$filter = new Laminas\Filter\StringToLower(['encoding' => 'UTF-8']);
+
+// or do this afterwards
+$filter->setEncoding('ISO-8859-1');
+```
+
+> ### Setting invalid Encodings
+>
+> Be aware that you will get an exception when:
+>
+> - you attempt to set an encoding and the mbstring extension is unavailable; or
+> - you attempt to set an encoding unsupported by the mbstring extension.
+
+## StringToUpper
+
+This filter converts any input to UPPERCASE.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StringToUpper`:
+
+- `encoding`: This option can be used to set the encoding to use.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StringToUpper();
+
+print $filter->filter('Sample');
+// returns "SAMPLE"
+```
+
+### Different encoded Strings
+
+Like the `StringToLower` filter, this filter will only handle characters
+supported by your server locale, unless you have the mbstring extension enabled.
+Using different character sets works the same as with `StringToLower`.
+
+```php
+$filter = new Laminas\Filter\StringToUpper(['encoding' => 'UTF-8']);
+
+// or do this afterwards
+$filter->setEncoding('ISO-8859-1');
+```
+
+## StringTrim
+
+This filter modifies a given string such that certain characters are removed
+from the beginning and end.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StringTrim`:
+
+- `charlist`: List of characters to remove from the beginning and end of the
+ string. If this is not set or is null, the default behavior will be invoked,
+ which is to remove only whitespace from the beginning and end of the string.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StringTrim();
+
+print $filter->filter(' This is (my) content: ');
+```
+
+The above example returns `This is (my) content:`. Notice that the whitespace
+characters have been removed.
+
+### Specifying alternate Characters
+
+```php
+$filter = new Laminas\Filter\StringTrim(':');
+// or new Laminas\Filter\StringTrim(array('charlist' => ':'));
+
+print $filter->filter(' This is (my) content:');
+```
+
+The above example returns `This is (my) content`. Notice that the whitespace
+characters and colon are removed. You can also provide a `Traversable` or an
+array with a `charlist` key. To set the desired character list after
+instantiation, use the `setCharList()` method. `getCharList()` returns the
+current character list.
+
+## StripNewlines
+
+This filter modifies a given string and removes all new line characters within
+that string.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\StripNewlines`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StripNewlines();
+
+print $filter->filter(' This is (my)``\n\r``content: ');
+```
+
+The above example returns `This is (my) content:`. Notice that all newline
+characters have been removed.
+
+## StripTags
+
+This filter can strip XML and HTML tags from given content.
+
+> ### Laminas\\Filter\\StripTags is potentially insecure
+>
+> Be warned that `Laminas\\Filter\\StripTags` should only be used to strip *all*
+> available tags. Using `Laminas\\Filter\\StripTags` to make your site secure by
+> stripping *some* unwanted tags will lead to unsecure and dangerous code,
+> including potential XSS vectors.
+>
+> For a fully secure solution that allows selected filtering of HTML tags, use
+> either Tidy or HtmlPurifier.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\StripTags`:
+
+- `allowAttribs`: This option sets the attributes which are accepted. All other
+ attributes are stripped from the given content.
+- `allowTags`: This option sets the tags which are accepted. All other tags will
+ be stripped from; the given content.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\StripTags();
+
+print $filter->filter('My content');
+```
+
+The result will be the stripped content `My content`.
+
+When the content contains broken or partial tags, any content following the
+opening tag will be completely removed:
+
+```php
+$filter = new Laminas\Filter\StripTags();
+
+print $filter->filter('This contains no ending tag');
+```
+
+The above will return `This contains`, with the rest being stripped.
+
+### Allowing defined Tags
+
+`Laminas\Filter\StripTags` allows stripping all but an allowed set of tags. As an
+example, this can be used to strip all markup except for links:
+
+```php
+$filter = new Laminas\Filter\StripTags(['allowTags' => 'a']);
+
+$input = "A text with
a link";
+print $filter->filter($input);
+```
+
+The above will return `A text with a link`;
+it strips all tags but the link. By providing an array, you can specify multiple
+tags at once.
+
+> ### Warning
+>
+> Do not use this feature to secure content. This component does not replace the
+> use of a properly configured html filter.
+
+### Allowing defined Attributes
+
+You can also strip all but an allowed set of attributes from a tag:
+
+```php
+$filter = new Laminas\Filter\StripTags([
+ 'allowTags' => 'img',
+ 'allowAttribs' => 'src',
+]);
+
+$input = "A text with
a picture";
+print $filter->filter($input);
+```
+
+The above will return `A text with a picture`; it
+strips all tags but ``, and all attributes but `src` from those tags.By
+providing an array you can set multiple attributes at once.
+
+### Allow specific Tags with specific Attributes
+
+You can also pass the tag allow list as a set of tag/attribute values. Each key
+will be an allowed tag, pointing to a list of allowed attributes for that
+tag.
+
+```php
+$allowedElements = [
+ 'img' => [
+ 'src',
+ 'width'
+ ],
+ 'a' => [
+ 'href'
+ ]
+];
+$filter = new Laminas\Filter\StripTags($allowedElements);
+
+$input = "A text with
a picture click "
+ . "here!";
+print $filter->filter($input);
+```
+
+The above will return
+`A text with a picture click here!`
+as the result.
+
+## UriNormalize
+
+This filter sets the scheme on a URI if the scheme is missing.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\UriNormalize`:
+
+- `defaultScheme`: This option can be used to set the default scheme to use when
+ parsing scheme-less URIs.
+- `enforcedScheme`: Set a URI scheme to enforce on schemeless URIs.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\UriNormalize(array(
+ 'enforcedScheme' => 'https'
+));
+
+echo $filter->filter('www.example.com');
+```
+
+The above results in the string `https://www.example.com`.
diff --git a/docs/book/v3/word.md b/docs/book/v3/word.md
new file mode 100644
index 00000000..7e1f6540
--- /dev/null
+++ b/docs/book/v3/word.md
@@ -0,0 +1,315 @@
+# Word Filters
+
+In addition to the standard set of filters, there are several classes specific
+to filtering word strings.
+
+## CamelCaseToDash
+
+This filter modifies a given string such that `CamelCaseWords` are converted to `Camel-Case-Words`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\CamelCaseToDash`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\CamelCaseToDash();
+
+print $filter->filter('ThisIsMyContent');
+```
+
+The above example returns `This-Is-My-Content`.
+
+## CamelCaseToSeparator
+
+This filter modifies a given string such that `CamelCaseWords` are converted to `Camel Case Words`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\CamelCaseToSeparator`:
+
+- `separator`: A separator character. If this is not set, the default separator
+ is a space.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\CamelCaseToSeparator(':');
+// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => ':'));
+
+print $filter->filter('ThisIsMyContent');
+```
+
+The above example returns `This:Is:My:Content`.
+
+### Default Behavior
+
+```php
+$filter = new Laminas\Filter\Word\CamelCaseToSeparator();
+
+print $filter->filter('ThisIsMyContent');
+```
+
+The above example returns `This Is My Content`.
+
+## CamelCaseToUnderscore
+
+This filter modifies a given string such that `CamelCaseWords` are converted to
+`Camel_Case_Words`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\CamelCaseToUnderscore`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\CamelCaseToUnderscore();
+
+print $filter->filter('ThisIsMyContent');
+```
+
+The above example returns `This_Is_My_Content`.
+
+## DashToCamelCase
+
+This filter modifies a given string such that `words-with-dashes` are converted
+to `WordsWithDashes`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\DashToCamelCase`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\DashToCamelCase();
+
+print $filter->filter('this-is-my-content');
+```
+
+The above example returns `ThisIsMyContent`.
+
+## DashToSeparator
+
+This filter modifies a given string such that `words-with-dashes` are converted
+to `words with dashes`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\DashToSeparator`:
+
+- `separator`: A separator character. If this is not set, the default separator
+ is a space.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\DashToSeparator('+');
+// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => '+'));
+
+print $filter->filter('this-is-my-content');
+```
+
+The above example returns `this+is+my+content`.
+
+### Default Behavior
+
+```php
+$filter = new Laminas\Filter\Word\DashToSeparator();
+
+print $filter->filter('this-is-my-content');
+```
+
+The above example returns `this is my content`.
+
+## DashToUnderscore
+
+This filter modifies a given string such that `words-with-dashes` are converted
+to `words_with_dashes`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\DashToUnderscore`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\DashToUnderscore();
+
+print $filter->filter('this-is-my-content');
+```
+
+The above example returns `this_is_my_content`.
+
+## SeparatorToCamelCase
+
+This filter modifies a given string such that `words with separators` are
+converted to `WordsWithSeparators`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\SeparatorToCamelCase`:
+
+- `separator`: A separator character. If this is not set, the default separator
+ is a space.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToCamelCase(':');
+// or new Laminas\Filter\Word\SeparatorToCamelCase(array('separator' => ':'));
+
+print $filter->filter('this:is:my:content');
+```
+
+The above example returns `ThisIsMyContent`.
+
+### Default Behavior
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToCamelCase();
+
+print $filter->filter('this is my content');
+```
+
+The above example returns `ThisIsMyContent`.
+
+## SeparatorToDash
+
+This filter modifies a given string such that `words with separators` are
+converted to `words-with-separators`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\SeparatorToDash`:
+
+- `separator`: A separator character. If this is not set, the default separator
+ is a space.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToDash(':');
+// or new Laminas\Filter\Word\SeparatorToDash(array('separator' => ':'));
+
+print $filter->filter('this:is:my:content');
+```
+
+The above example returns `this-is-my-content`.
+
+### Default Behavior
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToDash();
+
+print $filter->filter('this is my content');
+```
+
+The above example returns `this-is-my-content`.
+
+## SeparatorToSeparator
+
+This filter modifies a given string such that `words with separators` are
+converted to `words-with-separators`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\SeparatorToSeparator`:
+
+- `searchSeparator`: The search separator character. If this is not set, the
+ default separator is a space.
+- `replaceSeparator`: The replacement separator character. If this is not set, the
+ default separator is a dash (`-`).
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToSeparator(':', '+');
+
+print $filter->filter('this:is:my:content');
+```
+
+The above example returns `this+is+my+content`.
+
+### Default Behaviour
+
+```php
+$filter = new Laminas\Filter\Word\SeparatorToSeparator();
+
+print $filter->filter('this is my content');
+```
+
+The above example returns `this-is-my-content`.
+
+## UnderscoreToCamelCase
+
+This filter modifies a given string such that `words_with_underscores` are
+converted to `WordsWithUnderscores`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\UnderscoreToCamelCase`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\UnderscoreToCamelCase();
+
+print $filter->filter('this_is_my_content');
+```
+
+The above example returns `ThisIsMyContent`.
+
+## UnderscoreToSeparator
+
+This filter modifies a given string such that `words_with_underscores` are
+converted to `words with underscores`.
+
+### Supported Options
+
+The following options are supported for `Laminas\Filter\Word\UnderscoreToSeparator`:
+
+- `separator`: A separator character. If this is not set, the default separator
+ is a space.
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\UnderscoreToSeparator('+');
+// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => '+'));
+
+print $filter->filter('this_is_my_content');
+```
+
+The above example returns `this+is+my+content`.
+
+### Default Behavior
+
+```php
+$filter = new Laminas\Filter\Word\UnderscoreToSeparator();
+
+print $filter->filter('this_is_my_content');
+```
+
+The above example returns `this is my content`.
+
+## UnderscoreToDash
+
+This filter modifies a given string such that `words_with_underscores` are
+converted to `words-with-underscores`.
+
+### Supported Options
+
+There are no additional options for `Laminas\Filter\Word\UnderscoreToDash`:
+
+### Basic Usage
+
+```php
+$filter = new Laminas\Filter\Word\UnderscoreToDash();
+
+print $filter->filter('this_is_my_content');
+```
+
+The above example returns `this-is-my-content`.
diff --git a/docs/book/v3/writing-filters.md b/docs/book/v3/writing-filters.md
new file mode 100644
index 00000000..48552743
--- /dev/null
+++ b/docs/book/v3/writing-filters.md
@@ -0,0 +1,41 @@
+# Writing Filters
+
+`Laminas\Filter` supplies a set of commonly needed filters, but developers will
+often need to write custom filters for their particular use cases. You can do
+so by writing classes that implement `Laminas\Filter\FilterInterface`, which
+defines a single method, `filter()`.
+
+## Example
+
+```php
+namespace Application\Filter;
+
+use Laminas\Filter\FilterInterface;
+
+class MyFilter implements FilterInterface
+{
+ public function filter($value)
+ {
+ // perform some transformation upon $value to arrive on $valueFiltered
+
+ return $valueFiltered;
+ }
+}
+```
+
+To attach an instance of the filter defined above to a filter chain:
+
+```php
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain->attach(new Application\Filter\MyFilter());
+```
+
+Alternately, add it to the `FilterPluginManager`:
+
+```php
+$filterChain = new Laminas\Filter\FilterChain();
+$filterChain
+ ->getPluginManager()
+ ->setInvokableClass('myfilter', Application\Filter\MyFilter::class)
+$filterChain->attachByName('myfilter');
+```
diff --git a/mkdocs.yml b/mkdocs.yml
index 9fc753eb..4d138a71 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -12,22 +12,34 @@ nav:
- 'String Inflection': v2/inflector.md
- 'Static Filter': v2/static-filter.md
- 'Writing Filters': v2/writing-filters.md
+ - v3:
+ - Introduction: v3/intro.md
+ - Reference:
+ - 'Standard Filters': v3/standard-filters.md
+ - 'Word Filters': v3/word.md
+ - 'File Filters': v3/file.md
+ - 'Filter Chains': v3/filter-chains.md
+ - 'String Inflection': v3/inflector.md
+ - 'Writing Filters': v3/writing-filters.md
+ - Migration:
+ - "Migration from Version 2 to 3": v3/migration/v2-to-v3.md
site_name: laminas-filter
site_description: "Programmatically filter and normalize data and files."
repo_url: 'https://github.com/laminas/laminas-filter'
extra:
project: Components
- current_version: v2
+ current_version: v3
versions:
- v2
+ - v3
plugins:
- redirects:
redirect_maps:
- intro.md: v2/intro.md
- standard-filters.md: v2/standard-filters.md
- word.md: v2/word.md
- file.md: v2/file.md
- filter-chains.md: v2/filter-chains.md
- inflector.md: v2/inflector.md
+ intro.md: v3/intro.md
+ standard-filters.md: v3/standard-filters.md
+ word.md: v3/word.md
+ file.md: v3/file.md
+ filter-chains.md: v3/filter-chains.md
+ inflector.md: v3/inflector.md
static-filter.md: v2/static-filter.md
- writing-filters.md: v2/writing-filters.md
+ writing-filters.md: v3/writing-filters.md