From cf9cae0e69be553e649ece4f8dc36ac2f73aecb3 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Thu, 2 Sep 2021 23:15:03 +0200
Subject: [PATCH 01/39] feat(fields): #1 add sorting fields by priority field

---
 .gitlab-ci.yml                                |  1 -
 changelog.txt                                 |  4 ++
 composer.json                                 |  2 +-
 phpunit-integration.xml                       |  7 +-
 src/Field.php                                 |  3 +
 src/Field/BasicField.php                      | 11 +++
 src/Form/FormWithFields.php                   | 11 ++-
 tests/integration/Form/FormWithFieldsTest.php | 71 +++++++++++++++++++
 tests/integration/bootstrap.php               | 12 +---
 9 files changed, 102 insertions(+), 20 deletions(-)
 create mode 100644 tests/integration/Form/FormWithFieldsTest.php

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 38447e9..b865367 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,6 @@ variables:
   DISABLE_ACCEPTANCE: 1
   DISABLE_PHP_5_5: 1
   DISABLE_CODECEPTION: 1
-  DISABLE_INTEGRATION_TESTS: 1
   IS_LIBRARY: 1
 
 include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml'
diff --git a/changelog.txt b/changelog.txt
index ee2493b..e6b1ae0 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,9 @@
 # Changelog
 
+## [2.5.0] - 2021-09-03
+### Added
+- Added fields sorting by priority field
+
 ## [2.4.6] - 2021-08-23
 ### Fixed
 - Get attribute now returns attribute instead of bool value
diff --git a/composer.json b/composer.json
index 6a79cb8..afcddb9 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,7 @@
     }
   ],
   "require": {
-    "php": ">=5.6",
+    "php": ">=7.0",
     "ext-curl": "*",
     "ext-json": "*",
     "wpdesk/wp-persistence": "^2.0|^3.0",
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
index 4a342ab..c78958b 100644
--- a/phpunit-integration.xml
+++ b/phpunit-integration.xml
@@ -3,7 +3,7 @@
      >
     <testsuites>
         <testsuite>
-            <directory prefix="Test" suffix=".php">./tests/integration</directory>
+            <directory suffix="Test.php">./tests/integration</directory>
         </testsuite>
     </testsuites>
 
@@ -20,9 +20,4 @@
         <log type="coverage-clover" target="build-coverage/clover.xml"/>
     </logging>
 
-    <php>
-        <env name="WP_DEVELOP_DIR" value="/tmp/wordpress-develop"/>
-        <env name="WC_DEVELOP_DIR" value="/tmp/woocommerce"/>
-    </php>
-
 </phpunit>
\ No newline at end of file
diff --git a/src/Field.php b/src/Field.php
index 458bb38..4205df4 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -163,4 +163,7 @@ interface Field {
 
 	/** @return Serializer */
 	public function get_serializer();
+
+	/** @return int */
+	public function get_priority();
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index da93922..7158b73 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -298,4 +298,15 @@ abstract class BasicField implements Field {
 
 		return $this;
 	}
+
+	/** @return int */
+	public function get_priority() {
+		return $this->meta['priority'] ?? 10;
+	}
+
+	public function set_priority( int $priority ) {
+		$this->meta['priority'] = $priority;
+
+		return $this;
+	}
 }
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index 4b5819c..a5a494c 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -243,7 +243,16 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 * @inheritDoc
 	 */
 	public function get_fields() {
-		return $this->fields;
+		$fields = $this->fields;
+
+		usort(
+			$fields,
+			static function ( Field $a, Field $b ) {
+				return $a->get_priority() <=> $b->get_priority();
+			}
+		);
+
+		return $fields;
 	}
 
 	/**
diff --git a/tests/integration/Form/FormWithFieldsTest.php b/tests/integration/Form/FormWithFieldsTest.php
new file mode 100644
index 0000000..9d8c2b2
--- /dev/null
+++ b/tests/integration/Form/FormWithFieldsTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace integration\Form;
+
+use WPDesk\Forms\Field\InputNumberField;
+use WPDesk\Forms\Field\InputTextField;
+use WPDesk\Forms\Field\SelectField;
+use WPDesk\Forms\Form\FormWithFields;
+use PHPUnit\Framework\TestCase;
+
+class FormWithFieldsTest extends TestCase {
+
+	/** @var FormWithFields */
+	private $form;
+
+	protected function setUp() {
+		$this->form = new FormWithFields([]);
+	}
+
+	public function test_should_return_fields_sorted_by_priority() {
+		$this->form->add_fields(
+			[
+				( new InputTextField() )
+				->set_label('third'),
+				( new SelectField() )
+				->set_label('second')
+				->set_priority(5),
+				( new InputNumberField() )
+				->set_label('first')
+				->set_priority(1)
+			]
+		);
+
+		$expected = [
+			( new InputNumberField() )
+			->set_label('first')
+			->set_priority(1),
+			( new SelectField() )
+			->set_label('second')
+			->set_priority(5),
+			( new InputTextField() )
+			->set_label('third')
+		];
+
+		self::assertEquals($expected, $this->form->get_fields());
+	}
+
+	public function test_should_return_fields_by_adding_order_if_no_priority_set() {
+		$this->form->add_fields(
+			[
+				( new InputTextField() )
+					->set_label('first'),
+				( new SelectField() )
+					->set_label('second'),
+				( new InputNumberField() )
+					->set_label('third'),
+			]
+		);
+
+		$expected = [
+			( new InputTextField() )
+				->set_label('first'),
+			( new SelectField() )
+				->set_label('second'),
+			( new InputNumberField() )
+				->set_label('third'),
+		];
+
+		self::assertEquals($expected, $this->form->get_fields());
+	}
+}
diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php
index a422fd9..bbe2889 100644
--- a/tests/integration/bootstrap.php
+++ b/tests/integration/bootstrap.php
@@ -15,14 +15,4 @@ if ( getenv( 'PLUGIN_PATH' ) !== false ) {
 	define( 'PLUGIN_PATH', getenv( 'PLUGIN_PATH' ) );
 } else {
 	define( 'PLUGIN_PATH', __DIR__ . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR );
-}
-
-require_once( getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit/includes/functions.php' );
-
-tests_add_filter( 'muplugins_loaded', function () {
-}, 100 );
-
-putenv('WP_TESTS_DIR=' . getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit');
-require_once( getenv( 'WC_DEVELOP_DIR' ) . '/tests/bootstrap.php' );
-
-do_action('plugins_loaded');
\ No newline at end of file
+}
\ No newline at end of file
-- 
GitLab


From 398bb2ebd62701748da2383a4ca3477954bbd173 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Fri, 3 Sep 2021 10:41:06 +0200
Subject: [PATCH 02/39] refactor: add consistency in typing and inline docs

---
 src/Field/BasicField.php                      | 14 ++++++++++----
 tests/integration/Form/FormWithFieldsTest.php | 10 ++++++++--
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 7158b73..54ef3cc 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
+use WPDesk\Forms\Form\FormWithFields;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer\NoSerialize;
@@ -25,6 +26,7 @@ abstract class BasicField implements Field {
 
 	public function __construct() {
 		$this->meta['class'] = [];
+		$this->meta['priority'] = 10;
 	}
 
 	public function get_label() {
@@ -299,12 +301,16 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	/** @return int */
-	public function get_priority() {
-		return $this->meta['priority'] ?? 10;
+	public function get_priority(): int {
+		return $this->meta['priority'];
 	}
 
-	public function set_priority( int $priority ) {
+	/**
+	 * Fields are sorted by lowest priority value first, when getting FormWithFields
+	 *
+	 * @see FormWithFields::get_fields()
+	 */
+	public function set_priority( int $priority ): self {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/tests/integration/Form/FormWithFieldsTest.php b/tests/integration/Form/FormWithFieldsTest.php
index 9d8c2b2..165592d 100644
--- a/tests/integration/Form/FormWithFieldsTest.php
+++ b/tests/integration/Form/FormWithFieldsTest.php
@@ -21,10 +21,13 @@ class FormWithFieldsTest extends TestCase {
 		$this->form->add_fields(
 			[
 				( new InputTextField() )
-				->set_label('third'),
+				->set_label('fourth'),
 				( new SelectField() )
 				->set_label('second')
 				->set_priority(5),
+				( new SelectField() )
+				->set_label('third')
+				->set_priority(7),
 				( new InputNumberField() )
 				->set_label('first')
 				->set_priority(1)
@@ -38,8 +41,11 @@ class FormWithFieldsTest extends TestCase {
 			( new SelectField() )
 			->set_label('second')
 			->set_priority(5),
-			( new InputTextField() )
+			( new SelectField() )
 			->set_label('third')
+			->set_priority(7),
+			( new InputTextField() )
+			->set_label('fourth')
 		];
 
 		self::assertEquals($expected, $this->form->get_fields());
-- 
GitLab


From 573bfb703ee914e0fad2178799fcb0f0834392a2 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Mon, 6 Sep 2021 13:58:59 +0200
Subject: [PATCH 03/39] feat: add strong typing to the package

---
 .editorconfig                                |  91 ++++++++++
 .env.testing                                 |  17 ++
 .gitignore                                   |   3 +-
 composer.json                                | 101 +++++------
 phpcs.xml.dist                               |  48 +++++
 phpstan.neon.dist                            |   4 +
 phpunit-integration.xml                      |   6 -
 src/ContainerForm.php                        |  11 +-
 src/Escaper.php                              |   8 +-
 src/Field.php                                | 149 +++++-----------
 src/Field/BasicField.php                     | 173 ++++++-------------
 src/Field/ButtonField.php                    |  18 +-
 src/Field/CheckboxField.php                  |  11 +-
 src/Field/DatePickerField.php                |   9 +-
 src/Field/Header.php                         |   6 +-
 src/Field/HiddenField.php                    |   5 +-
 src/Field/ImageInputField.php                |   5 +-
 src/Field/InputNumberField.php               |   5 +-
 src/Field/InputTextField.php                 |   5 +-
 src/Field/MultipleInputTextField.php         |   5 +-
 src/Field/NoOnceField.php                    |   5 +-
 src/Field/NoValueField.php                   |   2 +-
 src/Field/Paragraph.php                      |   4 +-
 src/Field/ProductSelect.php                  |   2 +-
 src/Field/RadioField.php                     |   2 +-
 src/Field/SelectField.php                    |   7 +-
 src/Field/SubmitField.php                    |   6 +-
 src/Field/TextAreaField.php                  |   2 +-
 src/Field/TimepickerField.php                |   5 +-
 src/Field/Traits/HtmlAttributes.php          |  40 ++---
 src/Field/WooSelect.php                      |   2 +-
 src/Field/WyswigField.php                    |   4 +-
 src/FieldProvider.php                        |   2 +-
 src/FieldRenderer.php                        |  13 +-
 src/FieldsDataReceiver.php                   |   2 -
 src/Form.php                                 |  36 ++--
 src/Form/AbstractForm.php                    |  94 ----------
 src/Form/FormWithFields.php                  | 145 +++++-----------
 src/Form/FormsCollection.php                 | 115 ------------
 src/Persistence/FieldPersistenceStrategy.php |  10 +-
 src/Renderer/JsonNormalizedRenderer.php      |   8 +-
 src/Resolver/DefaultFormFieldResolver.php    |   5 +-
 src/Sanitizer.php                            |   8 +-
 src/Sanitizer/CallableSanitizer.php          |   6 +-
 src/Sanitizer/NoSanitize.php                 |   2 +-
 src/Sanitizer/TextFieldSanitizer.php         |   2 +-
 src/Serializer.php                           |  10 ++
 src/Serializer/JsonSerializer.php            |   4 +-
 src/Serializer/NoSerialize.php               |   2 +-
 src/Serializer/ProductSelectSerializer.php   |   3 -
 src/Validator.php                            |  14 +-
 src/Validator/ChainValidator.php             |   8 +-
 src/Validator/NoValidateValidator.php        |   4 +-
 src/Validator/NonceValidator.php             |   9 +-
 src/Validator/RequiredValidator.php          |   4 +-
 templates/button.php                         |  31 ++--
 templates/form-field.php                     |  22 ++-
 templates/form-label.php                     |   4 +-
 templates/form-start.php                     |   2 +-
 templates/header.php                         |   4 +-
 templates/input-checkbox.php                 |  18 +-
 templates/input-date-picker.php              |  11 +-
 templates/input-hidden.php                   |  17 +-
 templates/input-image.php                    |  36 ++--
 templates/input-number.php                   |  11 +-
 templates/input-radio.php                    |  17 +-
 templates/input-submit.php                   |  25 ++-
 templates/input-text-multiple.php            |  85 +++++----
 templates/input-text.php                     |  17 +-
 templates/input.php                          |  56 +++---
 templates/noonce.php                         |   4 +-
 templates/paragraph.php                      |   8 +-
 templates/product-select.php                 |  17 +-
 templates/select.php                         |  43 +++--
 templates/textarea.php                       |  38 ++--
 templates/wyswig.php                         |   8 +-
 tests/unit/TestForm.php                      |  58 -------
 tests/unit/TestFormCollection.php            | 141 ---------------
 78 files changed, 792 insertions(+), 1148 deletions(-)
 create mode 100644 .editorconfig
 create mode 100644 .env.testing
 create mode 100644 phpcs.xml.dist
 create mode 100644 phpstan.neon.dist
 delete mode 100644 src/Form/AbstractForm.php
 delete mode 100644 src/Form/FormsCollection.php
 delete mode 100644 tests/unit/TestForm.php
 delete mode 100644 tests/unit/TestFormCollection.php

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..3fe55c8
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,91 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# WordPress Coding Standards
+# https://make.wordpress.org/core/handbook/coding-standards/
+
+# Configuration for PhpStorm
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
+tab_width = 4
+ij_continuation_indent_size = 4
+
+[*.scss]
+ij_scss_enforce_quotes_on_format = true
+ij_scss_hex_color_long_format = true
+ij_scss_hex_color_lower_case = true
+
+[{*.cjs,*.js}]
+indent_style = space
+indent_size = 2
+ij_javascript_do_while_brace_force = always
+ij_javascript_if_brace_force = always
+ij_javascript_import_sort_module_name = true
+ij_javascript_reformat_c_style_comments = true
+ij_javascript_space_after_unary_not = true
+ij_javascript_space_before_unary_not = true
+ij_javascript_spaces_within_array_initializer_brackets = true
+ij_javascript_spaces_within_brackets = true
+ij_javascript_spaces_within_catch_parentheses = true
+ij_javascript_spaces_within_for_parentheses = true
+ij_javascript_spaces_within_if_parentheses = true
+ij_javascript_spaces_within_imports = true
+ij_javascript_spaces_within_interpolation_expressions = true
+ij_javascript_spaces_within_method_call_parentheses = true
+ij_javascript_spaces_within_method_parentheses = true
+ij_javascript_spaces_within_object_literal_braces = true
+ij_javascript_spaces_within_parentheses = true
+ij_javascript_spaces_within_switch_parentheses = true
+ij_javascript_spaces_within_while_parentheses = true
+ij_javascript_while_brace_force = always
+
+[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
+ij_php_align_assignments = true
+ij_php_align_class_constants = true
+ij_php_align_key_value_pairs = true
+ij_php_align_phpdoc_comments = true
+ij_php_align_phpdoc_param_names = true
+ij_php_class_brace_style = end_of_line
+ij_php_comma_after_last_array_element = true
+ij_php_else_if_style = combine
+ij_php_force_short_declaration_array_style = true
+ij_php_getters_setters_naming_style = snake_case
+ij_php_if_brace_force = always
+ij_php_lower_case_boolean_const = true
+ij_php_lower_case_null_const = true
+ij_php_method_brace_style = end_of_line
+ij_php_phpdoc_blank_line_before_tags = true
+ij_php_phpdoc_blank_lines_around_parameters = true
+ij_php_phpdoc_keep_blank_lines = false
+ij_php_phpdoc_wrap_long_lines = true
+ij_php_space_after_type_cast = true
+ij_php_space_after_unary_not = true
+ij_php_space_before_unary_not = true
+ij_php_spaces_around_var_within_brackets = true
+ij_php_spaces_within_array_initializer_braces = true
+ij_php_spaces_within_catch_parentheses = true
+ij_php_spaces_within_for_parentheses = true
+ij_php_spaces_within_if_parentheses = true
+ij_php_spaces_within_method_call_parentheses = true
+ij_php_spaces_within_method_parentheses = true
+ij_php_spaces_within_parentheses = true
+ij_php_spaces_within_switch_parentheses = true
+ij_php_spaces_within_while_parentheses = true
+ij_php_ternary_operation_signs_on_next_line = true
+ij_php_variable_naming_style = snake_case
+
+[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
+ij_html_add_new_line_before_tags = div,p,a
+ij_html_align_attributes = false
+ij_html_do_not_indent_children_of_tags = html,thead,tbody,tfoot
+ij_html_new_line_after_last_attribute = when multiline
+ij_html_space_inside_empty_tag = true
+ij_html_uniform_ident = true
diff --git a/.env.testing b/.env.testing
new file mode 100644
index 0000000..3aa2f5f
--- /dev/null
+++ b/.env.testing
@@ -0,0 +1,17 @@
+WP_ROOT_FOLDER="${APACHE_DOCUMENT_ROOT}"
+TEST_SITE_WP_ADMIN_PATH="/wp-admin"
+TEST_SITE_DB_NAME="wptest"
+TEST_SITE_DB_HOST="mysqltests"
+TEST_SITE_DB_USER="mysql"
+TEST_SITE_DB_PASSWORD="mysql"
+TEST_SITE_TABLE_PREFIX="wp_"
+TEST_DB_NAME="wptest"
+TEST_DB_HOST="mysqltests"
+TEST_DB_USER="mysql"
+TEST_DB_PASSWORD="mysql"
+TEST_TABLE_PREFIX="wp_"
+TEST_SITE_WP_URL="http://${WOOTESTS_IP}"
+TEST_SITE_WP_DOMAIN="${WOOTESTS_IP}"
+TEST_SITE_ADMIN_EMAIL="grola@seostudio.pl"
+TEST_SITE_ADMIN_USERNAME="admin"
+TEST_SITE_ADMIN_PASSWORD="admin"
diff --git a/.gitignore b/.gitignore
index 4b86223..16e7a8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
 .idea
 composer.lock
 build-coverage
-swagger
\ No newline at end of file
+swagger
+.phpcs-cache
diff --git a/composer.json b/composer.json
index afcddb9..8150bcf 100644
--- a/composer.json
+++ b/composer.json
@@ -1,52 +1,53 @@
 {
-  "name": "wpdesk/wp-forms",
-  "description": "WP Forms",
-  "authors": [
-    {
-      "name": "Marcin",
-      "email": "marcin@wpdesk.pl"
-    },
-    {
-      "name": "Krzysiek",
-      "email": "krzysiek@wpdesk.pl"
-    },
-    {
-      "name": "Piotr Potrebka",
-      "email": "piotr.potrebka@wpdesk.pl"
-    }
-  ],
-  "require": {
-    "php": ">=7.0",
-    "ext-curl": "*",
-    "ext-json": "*",
-    "wpdesk/wp-persistence": "^2.0|^3.0",
-    "wpdesk/wp-view": "^1.1"
-  },
-  "require-dev": {
-    "phpunit/phpunit": "<7",
-    "wp-coding-standards/wpcs": "^0.14.1",
-    "squizlabs/php_codesniffer": "^3.0.2",
-    "mockery/mockery": "*",
-    "10up/wp_mock": "*"
-  },
-  "autoload": {
-    "psr-4": {
-      "WPDesk\\Forms\\": "src/"
-    }
-  },
-  "autoload-dev": {
-  },
-  "extra": {
-    "text-domain": "wp-forms",
-    "translations-folder": "lang",
-    "po-files": {
-      "pl_PL": "pl_PL.po"
-    }
-  },
-  "scripts": {
-    "phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
-    "phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
-    "phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
-    "phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
-  }
+	"name": "wpdesk/wp-forms",
+	"description": "WP Forms",
+	"authors": [
+		{
+			"name": "Marcin",
+			"email": "marcin@wpdesk.pl"
+		},
+		{
+			"name": "Krzysiek",
+			"email": "krzysiek@wpdesk.pl"
+		},
+		{
+			"name": "Piotr Potrebka",
+			"email": "piotr.potrebka@wpdesk.pl"
+		}
+	],
+	"require": {
+		"php": ">=7.0",
+		"ext-curl": "*",
+		"ext-json": "*",
+		"wpdesk/wp-persistence": "^2.0|^3.0",
+		"wpdesk/wp-view": "^1.1"
+	},
+	"require-dev": {
+		"phpunit/phpunit": "<7",
+		"phpstan/phpstan": "^0.12",
+		"wpdesk/wp-code-sniffer": "^1.2.3",
+		"10up/wp_mock": "*",
+		"szepeviktor/phpstan-wordpress": "^0.7.7",
+		"phpstan/extension-installer": "^1.1"
+	},
+	"autoload": {
+		"psr-4": {
+			"WPDesk\\Forms\\": "src/"
+		}
+	},
+	"autoload-dev": {
+	},
+	"extra": {
+		"text-domain": "wp-forms",
+		"translations-folder": "lang",
+		"po-files": {
+			"pl_PL": "pl_PL.po"
+		}
+	},
+	"scripts": {
+		"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
+		"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
+		"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
+		"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
+	}
 }
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..6ef3f27
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<ruleset name="WordPress Coding Standards for WP Desk Plugin">
+
+	<!--
+	#############################################################################
+	COMMAND LINE ARGUMENTS
+	https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml
+	#############################################################################
+	-->
+
+	<!-- Scan all files. -->
+	<file>./src</file>
+	<file>./templates</file>
+
+	<!-- Only check PHP files. -->
+	<arg name="extensions" value="php"/>
+
+	<!-- Show progress, show the error codes for each message (source). -->
+	<arg value="sp"/>
+
+	<!-- Check up to 8 files simultaneously. -->
+	<arg name="parallel" value="8"/>
+
+	<!-- Cache outcomes for better performance. Remember to add the file to .gitignore. -->
+	<arg name="cache" value="./.phpcs-cache"/>
+
+	<!--
+	#############################################################################
+	USE THE WPDeskCS RULESET
+	#############################################################################
+	-->
+
+	<!-- Define plugin text domain for i18n. -->
+	<config name="text_domain" value="shopmagic-for-woocommerce"/>
+
+	<!-- This value should be aligned with WordPress support version declared in plugin header -->
+	<config name="minimum_supported_wp_version" value="5.0"/>
+
+	<!-- Set value aligned with supported PHP Version for PHPCompatibilityWP check. -->
+	<config name="testVersion" value="7.0-"/>
+
+	<rule ref="WPDeskPlugin"/>
+
+	<rule ref="Squiz.Commenting.ClassComment.Missing">
+		<exclude name="Squiz.Commenting.ClassComment.Missing"/>
+	</rule>
+
+</ruleset>
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..200d200
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,4 @@
+parameters:
+    level: max
+    paths:
+        - src/
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
index c78958b..8341e36 100644
--- a/phpunit-integration.xml
+++ b/phpunit-integration.xml
@@ -13,11 +13,5 @@
         </whitelist>
     </filter>
 
-    <logging>
-        <log type="junit" target="build-coverage/report.junit.xml"/>
-        <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/>
-        <log type="coverage-text" target="build-coverage/coverage.txt"/>
-        <log type="coverage-clover" target="build-coverage/clover.xml"/>
-    </logging>
 
 </phpunit>
\ No newline at end of file
diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 1d056b6..0510706 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
@@ -12,18 +11,12 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 interface ContainerForm {
-	/**
-	 * @param ContainerInterface $data
-	 *
-	 * @return void
-	 */
-	public function set_data( $data );
+	/** @return void */
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Put data from form into a container.
 	 *
-	 * @param PersistentContainer $container Target container.
-	 *
 	 * @return void
 	 */
 	public function put_data( PersistentContainer $container );
diff --git a/src/Escaper.php b/src/Escaper.php
index cb20d58..8c460dd 100644
--- a/src/Escaper.php
+++ b/src/Escaper.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms;
 
 interface Escaper {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return string
-	 */
-	public function escape( $value );
+	/** @param mixed $value */
+	public function escape( $value ): string;
 }
diff --git a/src/Field.php b/src/Field.php
index 4205df4..2a6569e 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use WPDesk\Forms\Field\BasicField;
-
 /**
  * The idea is that from the moment the factory returns this interface it's values cannot be changed.
  * And that is why here are only the getters.
@@ -13,157 +11,88 @@ use WPDesk\Forms\Field\BasicField;
  * @package WPDesk\Forms
  */
 interface Field {
-	/** @return string */
-	public function get_name();
+	public function get_name(): string;
 
 	/** @return mixed */
 	public function get_default_value();
 
-	/** @return string */
-	public function get_template_name();
+	public function get_template_name(): string;
 
-	/**
-	 * When this field is used on form this field will force it's own template.
-	 *
-	 * return bool
-	 */
-	public function should_override_form_template();
+	/** When this field is used on form this field will force it's own template. */
+	public function should_override_form_template(): bool;
 
-	/**
-	 * HTML label.
-	 *
-	 * @return string
-	 */
-	public function get_label();
+	/** HTML label. */
+	public function get_label(): string;
 
-	/** bool */
-	public function has_label();
+	public function has_label(): bool;
 
-	/**
-	 * Description for field. It can be shown near the field.
-	 *
-	 * @return string
-	 */
-	public function get_description();
+	public function get_description(): string;
 
-	/**
-	 * Additional field description that should be shown in optional hover tip.
-	 *
-	 * @return string
-	 */
-	public function get_description_tip();
+	/** Additional field description that should be shown in optional hover tip. */
+	public function get_description_tip(): string;
 
-	/** @return bool */
-	public function has_description_tip();
+	public function has_description_tip(): bool;
 
-	/** @return bool */
-	public function has_description();
+	public function has_description(): bool;
 
-	/**
-	 * @return bool
-	 */
-	public function is_readonly();
+	public function is_readonly(): bool;
 
-	/** @return bool */
-	public function is_disabled();
+	public function is_disabled(): bool;
 
-	/** @return string */
-	public function get_id();
+	public function get_id(): string;
 
-	/** @bool */
-	public function is_required();
+	public function is_required(): bool;
 
-	/** @return bool */
-	public function has_placeholder();
+	public function has_placeholder(): bool;
 
-	/** @return string */
-	public function get_placeholder();
+	public function get_placeholder(): string;
 
 	/**
 	 * @param string[] $except
 	 *
 	 * @return string[] name->value
 	 */
-	public function get_attributes( $except = [] );
+	public function get_attributes( array $except = [] ): array;
 
 	/**
-	 * @param string $name
-	 * @param string $default
+	 * @param string  $name
+	 * @param ?string $default
 	 *
 	 * @return string
 	 */
-	public function get_attribute( $name, $default = null );
+	public function get_attribute( string $name, $default = null ): string;
 
-	/** @return bool */
-	public function is_attribute_set( $name );
+	public function is_attribute_set( string $name ): bool;
 
-	/**
-	 * @param string $name
-	 *
-	 * @return string
-	 */
-	public function get_meta_value( $name );
+	public function get_meta_value( string $name ): string;
 
-	/** @return bool */
-	public function is_meta_value_set( $name );
+	public function is_meta_value_set( string $name ): bool;
 
-	/**
-	 * @return string
-	 */
-	public function get_classes();
+	public function get_classes(): string;
 
-	/** bool */
-	public function has_classes();
+	public function has_classes(): bool;
 
-	/** @return bool */
-	public function is_class_set( $name );
+	public function is_class_set( string $name ): bool;
 
-	/** bool */
-	public function has_data();
+	public function has_data(): bool;
 
-	/**
-	 * @return array
-	 */
-	public function get_data();
+	/** @return array<string,int> */
+	public function get_data(): array;
 
-	/**
-	 * @param string $data_name
-	 * @param string $data_value
-	 *
-	 * @return $this
-	 */
-	public function add_data( $data_name, $data_value );
+	public function add_data( string $data_name, string $data_value ): self;
 
-	/**
-	 * @param string $data_name
-	 *
-	 * @return $this
-	 */
-	public function unset_data( $data_name );
+	public function unset_data( string $data_name ): self;
 
-	/**
-	 * @return mixed
-	 */
+	/** @return mixed */
 	public function get_possible_values();
 
-	/**
-	 * @return bool
-	 */
-	public function is_multiple();
+	public function is_multiple(): bool;
 
-	/**
-	 * @return Validator
-	 */
-	public function get_validator();
+	public function get_validator(): Validator;
 
-	/**
-	 * @return Sanitizer
-	 */
-	public function get_sanitizer();
+	public function get_sanitizer(): Sanitizer;
 
-	/** @return Serializer */
-	public function get_serializer();
+	public function get_serializer(): Serializer;
 
-	/** @return int */
-	public function get_priority();
+	public function get_priority(): int;
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 54ef3cc..ee7f144 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -4,9 +4,11 @@ namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
 use WPDesk\Forms\Form\FormWithFields;
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer\NoSerialize;
+use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\ChainValidator;
 use WPDesk\Forms\Validator\RequiredValidator;
 
@@ -19,210 +21,165 @@ use WPDesk\Forms\Validator\RequiredValidator;
 abstract class BasicField implements Field {
 	use Field\Traits\HtmlAttributes;
 
-	/** @var array[] */
+	const DEFAULT_PRIORITY = 10;
+
+	/** @var array<string,int,bool> */
 	protected $meta;
 
+	/** @var string */
 	protected $default_value;
 
 	public function __construct() {
-		$this->meta['class'] = [];
-		$this->meta['priority'] = 10;
+		$this->meta['class']    = [];
+		$this->meta['priority'] = self::DEFAULT_PRIORITY;
 	}
 
-	public function get_label() {
+	public function get_label(): string {
 		return $this->meta['label'];
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_label( $value ) {
+	public function set_label( string $value ): self {
 		$this->meta['label'] = $value;
 
 		return $this;
 	}
 
-	public function get_description_tip() {
+	public function get_description_tip(): string {
 		return $this->meta['description_tip'];
 	}
 
-	public function has_description_tip() {
+	public function has_description_tip(): bool {
 		return isset( $this->meta['description_tip'] );
 	}
 
-	public function should_override_form_template() {
-		return isset( $this->attributes['overrite_template'] ) ? $this->attributes['overrite_template'] : false;
+	public function should_override_form_template(): bool {
+		return $this->attributes['overrite_template'] ?? false;
 	}
 
-	public function get_description() {
+	public function get_description(): string {
 		return $this->meta['description'];
 	}
 
-	public function has_label() {
+	public function has_label(): bool {
 		return isset( $this->meta['label'] );
 	}
 
-	public function has_description() {
+	public function has_description(): bool {
 		return isset( $this->meta['description'] );
 	}
 
-	public function set_description( $value ) {
+	public function set_description( string $value ): self {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( $value ) {
+	public function set_description_tip( string $value ): self {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @return array
-	 *
-	 * @deprecated not sure if needed. TODO: Check later.
-	 */
-	public function get_type() {
+	public function get_type(): string {
 		return $this->attributes['type'];
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_placeholder( $value ) {
+	public function set_placeholder( string $value ): self {
 		$this->meta['placeholder'] = $value;
 
 		return $this;
 	}
 
-	public function has_placeholder() {
+	public function has_placeholder(): bool {
 		return isset( $this->meta['placeholder'] );
 	}
 
-	public function get_placeholder() {
+	public function get_placeholder(): string {
 		return $this->meta['placeholder'];
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return $this
-	 */
-	public function set_name( $name ) {
+	public function set_name( string $name ): self {
 		$this->attributes['name'] = $name;
 
 		return $this;
 	}
 
-	public function get_meta_value( $name ) {
+	public function get_meta_value( string $name ): string {
 		return $this->meta[ $name ];
 	}
 
-	public function get_classes() {
+	public function get_classes(): string {
 		return implode( ' ', $this->meta['class'] );
 	}
 
-	public function has_classes() {
+	public function has_classes(): bool {
 		return ! empty( $this->meta['class'] );
 	}
 
-	public function has_data() {
+	public function has_data(): bool {
 		return ! empty( $this->meta['data'] );
 	}
 
-	/**
-	 * @return array
-	 */
-	public function get_data() {
-		return empty( $this->meta['data'] ) ? [] : $this->meta['data'];
+	public function get_data(): array {
+		return $this->meta['data'] ?: [];
 	}
 
 	public function get_possible_values() {
 		return isset( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
 	}
 
-	public function get_id() {
-		return isset( $this->attributes['id'] ) ? $this->attributes['id'] : sanitize_title( $this->get_name() );
+	public function get_id(): string {
+		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
-	public function get_name() {
+	public function get_name(): string {
 		return $this->attributes['name'];
 	}
 
-	public function is_multiple() {
-		return isset( $this->attributes['multiple'] ) ? $this->attributes['multiple'] : false;
+	public function is_multiple(): bool {
+		return $this->attributes['multiple'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_disabled() {
+	public function set_disabled(): self {
 		$this->attributes['disabled'] = true;
 
 		return $this;
 	}
 
-	public function is_disabled() {
-		return isset( $this->attributes['disabled'] ) ? $this->attributes['disabled'] : false;
+	public function is_disabled(): bool {
+		return $this->attributes['disabled'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_readonly() {
+	public function set_readonly(): self {
 		$this->attributes['readonly'] = true;
 
 		return $this;
 	}
 
-	public function is_readonly() {
-		return isset( $this->attributes['readonly'] ) ? $this->attributes['readonly'] : false;
+	public function is_readonly(): bool {
+		return $this->attributes['readonly'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_required() {
+	public function set_required(): self {
 		$this->meta['required'] = true;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $class_name
-	 *
-	 * @return $this
-	 */
-	public function add_class( $class_name ) {
+	public function add_class( string $class_name ): self {
 		$this->meta['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $class_name
-	 *
-	 * @return $this
-	 */
-	public function unset_class( $class_name ) {
+	public function unset_class( string $class_name ): self {
 		unset( $this->meta['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	/**
-	 * @param string $data_name
-	 * @param string $data_value
-	 *
-	 * @return $this
-	 */
-	public function add_data( $data_name, $data_value ) {
-		if ( !isset( $this->meta['data'] ) ) {
+	public function add_data( string $data_name, string $data_value ): self {
+		if ( ! isset( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
 		$this->meta['data'][ $data_name ] = $data_value;
@@ -230,44 +187,31 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	/**
-	 * @param string $data_name
-	 *
-	 * @return $this
-	 */
-	public function unset_data( $data_name ) {
+	public function unset_data( string $data_name ): self {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
 	}
 
-	public function is_meta_value_set( $name ) {
+	public function is_meta_value_set( string $name ): bool {
 		return isset( $this->meta[ $name ] );
 	}
 
-	public function is_class_set( $name ) {
+	public function is_class_set( string $name ): bool {
 		return isset( $this->meta['class'][ $name ] );
 	}
 
-	public function get_default_value() {
+	public function get_default_value(): string {
 		return $this->default_value;
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_default_value( $value ) {
+	public function set_default_value( string $value ): self {
 		$this->default_value = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @return ChainValidator
-	 */
-	public function get_validator() {
+	public function get_validator(): Validator {
 		$chain = new ChainValidator();
 		if ( $this->is_required() ) {
 			$chain->attach( new RequiredValidator() );
@@ -276,18 +220,15 @@ abstract class BasicField implements Field {
 		return $chain;
 	}
 
-	public function is_required() {
-		return isset( $this->meta['required'] ) ? $this->meta['required'] : false;
+	public function is_required(): bool {
+		return $this->meta['required'] ?? false;
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new NoSanitize();
 	}
 
-	/**
-	 * @return Serializer
-	 */
-	public function get_serializer() {
+	public function get_serializer(): Serializer {
 		if ( isset( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
 			return $this->meta['serializer'];
 		}
@@ -295,7 +236,7 @@ abstract class BasicField implements Field {
 		return new NoSerialize();
 	}
 
-	public function set_serializer( Serializer $serializer ) {
+	public function set_serializer( Serializer $serializer ): self {
 		$this->meta['serializer'] = $serializer;
 
 		return $this;
diff --git a/src/Field/ButtonField.php b/src/Field/ButtonField.php
index 86312d0..f0a4023 100644
--- a/src/Field/ButtonField.php
+++ b/src/Field/ButtonField.php
@@ -2,14 +2,12 @@
 
 namespace WPDesk\Forms\Field;
 
-class ButtonField extends NoValueField
-{
-    public function get_template_name()
-    {
-        return 'button';
-    }
-    public function get_type()
-    {
-        return 'button';
-    }
+class ButtonField extends NoValueField {
+
+	public function get_template_name(): string {
+		return 'button';
+	}
+	public function get_type(): string {
+		return 'button';
+	}
 }
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index 705c4fe..e8cc29f 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -2,9 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
-
 class CheckboxField extends BasicField {
-	const VALUE_TRUE = 'yes';
+	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
 
 	public function __construct() {
@@ -12,21 +11,21 @@ class CheckboxField extends BasicField {
 		$this->set_attribute( 'type', 'checkbox' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-checkbox';
 	}
 
-	public function get_sublabel() {
+	public function get_sublabel(): string {
 		return $this->meta['sublabel'];
 	}
 
-	public function set_sublabel( $value ) {
+	public function set_sublabel( string $value ): self {
 		$this->meta['sublabel'] = $value;
 
 		return $this;
 	}
 
-	public function has_sublabel() {
+	public function has_sublabel(): bool {
 		return isset( $this->meta['sublabel'] );
 	}
 }
diff --git a/src/Field/DatePickerField.php b/src/Field/DatePickerField.php
index 8b50df8..7060d90 100644
--- a/src/Field/DatePickerField.php
+++ b/src/Field/DatePickerField.php
@@ -2,22 +2,23 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class DatePickerField extends BasicField {
 	public function __construct() {
 		parent::__construct();
 		$this->set_default_value( '' );
-		$this->add_class('date-picker');
-		$this->set_placeholder('YYYY-MM-DD');
+		$this->add_class( 'date-picker' );
+		$this->set_placeholder( 'YYYY-MM-DD' );
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-date-picker';
 	}
 }
diff --git a/src/Field/Header.php b/src/Field/Header.php
index 491d99c..fa86700 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -8,15 +8,15 @@ class Header extends NoValueField {
 		$this->meta['header_size'] = '';
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'header';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 
-	public function set_header_size( $value ) {
+	public function set_header_size( int $value ): self {
 		$this->meta['header_size'] = $value;
 
 		return $this;
diff --git a/src/Field/HiddenField.php b/src/Field/HiddenField.php
index 51b7808..9c3856c 100644
--- a/src/Field/HiddenField.php
+++ b/src/Field/HiddenField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class HiddenField extends BasicField {
@@ -11,11 +12,11 @@ class HiddenField extends BasicField {
 		$this->set_attribute( 'type', 'hidden' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-hidden';
 	}
 }
diff --git a/src/Field/ImageInputField.php b/src/Field/ImageInputField.php
index 95d4bb6..74c8410 100644
--- a/src/Field/ImageInputField.php
+++ b/src/Field/ImageInputField.php
@@ -10,10 +10,7 @@ class ImageInputField extends BasicField {
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-image';
 	}
 }
diff --git a/src/Field/InputNumberField.php b/src/Field/InputNumberField.php
index a563cd2..9ee7405 100644
--- a/src/Field/InputNumberField.php
+++ b/src/Field/InputNumberField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputNumberField extends BasicField {
@@ -11,11 +12,11 @@ class InputNumberField extends BasicField {
 		$this->set_attribute( 'type', 'number' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-number';
 	}
 }
diff --git a/src/Field/InputTextField.php b/src/Field/InputTextField.php
index 2070412..7ca6a96 100644
--- a/src/Field/InputTextField.php
+++ b/src/Field/InputTextField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputTextField extends BasicField {
@@ -11,11 +12,11 @@ class InputTextField extends BasicField {
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-text';
 	}
 }
diff --git a/src/Field/MultipleInputTextField.php b/src/Field/MultipleInputTextField.php
index fab8398..cf976fe 100644
--- a/src/Field/MultipleInputTextField.php
+++ b/src/Field/MultipleInputTextField.php
@@ -4,10 +4,7 @@ namespace WPDesk\Forms\Field;
 
 class MultipleInputTextField extends InputTextField {
 
-	/**
-	 * @return string
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-text-multiple';
 	}
 }
diff --git a/src/Field/NoOnceField.php b/src/Field/NoOnceField.php
index 0b6eeaf..6419a37 100644
--- a/src/Field/NoOnceField.php
+++ b/src/Field/NoOnceField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\NonceValidator;
 
 class NoOnceField extends BasicField {
@@ -11,11 +12,11 @@ class NoOnceField extends BasicField {
 		$this->meta['action'] = $action_name;
 	}
 
-	public function get_validator() {
+	public function get_validator(): Validator {
 		return new NonceValidator( $this->get_meta_value( 'action' ) );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'noonce';
 	}
 }
diff --git a/src/Field/NoValueField.php b/src/Field/NoValueField.php
index 830f47e..90bbecb 100644
--- a/src/Field/NoValueField.php
+++ b/src/Field/NoValueField.php
@@ -8,7 +8,7 @@ namespace WPDesk\Forms\Field;
  * @package WPDesk\Forms
  */
 abstract class NoValueField extends BasicField {
-	public function get_name() {
+	public function get_name(): string {
 		return '';
 	}
 }
diff --git a/src/Field/Paragraph.php b/src/Field/Paragraph.php
index c62cb6b..6e74de3 100644
--- a/src/Field/Paragraph.php
+++ b/src/Field/Paragraph.php
@@ -3,11 +3,11 @@
 namespace WPDesk\Forms\Field;
 
 class Paragraph extends NoValueField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'paragraph';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 19b14ae..8960304 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -8,7 +8,7 @@ class ProductSelect extends SelectField {
 		$this->set_multiple();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'product-select';
 	}
 }
diff --git a/src/Field/RadioField.php b/src/Field/RadioField.php
index 69630bf..3e20d1b 100644
--- a/src/Field/RadioField.php
+++ b/src/Field/RadioField.php
@@ -3,7 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class RadioField extends BasicField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-radio';
 	}
 }
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index 0578379..bead3bb 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -4,17 +4,18 @@ namespace WPDesk\Forms\Field;
 
 class SelectField extends BasicField {
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'select';
 	}
 
-	public function set_options( $options ) {
+	/** @param string[] $options */
+	public function set_options( array $options ): self {
 		$this->meta['possible_values'] = $options;
 
 		return $this;
 	}
 
-	public function set_multiple() {
+	public function set_multiple(): self {
 		$this->attributes['multiple'] = true;
 
 		return $this;
diff --git a/src/Field/SubmitField.php b/src/Field/SubmitField.php
index c8e1f79..bcb00f7 100644
--- a/src/Field/SubmitField.php
+++ b/src/Field/SubmitField.php
@@ -3,15 +3,15 @@
 namespace WPDesk\Forms\Field;
 
 class SubmitField extends NoValueField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-submit';
 	}
 
-	public function get_type() {
+	public function get_type(): string {
 		return 'submit';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/Field/TextAreaField.php b/src/Field/TextAreaField.php
index 94873b3..0f83ffe 100644
--- a/src/Field/TextAreaField.php
+++ b/src/Field/TextAreaField.php
@@ -8,7 +8,7 @@ class TextAreaField extends BasicField {
 		$this->set_default_value( '' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'textarea';
 	}
 }
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index 55b1fb1..8468254 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -3,10 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class TimepickerField extends BasicField {
-	/**
-	 * @inheritDoc
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'timepicker';
 	}
 }
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 8116ee9..4e54c85 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -19,51 +19,39 @@ trait HtmlAttributes {
 	 *
 	 * @return string[]
 	 */
-	public function get_attributes( $except = [ 'name', 'type' ] ) {
-		return array_filter( $this->attributes, function ( $value, $key ) use ( $except ) {
-			return ! in_array( $key, $except, true );
-		}, ARRAY_FILTER_USE_BOTH );
+	public function get_attributes( array $except = [ 'name', 'type' ] ): array {
+		return array_filter(
+			$this->attributes,
+			static function ( $value, $key ) use ( $except ) {
+				return ! in_array( $key, $except, true );
+			},
+			ARRAY_FILTER_USE_BOTH
+		);
 	}
 
-	/**
-	 * @param string $name
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_attribute( $name, $value ) {
+	public function set_attribute( string $name, string $value ): self {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return $this
-	 */
-	public function unset_attribute( $name ) {
+	public function unset_attribute( string $name ): self {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return bool
-	 */
-	public function is_attribute_set( $name ) {
+	public function is_attribute_set( string $name ): bool {
 		return isset( $this->attributes[ $name ] );
 	}
 
 	/**
-	 * @param string $name
-	 * @param mixed $default
+	 * @param string  $name
+	 * @param ?string $default
 	 *
 	 * @return string
 	 */
-	public function get_attribute( $name, $default = null ) {
+	public function get_attribute( string $name, $default = null ): string {
 		return $this->attributes[ $name ] ?? $default;
 	}
 }
diff --git a/src/Field/WooSelect.php b/src/Field/WooSelect.php
index b8d9538..bc59f9c 100644
--- a/src/Field/WooSelect.php
+++ b/src/Field/WooSelect.php
@@ -9,7 +9,7 @@ class WooSelect extends SelectField {
 		$this->add_class( 'wc-enhanced-select' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'woo-select';
 	}
 }
diff --git a/src/Field/WyswigField.php b/src/Field/WyswigField.php
index 846c919..06db980 100644
--- a/src/Field/WyswigField.php
+++ b/src/Field/WyswigField.php
@@ -8,11 +8,11 @@ class WyswigField extends BasicField {
 		$this->set_default_value( '' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'wyswig';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/FieldProvider.php b/src/FieldProvider.php
index f7f3841..e693d00 100644
--- a/src/FieldProvider.php
+++ b/src/FieldProvider.php
@@ -11,5 +11,5 @@ interface FieldProvider {
 	 *
 	 * @return Field[]
 	 */
-	public function get_fields();
+	public function get_fields(): array;
 }
diff --git a/src/FieldRenderer.php b/src/FieldRenderer.php
index 37a356d..f60c1b0 100644
--- a/src/FieldRenderer.php
+++ b/src/FieldRenderer.php
@@ -2,16 +2,7 @@
 
 namespace WPDesk\Forms;
 
-/**
- * @class FieldRenderer
- */
 interface FieldRenderer {
-	/**
-	 * @param FieldProvider $provider
-	 * @param array $fields_data
-	 * @param string $name_prefix
-	 *
-	 * @return string|array String or normalized array
-	 */
-	public function render_fields( FieldProvider $provider, array $fields_data, $name_prefix = '' );
+	/** @return string|array String or normalized array */
+	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' );
 }
diff --git a/src/FieldsDataReceiver.php b/src/FieldsDataReceiver.php
index 9e2bdc9..86a1583 100644
--- a/src/FieldsDataReceiver.php
+++ b/src/FieldsDataReceiver.php
@@ -14,8 +14,6 @@ interface FieldsDataReceiver {
 	/**
 	 * Set values corresponding to fields.
 	 *
-	 * @param ContainerInterface $data
-	 *
 	 * @return void
 	 */
 	public function update_fields_data( ContainerInterface $data );
diff --git a/src/Form.php b/src/Form.php
index 7450b2b..8ea2d78 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -12,55 +12,51 @@ use WPDesk\View\Renderer\Renderer;
 interface Form {
 	/**
 	 * For some reason you may want to disable a form. Returns false when disabled.
-	 *
-	 * @return bool
 	 */
-	public function is_active();
+	public function is_active(): bool;
 
 	/**
 	 * Whether form handle_request method was successfully executed.
-	 *
-	 * @return bool
 	 */
-	public function is_submitted();
+	public function is_submitted(): bool;
 
 	/**
 	 * After handle_request or set_data the data in form can be invalid according to field validators.
-	 * Returns false when onle of them says the data is invalid.
-	 *
-	 * @return bool
+	 * Returns false when one of them says the data is invalid.
 	 */
-	public function is_valid();
+	public function is_valid(): bool;
 
 	/**
 	 * Add array to update data.
 	 *
 	 * @param array $request New data to update.
+	 *
+	 * @return void
 	 */
-	public function handle_request( $request = array() );
+	public function handle_request( array $request = [] );
 
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
 	 * @param array $data Data for form.
+	 *
+	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( array $data );
 
 	/**
 	 * Use to render the form to string.
 	 *
 	 * @param Renderer $renderer Renderer to render form fields and form-templates.
-	 *
-	 * @return string
 	 */
-	public function render_form( Renderer $renderer );
+	public function render_form( Renderer $renderer ): string;
 
 	/**
 	 * Get data from form. Use after handle_request or set_data.
 	 *
-	 * @return array
+	 * @return array<int,string>
 	 */
-	public function get_data();
+	public function get_data(): array;
 
 	/**
 	 * Get data from form. Use after handle_request or set_data.
@@ -68,13 +64,11 @@ interface Form {
 	 *
 	 * @return array
 	 */
-	public function get_normalized_data();
+	public function get_normalized_data(): array;
 
 	/**
 	 * Form if you ever need to have more than one form at once.
-	 *
-	 * @return string
 	 */
-	public function get_form_id();
+	public function get_form_id(): int;
 }
 
diff --git a/src/Form/AbstractForm.php b/src/Form/AbstractForm.php
deleted file mode 100644
index b51a0e3..0000000
--- a/src/Form/AbstractForm.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Form;
-
-
-/**
- * Old abstraction layer for forms.
- *
- * @package WPDesk\Forms
- *
- * @deprecated Use ony for backward compatibility with Forms 1.x
- */
-abstract class AbstractForm {
-
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
-	protected $form_id = 'form';
-
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
-	protected $updated_data = array();
-
-
-	/**
-	 * Checks if form should be active.
-	 *
-	 * @return bool
-	 */
-	public function is_active() {
-		return true;
-	}
-
-	/**
-	 * Create form data and return an associative array.
-	 *
-	 * @return array
-	 */
-	abstract protected function create_form_data();
-
-	/**
-	 * Add array to update data.
-	 *
-	 * @param array $new_data new data to update.
-	 */
-	public function update_form_data( array $new_data = array() ) {
-		$this->updated_data = $new_data;
-	}
-
-	/**
-	 * Merge created and updated data and return associative array. Add to all keys form prefix.
-	 *
-	 * @return array
-	 */
-	public function get_form_data() {
-		return array_merge(
-			$this->create_form_data(),
-			$this->updated_data
-		);
-	}
-
-	/**
-	 * Get prefixed array returns array with prefixed form_id
-	 *
-	 * @return array
-	 */
-	public function get_prefixed_form_data() {
-		$array   = $this->get_form_data();
-		$form_id = $this->get_form_id();
-
-		return array_combine(
-			array_map( function ( $k ) use ( $form_id ) {
-				return $form_id . '_' . $k;
-			}, array_keys( $array ) ),
-			$array
-		);
-	}
-
-	/**
-	 * return form Id
-	 *
-	 * @return string
-	 */
-	public function get_form_id() {
-		return $this->form_id;
-	}
-
-}
-
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index a5a494c..45dc515 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -15,91 +15,58 @@ use WPDesk\View\Renderer\Renderer;
 class FormWithFields implements Form, ContainerForm, FieldProvider {
 	use Field\Traits\HtmlAttributes;
 
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
+	/** @var string Unique form_id. */
 	protected $form_id = 'form';
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
+
+	/** @var array Updated data. */
 	private $updated_data;
-	/**
-	 * Form fields.
-	 *
-	 * @var Field[]
-	 */
+
+	/** @var Field[] Form fields. */
 	private $fields;
 
 	/**
 	 * FormWithFields constructor.
 	 *
-	 * @param array $fields Form fields.
-	 * @param string $form_id Unique form id.
+	 * @param Field[]  $fields
+	 * @param string $form_id
 	 */
-	public function __construct( array $fields, $form_id = 'form' ) {
-		$this->fields       = $fields;
-		$this->form_id      = $form_id;
-		$this->updated_data = null;
+	public function __construct( array $fields, string $form_id = 'form' ) {
+		$this->fields  = $fields;
+		$this->form_id = $form_id;
 	}
 
-	/**
-	 * Set Form action attribute.
-	 *
-	 * @param string $action
-	 */
-	public function set_action( $action ) {
+	/** Set Form action attribute. */
+	public function set_action( string $action ): self {
 		$this->attributes['action'] = $action;
 
 		return $this;
 	}
 
-	/**
-	 * Set Form method attribute ie. GET/POST.
-	 *
-	 * @param string $method
-	 */
-	public function set_method( $method ) {
+	/** Set Form method attribute ie. GET/POST. */
+	public function set_method( string $method ): self {
 		$this->attributes['method'] = $method;
 
 		return $this;
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_method() {
-		return isset( $this->attributes['method'] ) ? $this->attributes['method'] : 'POST';
+	public function get_method(): string {
+		return $this->attributes['method'] ?? 'POST';
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_action() {
-		return isset( $this->attributes['action'] ) ? $this->attributes['action'] : '';
+	public function get_action(): string {
+		return $this->attributes['action'] ?? '';
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_submitted() {
+	public function is_submitted(): bool {
 		return null !== $this->updated_data;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
+	/** @return void */
 	public function add_field( Field $field ) {
 		$this->fields[] = $field;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_active() {
+	public function is_active(): bool {
 		return true;
 	}
 
@@ -107,17 +74,16 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 * Add more fields to form.
 	 *
 	 * @param Field[] $fields Field to add to form.
+	 *
+	 * @return void
 	 */
 	public function add_fields( array $fields ) {
 		array_map( [ $this, 'add_field' ], $fields );
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_valid() {
+	public function is_valid(): bool {
 		foreach ( $this->fields as $field ) {
-			$field_value     = isset( $this->updated_data[ $field->get_name() ] ) ? $this->updated_data[ $field->get_name() ] : $field->get_default_value();
+			$field_value     = $this->updated_data[ $field->get_name() ] ?? $field->get_default_value();
 			$field_validator = $field->get_validator();
 			if ( ! $field_validator->is_valid( $field_value ) ) {
 				return false;
@@ -132,7 +98,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 *
 	 * @param array|ContainerInterface $request new data to update.
 	 */
-	public function handle_request( $request = array() ) {
+	public function handle_request( array $request = [] ) {
 		if ( $this->updated_data === null ) {
 			$this->updated_data = [];
 		}
@@ -165,48 +131,41 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		}
 	}
 
-	/**
-	 * Renders only fields without form.
-	 *
-	 * @param Renderer $renderer
-	 *
-	 * @return string
-	 */
-	public function render_fields( Renderer $renderer ) {
+	/** Renders only fields without form. */
+	public function render_fields( Renderer $renderer ): string {
 		$content     = '';
 		$fields_data = $this->get_data();
 		foreach ( $this->get_fields() as $field ) {
-			$content .= $renderer->render( $field->should_override_form_template() ? $field->get_template_name() : 'form-field',
+			$content .= $renderer->render(
+				$field->should_override_form_template() ? $field->get_template_name() : 'form-field',
 				[
 					'field'         => $field,
 					'renderer'      => $renderer,
 					'name_prefix'   => $this->get_form_id(),
-					'value'         => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
+					'value'         => $fields_data[ $field->get_name() ] ?? $field->get_default_value(),
 					'template_name' => $field->get_template_name(),
-				] );
+				]
+			);
 		}
 
 		return $content;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function render_form( Renderer $renderer ) {
-		$content = $renderer->render( 'form-start', [
-			'form'   => $this,
-			'method' => $this->get_method(), // backward compat
-			'action' => $this->get_action(),  // backward compat
-		] );
+	public function render_form( Renderer $renderer ): string {
+		$content  = $renderer->render(
+			'form-start',
+			[
+				'form'   => $this,
+				'method' => $this->get_method(), // backward compat.
+				'action' => $this->get_action(),  // backward compat.
+			]
+		);
 		$content .= $this->render_fields( $renderer );
 		$content .= $renderer->render( 'form-end' );
 
 		return $content;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public function put_data( PersistentContainer $container ) {
 		foreach ( $this->get_fields() as $field ) {
 			$data_key = $field->get_name();
@@ -223,10 +182,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		}
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_data() {
+	public function get_data(): array {
 		$data = $this->updated_data;
 
 		foreach ( $this->get_fields() as $field ) {
@@ -239,10 +195,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $data;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_fields() {
+	public function get_fields(): array {
 		$fields = $this->fields;
 
 		usort(
@@ -255,17 +208,11 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $fields;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_form_id() {
+	public function get_form_id(): int {
 		return $this->form_id;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_normalized_data() {
+	public function get_normalized_data(): array {
 		return $this->get_data();
 	}
 }
diff --git a/src/Form/FormsCollection.php b/src/Form/FormsCollection.php
deleted file mode 100644
index f2603a3..0000000
--- a/src/Form/FormsCollection.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Form;
-
-use WPDesk\Forms\Form;
-
-/**
- * FormsCollection class store AbstractForm instances and merges forms data from all collections
- *
- * @deprecated Use ony for backward compatibility with Forms 1.x
- *
- * @package WPDesk\Forms
- */
-class FormsCollection {
-	/**
-	 * AbstractForm array collection.
-	 *
-	 * @var Form[]
-	 */
-	protected $forms = array();
-
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
-	protected $form_id = 'form';
-
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
-	protected $updated_data = array();
-
-	/**
-	 * Add forms. All keys in this array must be unique, otherwise add_form will throw exception.
-	 *
-	 * @param Form[] $forms
-	 */
-	public function add_forms( array $forms = array() ) {
-		foreach ( $forms as $form_object ) {
-			$this->add_form( $form_object );
-		}
-	}
-
-	/**
-	 * Add form. If key is not unique throw exception.
-	 *
-	 * @param Form $form
-	 *
-	 * @throws \OutOfBoundsException
-	 */
-	public function add_form( AbstractForm $form ) {
-		if ( ! $this->is_form_exists( $form->get_form_id() ) ) {
-			$this->forms[ $form->get_form_id() ] = $form;
-		} else {
-			throw new \OutOfBoundsException( 'Form with this key already exists' );
-		}
-	}
-
-	/**
-	 * Is form exists. Checks if key exists in the array of forms and return bool.
-	 *
-	 * @param string $form_id
-	 *
-	 * @return bool
-	 */
-	public function is_form_exists( $form_id ) {
-		return isset( $this->forms[ (string) $form_id ] );
-	}
-
-	/**
-	 * Get form.
-	 *
-	 * @param string $form_id
-	 *
-	 * @return Form
-	 * @throws \OutOfRangeException
-	 */
-	public function get_form( $form_id ) {
-		if ( $this->is_form_exists( $form_id ) ) {
-			return $this->forms[ (string) $form_id ];
-		}
-
-		throw new \OutOfRangeException( 'Form with this key not exists' );
-	}
-
-	/**
-	 * Get forms data. This method merge all arrays from forms and return associative array for woocommerce form_fields.
-	 *
-	 * @param bool $prefixed if true add form_id as prefix to form keys
-	 *
-	 * @return array
-	 */
-	public function get_forms_data( $prefixed = false ) {
-
-		$forms_data = array();
-
-		foreach ( $this->forms as $form ) {
-			if ( ! $form->is_active() ) {
-				continue;
-			}
-
-			if ( $prefixed ) {
-				$forms_data = array_merge( $forms_data, $form->get_prefixed_form_data() );
-			} else {
-				$forms_data = array_merge( $forms_data, $form->get_form_data() );
-			}
-		}
-
-		return $forms_data;
-	}
-
-}
diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php
index 092a01a..02f2d4f 100644
--- a/src/Persistence/FieldPersistenceStrategy.php
+++ b/src/Persistence/FieldPersistenceStrategy.php
@@ -12,6 +12,7 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 class FieldPersistenceStrategy {
+
 	/** @var PersistentContainer */
 	private $persistence;
 
@@ -21,9 +22,6 @@ class FieldPersistenceStrategy {
 
 	/**
 	 * Save fields data.
-	 *
-	 * @param FieldProvider $fields_provider
-	 * @param array $data
 	 */
 	public function persist_fields( FieldProvider $fields_provider, array $data ) {
 		foreach ( $fields_provider->get_fields() as $field ) {
@@ -34,10 +32,8 @@ class FieldPersistenceStrategy {
 
 	/**
 	 * Load fields data.
-	 *
-	 * @return array
 	 */
-	public function load_fields( FieldProvider $fields_provider ) {
+	public function load_fields( FieldProvider $fields_provider ): array {
 		$data = [];
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
@@ -45,7 +41,7 @@ class FieldPersistenceStrategy {
 				$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
 			} catch ( NotFoundExceptionInterface $not_found ) {
 				// TODO: Logger
-//				LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
+				// LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
 			}
 		}
 
diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 4d078ac..371490c 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -18,7 +18,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 	 *
 	 * @return array Normalized fields with data.
 	 */
-	public function render_fields( FieldProvider $provider, array $fields_data, $name_prefix = '' ) {
+	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' ): array {
 		$rendered_fields = [];
 		foreach ( $provider->get_fields() as $field ) {
 			$rendered = [
@@ -29,7 +29,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				'readonly' => $field->is_readonly(),
 				'required' => $field->is_required(),
 				'prefix'   => $name_prefix,
-				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value()
+				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
 			];
 
 			if ( $field->has_classes() ) {
@@ -52,7 +52,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				$rendered['options'] = $options;
 			}
 			if ( $field->has_data() ) {
-				$data = $field->get_data();
+				$data             = $field->get_data();
 				$rendered['data'] = [];
 				foreach ( $data as $data_name => $data_value ) {
 					$rendered['data'][] = [
@@ -61,7 +61,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 					];
 				}
 			}
-			if (json_encode($rendered) !== false) {
+			if ( json_encode( $rendered ) !== false ) {
 				$rendered_fields[] = $rendered;
 			}
 		}
diff --git a/src/Resolver/DefaultFormFieldResolver.php b/src/Resolver/DefaultFormFieldResolver.php
index 3609a69..b5c1675 100644
--- a/src/Resolver/DefaultFormFieldResolver.php
+++ b/src/Resolver/DefaultFormFieldResolver.php
@@ -12,6 +12,7 @@ use WPDesk\View\Resolver\Resolver;
  * @package WPDesk\Forms\Resolver
  */
 class DefaultFormFieldResolver implements Resolver {
+
 	/** @var Resolver */
 	private $dir_resolver;
 
@@ -19,8 +20,8 @@ class DefaultFormFieldResolver implements Resolver {
 		$this->dir_resolver = new DirResolver( __DIR__ . '/../../templates' );
 	}
 
-	public function resolve( $name, Renderer $renderer = null ) {
+	public function resolve( $name, Renderer $renderer = null ): string {
 		return $this->dir_resolver->resolve( $name, $renderer );
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/Sanitizer.php b/src/Sanitizer.php
index a7883dc..bc8f207 100644
--- a/src/Sanitizer.php
+++ b/src/Sanitizer.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms;
 
 interface Sanitizer {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return string
-	 */
-	public function sanitize( $value );
+	/** @param mixed $value */
+	public function sanitize( $value ): string;
 }
diff --git a/src/Sanitizer/CallableSanitizer.php b/src/Sanitizer/CallableSanitizer.php
index c0a28b9..da916ab 100644
--- a/src/Sanitizer/CallableSanitizer.php
+++ b/src/Sanitizer/CallableSanitizer.php
@@ -5,13 +5,15 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class CallableSanitizer implements Sanitizer {
+
+	/** @var callable */
 	private $callable;
 
-	public function __construct( $callable ) {
+	public function __construct( callable $callable ) {
 		$this->callable = $callable;
 	}
 
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return call_user_func( $this->callable, $value );
 	}
 
diff --git a/src/Sanitizer/NoSanitize.php b/src/Sanitizer/NoSanitize.php
index a3fe4a6..21bce01 100644
--- a/src/Sanitizer/NoSanitize.php
+++ b/src/Sanitizer/NoSanitize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class NoSanitize implements Sanitizer {
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return $value;
 	}
 
diff --git a/src/Sanitizer/TextFieldSanitizer.php b/src/Sanitizer/TextFieldSanitizer.php
index 0a1bbcb..325c652 100644
--- a/src/Sanitizer/TextFieldSanitizer.php
+++ b/src/Sanitizer/TextFieldSanitizer.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class TextFieldSanitizer implements Sanitizer {
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return sanitize_text_field( $value );
 	}
 
diff --git a/src/Serializer.php b/src/Serializer.php
index 9105400..8302325 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -3,7 +3,17 @@
 namespace WPDesk\Forms;
 
 interface Serializer {
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
 	public function serialize( $value );
 
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
 	public function unserialize( $value );
 }
diff --git a/src/Serializer/JsonSerializer.php b/src/Serializer/JsonSerializer.php
index d7e5ca0..bc8c0e0 100644
--- a/src/Serializer/JsonSerializer.php
+++ b/src/Serializer/JsonSerializer.php
@@ -5,8 +5,8 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class JsonSerializer implements Serializer {
-	public function serialize( $value ) {
-		return json_encode( $value );
+	public function serialize( $value ): string {
+		return (string) json_encode( $value );
 	}
 
 	public function unserialize( $value ) {
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index b29e88b..31a09e1 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		return $value;
 	}
 
diff --git a/src/Serializer/ProductSelectSerializer.php b/src/Serializer/ProductSelectSerializer.php
index 2adf327..e801d4d 100644
--- a/src/Serializer/ProductSelectSerializer.php
+++ b/src/Serializer/ProductSelectSerializer.php
@@ -10,9 +10,6 @@ use WPDesk\Forms\Serializer;
  * @package WPDesk\Forms\Serializer
  */
 class ProductSelectSerializer implements Serializer {
-	/**
-	 * @param $value
-	 */
 	public function serialize( $value ) {
 		$products_with_names = [];
 		if ( is_array( $value ) ) {
diff --git a/src/Validator.php b/src/Validator.php
index d953702..2281820 100644
--- a/src/Validator.php
+++ b/src/Validator.php
@@ -3,15 +3,9 @@
 namespace WPDesk\Forms;
 
 interface Validator {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return bool
-	 */
-	public function is_valid( $value );
+	/** @param mixed $value */
+	public function is_valid( $value ): bool;
 
-	/**
-	 * @return string[]
-	 */
-	public function get_messages();
+	/** @return string[] */
+	public function get_messages(): array;
 }
diff --git a/src/Validator/ChainValidator.php b/src/Validator/ChainValidator.php
index d3549d5..341abee 100644
--- a/src/Validator/ChainValidator.php
+++ b/src/Validator/ChainValidator.php
@@ -5,9 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class ChainValidator implements Validator {
+
 	/** @var Validator[] */
 	private $validators;
 
+	/** @var array */
 	private $messages;
 
 	public function __construct() {
@@ -20,13 +22,13 @@ class ChainValidator implements Validator {
 	 *
 	 * @return $this
 	 */
-	public function attach( Validator $validator ) {
+	public function attach( Validator $validator ): self {
 		$this->validators[] = $validator;
 
 		return $this;
 	}
 
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		$result   = true;
 		$messages = [ [] ];
 		foreach ( $this->validators as $validator ) {
@@ -40,7 +42,7 @@ class ChainValidator implements Validator {
 		return $result;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return $this->messages;
 	}
 
diff --git a/src/Validator/NoValidateValidator.php b/src/Validator/NoValidateValidator.php
index dbc9966..04cf59c 100644
--- a/src/Validator/NoValidateValidator.php
+++ b/src/Validator/NoValidateValidator.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class NoValidateValidator implements Validator {
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		return true;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/src/Validator/NonceValidator.php b/src/Validator/NonceValidator.php
index 8768225..8709af6 100644
--- a/src/Validator/NonceValidator.php
+++ b/src/Validator/NonceValidator.php
@@ -5,19 +5,18 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class NonceValidator implements Validator {
+
 	private $action;
 
 	public function __construct( $action ) {
 		$this->action = $action;
 	}
 
-	public function is_valid( $value ) {
-		$valid = wp_verify_nonce( $value, $this->action );
-
-		return $valid;
+	public function is_valid( $value ): bool {
+		return wp_verify_nonce( $value, $this->action );
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/src/Validator/RequiredValidator.php b/src/Validator/RequiredValidator.php
index 016d803..4e78faf 100644
--- a/src/Validator/RequiredValidator.php
+++ b/src/Validator/RequiredValidator.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class RequiredValidator implements Validator {
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		return $value !== null;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/templates/button.php b/templates/button.php
index 43c2119..c558c6e 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -6,26 +6,31 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
+
 ?>
 
 <button
-<?php if ($field->has_classes()): ?>
-	class="<?php echo \esc_attr($field->get_classes()); ?>"
+<?php if ( $field->has_classes() ) : ?>
+	class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 <?php endif; ?>
 
-<?php foreach ($field->get_attributes([]) as $key => $val): ?>
-	<?php echo $key.'="'.\esc_attr($val).'"'; ?>
+<?php foreach ( $field->get_attributes( [] ) as $key => $val ) : ?>
+	<?php echo $key . '="' . \esc_attr( $val ) . '"'; ?>
 <?php endforeach; ?>
 
-	type="<?php echo \esc_attr($field->get_type()); ?>"
-	name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).']'?>"
-	id="<?php echo \esc_attr($field->get_id()); ?>"
-	value="<?php echo \esc_html($value); ?>"
+	type="<?php echo \esc_attr( $field->get_type() ); ?>"
+	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
+	value="<?php echo \esc_html( $value ); ?>"
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
 
-><?php echo \esc_html($field->get_label()); ?></button>
+><?php echo \esc_html( $field->get_label() ); ?></button>
diff --git a/templates/form-field.php b/templates/form-field.php
index 971e53b..50f5678 100644
--- a/templates/form-field.php
+++ b/templates/form-field.php
@@ -6,24 +6,28 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 
 <tr valign="top">
-	<?php if ( $field->has_label() ): ?>
+	<?php if ( $field->has_label() ) : ?>
 		<?php echo $renderer->render( 'form-label', [ 'field' => $field ] ); ?>
 	<?php endif; ?>
 
 	<td class="forminp">
-		<?php echo $renderer->render( $template_name, [
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		] ); ?>
+		<?php
+		echo $renderer->render(
+			$template_name,
+			[
+				'field'       => $field,
+				'renderer'    => $renderer,
+				'name_prefix' => $name_prefix,
+				'value'       => $value,
+			]
+		);
+		?>
 
-		<?php if ( $field->has_description() ): ?>
+		<?php if ( $field->has_description() ) : ?>
 			<p class="description"><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		<?php endif; ?>
 	</td>
diff --git a/templates/form-label.php b/templates/form-label.php
index 703ed78..f6268a5 100644
--- a/templates/form-label.php
+++ b/templates/form-label.php
@@ -7,8 +7,8 @@
 ?>
 <th class="titledesc" scope="row">
 	<label for="<?php echo esc_attr( $field->get_id() ); ?>"><?php echo esc_html( $field->get_label() ); ?>
-		<?php if ( $field->has_description_tip() ): ?>
-			<?php echo wc_help_tip($field->get_description_tip()); ?>
+		<?php if ( $field->has_description_tip() ) : ?>
+			<?php echo wc_help_tip( $field->get_description_tip() ); ?>
 		<?php endif ?>
 	</label>
 </th>
diff --git a/templates/form-start.php b/templates/form-start.php
index 10d7686..e3d4bbe 100644
--- a/templates/form-start.php
+++ b/templates/form-start.php
@@ -3,7 +3,7 @@
  * @var \WPDesk\Forms\Form\FormWithFields $form
  */
 ?>
-<form class="wrap woocommerce" method="<?php echo esc_attr($form->get_method()); ?>" action="<?php echo esc_attr($form->get_action()); ?>">
+<form class="wrap woocommerce" method="<?php echo esc_attr( $form->get_method() ); ?>" action="<?php echo esc_attr( $form->get_action() ); ?>">
 	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js ?>
 
 	<table class="form-table">
diff --git a/templates/header.php b/templates/header.php
index 48b0f11..276c103 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -10,10 +10,10 @@ $classes     = $field->has_classes() ? 'class="' . $field->get_classes() . '"' :
 
 ?>
 
-<?php if ( $field->has_label() ): ?>
+<?php if ( $field->has_label() ) : ?>
 	<h<?php echo $header_size; ?> <?php echo $classes; ?>><?php echo esc_html( $field->get_label() ); ?></h<?php echo $header_size; ?>>
 <?php endif; ?>
 
-<?php if ( $field->has_description() ): ?>
+<?php if ( $field->has_description() ) : ?>
 	<p <?php echo $classes; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 <?php endif; ?>
diff --git a/templates/input-checkbox.php b/templates/input-checkbox.php
index 61dc39f..d69ecec 100644
--- a/templates/input-checkbox.php
+++ b/templates/input-checkbox.php
@@ -6,13 +6,17 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
+
 ?>
 
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-date-picker.php b/templates/input-date-picker.php
index 7dea702..0c5b70c 100644
--- a/templates/input-date-picker.php
+++ b/templates/input-date-picker.php
@@ -7,6 +7,13 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
-echo $renderer->render('input', ['field' => $field, 'renderer' => $renderer, 'name_prefix' => $name_prefix, 'value' => $value]);
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-hidden.php b/templates/input-hidden.php
index 3effbd2..300944e 100644
--- a/templates/input-hidden.php
+++ b/templates/input-hidden.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-image.php b/templates/input-image.php
index 18fba1b..8141b2f 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -8,22 +8,30 @@
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
 <div class="media-input-wrapper" id="<?php echo $media_container_id; ?>">
-    <input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
-           name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
-           id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
-    <div class="custom-img-container">
+	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
+		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
+	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
-            <img src="<?php echo $value ?>" alt="" width="100"/>
+			<img src="<?php echo $value; ?>" alt="" width="100"/>
 		<?php endif; ?>
-    </div>
-    <p class="hide-if-no-js">
-        <a class="upload-custom-img <?php if ( $value ): ?>hidden<?php endif ?>" href="<?php echo $value ?>">
-			<?php _e( 'Set image', 'wp-forms' ) ?>
-        </a>
-        <a class="delete-custom-img <?php if ( ! $value ): ?>hidden<?php endif ?>" href="#">
-			<?php _e( 'Remove image', 'wp-forms' ) ?>
-        </a>
-    </p>
+	</div>
+	<p class="hide-if-no-js">
+		<a class="upload-custom-img 
+		<?php
+		if ( $value ) :
+			?>
+			hidden<?php endif ?>" href="<?php echo $value; ?>">
+			<?php _e( 'Set image', 'wp-forms' ); ?>
+		</a>
+		<a class="delete-custom-img 
+		<?php
+		if ( ! $value ) :
+			?>
+			hidden<?php endif ?>" href="#">
+			<?php _e( 'Remove image', 'wp-forms' ); ?>
+		</a>
+	</p>
 </div>
 <script>
 	jQuery( function ( $ ) {
diff --git a/templates/input-number.php b/templates/input-number.php
index 7dea702..0c5b70c 100644
--- a/templates/input-number.php
+++ b/templates/input-number.php
@@ -7,6 +7,13 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
-echo $renderer->render('input', ['field' => $field, 'renderer' => $renderer, 'name_prefix' => $name_prefix, 'value' => $value]);
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-radio.php b/templates/input-radio.php
index 3effbd2..300944e 100644
--- a/templates/input-radio.php
+++ b/templates/input-radio.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-submit.php b/templates/input-submit.php
index 5f67645..5c11fc8 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -6,7 +6,6 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 
@@ -14,17 +13,29 @@
 	<td style="padding-left:0;">
 		<p class="submit">
 			<input
-				<?php if ( $field->has_classes() ): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-				<?php foreach ( $field->get_attributes( [] ) as $key => $value ): ?>
-					<?php echo $key ?>="<?php echo esc_attr( $value ); ?>"
+				<?php
+				if ( $field->has_classes() ) :
+					?>
+					class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+				<?php foreach ( $field->get_attributes( [] ) as $key => $value ) : ?>
+					<?php echo $key; ?>="<?php echo esc_attr( $value ); ?>"
 				<?php endforeach; ?>
 				type="<?php echo esc_attr( $field->get_type() ); ?>"
 				name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
 				id="<?php echo esc_attr( $field->get_id() ); ?>"
 				value="<?php echo esc_html( $field->get_label() ); ?>"
-				<?php if ( $field->is_required() ): ?>required="required"<?php endif; ?>
-				<?php if ( $field->is_disabled() ): ?>disabled="disabled"<?php endif; ?>
-				<?php if ( $field->is_readonly() ): ?>readonly="readonly"<?php endif; ?>
+				<?php
+				if ( $field->is_required() ) :
+					?>
+					required="required"<?php endif; ?>
+				<?php
+				if ( $field->is_disabled() ) :
+					?>
+					disabled="disabled"<?php endif; ?>
+				<?php
+				if ( $field->is_readonly() ) :
+					?>
+					readonly="readonly"<?php endif; ?>
 			/>
 		</p>
 	</td>
diff --git a/templates/input-text-multiple.php b/templates/input-text-multiple.php
index 7d3fff8..f278729 100644
--- a/templates/input-text-multiple.php
+++ b/templates/input-text-multiple.php
@@ -6,49 +6,62 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 <?php
-if( empty( $value ) || is_string( $value ) ) {
+if ( empty( $value ) || is_string( $value ) ) {
 	$input_values[] = '';
 } else {
 	$input_values = $value;
 }
 ?>
 <div class="clone-element-container">
-<?php foreach( $input_values as $text_value ): ?>
-<?php if (!\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-	<input type="hidden" name="<?php echo $name_prefix.'['.$field->get_name().']'; ?>" value="no"/>
+<?php foreach ( $input_values as $text_value ) : ?>
+	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
 <?php endif; ?>
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?><label><?php endif; ?>
+	<?php
+	if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
+		?>
+		<label><?php endif; ?>
 	<div class="clone-wrapper">
 	<input
-		type="<?php echo \esc_attr($field->get_type()); ?>"
-		name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).'][]'; ?>"
-		id="<?php echo \esc_attr($field->get_id()); ?>"
+		type="<?php echo \esc_attr( $field->get_type() ); ?>"
+		name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . '][]'; ?>"
+		id="<?php echo \esc_attr( $field->get_id() ); ?>"
 
-		<?php if ($field->has_classes()): ?>
-			class="<?php echo \esc_attr($field->get_classes()); ?>"
+		<?php if ( $field->has_classes() ) : ?>
+			class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 		<?php endif; ?>
 
-		<?php if ($field->get_type() === 'text' && $field->has_placeholder()):?>
-			placeholder="<?php echo \esc_html($field->get_placeholder());?>"
+		<?php if ( $field->get_type() === 'text' && $field->has_placeholder() ) : ?>
+			placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"
 		<?php endif; ?>
 
-		<?php foreach ($field->get_attributes() as $key => $atr_val):
-			echo $key.'="'.\esc_attr($atr_val).'"'; ?>
+		<?php
+		foreach ( $field->get_attributes() as $key => $atr_val ) :
+			echo $key . '="' . \esc_attr( $atr_val ) . '"';
+			?>
 		<?php endforeach; ?>
 
-		<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-		<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-		<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-		<?php if (\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-			value="<?php echo \esc_html($text_value); ?>"
-		<?php else: ?>
+		<?php
+		if ( $field->is_required() ) :
+			?>
+			required="required"<?php endif; ?>
+		<?php
+		if ( $field->is_disabled() ) :
+			?>
+			disabled="disabled"<?php endif; ?>
+		<?php
+		if ( $field->is_readonly() ) :
+			?>
+			readonly="readonly"<?php endif; ?>
+		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+			value="<?php echo \esc_html( $text_value ); ?>"
+		<?php else : ?>
 			value="yes"
-			<?php if ($value === 'yes'): ?>
+			<?php if ( $value === 'yes' ) : ?>
 				checked="checked"
 			<?php endif; ?>
 		<?php endif; ?>
@@ -57,25 +70,25 @@ if( empty( $value ) || is_string( $value ) ) {
 		<span class="remove-field hidden"><span class="dashicons dashicons-remove"></span></span>
 	</div>
 
-	<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?>
-	<?php echo \esc_html($field->get_sublabel()); ?></label>
+	<?php if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) : ?>
+		<?php echo \esc_html( $field->get_sublabel() ); ?></label>
 <?php endif; ?>
 <?php endforeach; ?>
 </div>
 <style>
-    .clone-element-container .clone-wrapper .add-field {
-        display: none;
-    }
-    .clone-element-container .clone-wrapper:first-child .add-field {
-        display: inline-block;
-    }
+	.clone-element-container .clone-wrapper .add-field {
+		display: none;
+	}
+	.clone-element-container .clone-wrapper:first-child .add-field {
+		display: inline-block;
+	}
 
-    .clone-element-container .clone-wrapper .remove-field {
-        display: inline-block;
-    }
-    .clone-element-container .clone-wrapper:first-child .remove-field {
-        display: none;
-    }
+	.clone-element-container .clone-wrapper .remove-field {
+		display: inline-block;
+	}
+	.clone-element-container .clone-wrapper:first-child .remove-field {
+		display: none;
+	}
 </style>
 <script>
 	jQuery( function ( $ ) {
diff --git a/templates/input-text.php b/templates/input-text.php
index 3effbd2..300944e 100644
--- a/templates/input-text.php
+++ b/templates/input-text.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input.php b/templates/input.php
index b02e5ea..83448ea 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -7,42 +7,56 @@
  */
 ?>
 
-<?php if (!\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-	<input type="hidden" name="<?php echo $name_prefix.'['.$field->get_name().']'; ?>" value="no"/>
+<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
 <?php endif; ?>
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?><label><?php endif; ?>
+<?php
+if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
+	?>
+	<label><?php endif; ?>
 
 <input
-	type="<?php echo \esc_attr($field->get_type()); ?>"
-	name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).']'; ?>"
-	id="<?php echo \esc_attr($field->get_id()); ?>"
+	type="<?php echo \esc_attr( $field->get_type() ); ?>"
+	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 
-	<?php if ($field->has_classes()): ?>
-		class="<?php echo \esc_attr($field->get_classes()); ?>"
+	<?php if ( $field->has_classes() ) : ?>
+		class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 	<?php endif; ?>
 
-	<?php if ($field->get_type() === 'text' && $field->has_placeholder()):?>
-		placeholder="<?php echo \esc_html($field->get_placeholder());?>"
+	<?php if ( $field->get_type() === 'text' && $field->has_placeholder() ) : ?>
+		placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"
 	<?php endif; ?>
 
-	<?php foreach ($field->get_attributes() as $key => $atr_val):
-        echo $key.'="'.\esc_attr($atr_val).'"'; ?>
+	<?php
+	foreach ( $field->get_attributes() as $key => $atr_val ) :
+		echo $key . '="' . \esc_attr( $atr_val ) . '"';
+		?>
 	<?php endforeach; ?>
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-	<?php if (\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-		value="<?php echo \esc_html($value); ?>"
-	<?php else: ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+		value="<?php echo \esc_html( $value ); ?>"
+	<?php else : ?>
 		value="yes"
-		<?php if ($value === 'yes'): ?>
+		<?php if ( $value === 'yes' ) : ?>
 			checked="checked"
 		<?php endif; ?>
 	<?php endif; ?>
 />
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?>
-	<?php echo \esc_html($field->get_sublabel()); ?></label>
+<?php if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) : ?>
+	<?php echo \esc_html( $field->get_sublabel() ); ?></label>
 <?php endif; ?>
diff --git a/templates/noonce.php b/templates/noonce.php
index 0cd58a5..edc9522 100644
--- a/templates/noonce.php
+++ b/templates/noonce.php
@@ -1,8 +1,8 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string $value
  */
-\wp_nonce_field($field->get_meta_value('action'), $name_prefix .'['. $field->get_name().']');
+
+\wp_nonce_field( $field->get_meta_value( 'action' ), $name_prefix . '[' . $field->get_name() . ']' );
diff --git a/templates/paragraph.php b/templates/paragraph.php
index 184e394..9d29015 100644
--- a/templates/paragraph.php
+++ b/templates/paragraph.php
@@ -6,10 +6,14 @@
  */
 ?>
 
-<?php if ( $field->has_description() ): ?>
+<?php if ( $field->has_description() ) : ?>
 	<tr>
 		<td style="padding-left:0;" colspan="2">
-			<p <?php if ( $field->has_classes() ): ?>class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+			<p 
+			<?php
+			if ( $field->has_classes() ) :
+				?>
+				class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		</td>
 	</tr>
 <?php endif; ?>
diff --git a/templates/product-select.php b/templates/product-select.php
index 3efbbaf..bf545ba 100644
--- a/templates/product-select.php
+++ b/templates/product-select.php
@@ -1,23 +1,26 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string[] $value
  */
+
 ?>
 
 <select class="wc-product-search" multiple="multiple" style="width: 50%;"
-        id="<?php echo esc_attr( $field->get_id() ); ?>"
-        name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
-        data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
-        data-action="woocommerce_json_search_products_and_variations">
+		id="<?php echo esc_attr( $field->get_id() ); ?>"
+		name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
+		data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
+		data-action="woocommerce_json_search_products_and_variations">
 	<?php
 	foreach ( (array) $value as $product_id ) {
 		$product = wc_get_product( $product_id );
 		if ( is_object( $product ) ) {
-			echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true,
-					false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
+			echo '<option value="' . esc_attr( $product_id ) . '"' . selected(
+				true,
+				true,
+				false
+			) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
 		}
 	}
 	?>
diff --git a/templates/select.php b/templates/select.php
index 0c53396..e437efc 100644
--- a/templates/select.php
+++ b/templates/select.php
@@ -7,22 +7,43 @@
 ?>
 <select
 	id="<?php echo esc_attr( $field->get_id() ); ?>"
-	<?php if ($field->has_classes()): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple()? '[]' : ''; ?>"
-	<?php foreach ($field->get_attributes() as $key => $attr_val): ?>
-		<?php echo esc_attr($key); ?>="<?php echo esc_attr($attr_val); ?>"
+	<?php
+	if ( $field->has_classes() ) :
+		?>
+		class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple() ? '[]' : ''; ?>"
+	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
+		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-	<?php if ($field->is_multiple()): ?>multiple="multiple"<?php endif; ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_multiple() ) :
+		?>
+		multiple="multiple"<?php endif; ?>
 >
-	<?php if ( $field->has_placeholder() ): ?><option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
+	<?php
+	if ( $field->has_placeholder() ) :
+		?>
+		<option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
 
-	<?php foreach ( $field->get_possible_values() as $possible_value => $label ): ?>
+	<?php foreach ( $field->get_possible_values() as $possible_value => $label ) : ?>
 		<option
-			<?php if ( $possible_value === $value || (is_array($value) && in_array($possible_value, $value)) || (is_numeric($possible_value) && is_numeric($value) && (int) $possible_value === (int) $value )): ?>selected="selected"<?php endif; ?>
+			<?php
+			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
+				?>
+				selected="selected"<?php endif; ?>
 			value="<?php echo esc_attr( $possible_value ); ?>"
 		><?php echo esc_html( $label ); ?></option>
 	<?php endforeach; ?>
diff --git a/templates/textarea.php b/templates/textarea.php
index cf2f2a7..4d140fa 100644
--- a/templates/textarea.php
+++ b/templates/textarea.php
@@ -7,17 +7,35 @@
 ?>
 
 <textarea
-    id="<?php echo esc_attr( $field->get_id() ); ?>"
-		<?php if ( $field->has_classes() ): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	id="<?php echo esc_attr( $field->get_id() ); ?>"
+		<?php
+		if ( $field->has_classes() ) :
+			?>
+			class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
 	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
-    <?php foreach ( $field->get_attributes() as $key => $attr_val ): ?>
-    <?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
-    <?php endforeach; ?>
+	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
+		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+	<?php endforeach; ?>
 
-    <?php if ( $field->is_required() ): ?>required="required"<?php endif; ?>
-    <?php if ( $field->is_disabled() ): ?>disabled="disabled"<?php endif; ?>
-    <?php if ( $field->is_readonly() ): ?>readonly="readonly"<?php endif; ?>
-    <?php if ( $field->is_multiple() ): ?>multiple="multiple"<?php endif; ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_multiple() ) :
+		?>
+		multiple="multiple"<?php endif; ?>
 
-    <?php if ( $field->has_placeholder() ): ?>placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
+	<?php
+	if ( $field->has_placeholder() ) :
+		?>
+		placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
 ><?php echo esc_html( $value ); ?></textarea>
diff --git a/templates/wyswig.php b/templates/wyswig.php
index fd1ea9d..6bf06d3 100644
--- a/templates/wyswig.php
+++ b/templates/wyswig.php
@@ -13,14 +13,14 @@
 
 <?php
 $id              = uniqid( 'wyswig_' );
-$editor_settings = array(
-	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']'
-);
+$editor_settings = [
+	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']',
+];
 
 wp_editor( wp_kses_post( $value ), $id, $editor_settings );
 ?>
 <script type="text/javascript">
 	(function () {
-		ShopMagic.wyswig.init('<?php echo $id; ?>');
+		ShopMagic.wyswig.init('<?php echo esc_attr( $id ); ?>');
 	}());
 </script>
diff --git a/tests/unit/TestForm.php b/tests/unit/TestForm.php
deleted file mode 100644
index a0702cf..0000000
--- a/tests/unit/TestForm.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Tests;
-
-use WPDesk\Forms\Form\AbstractForm;
-
-class TestForm extends \PHPUnit\Framework\TestCase
-{
-
-	const FORM1_ID                = 'test_form';
-	const FORM1_FORM_DATA         = [ 'test' => true ];
-	const FORM1_UPDATED_FORM_DATA = [ 'test666' => true ];
-
-	private $form;
-
-	protected function setUp(){
-		// Create a new instance from the Abstract Class
-		$this->form = $this->getMockBuilder( AbstractForm::class )
-		                   ->enableOriginalConstructor()
-		                   ->setMethods(['get_form_id'])
-		                   ->getMockForAbstractClass();
-		$this->form->method( 'get_form_id' )->willReturn( self::FORM1_ID );
-		$this->form->method( 'create_form_data' )->willReturn( self::FORM1_FORM_DATA );
-	}
-
-	protected function getForm(){
-		return clone $this->form;
-	}
-
-    /**
-     * Test getting form id.
-     */
-    public function testFormId()
-    {
-    	$form = $this->getForm();
-	    $this->assertEquals(self::FORM1_ID, $form->get_form_id());
-    }
-
-	/**
-	 * Test getting form data.
-	 */
-	public function testFormData()
-	{
-		$form = $this->getForm();
-		$this->assertSame( self::FORM1_FORM_DATA, $form->get_form_data());
-	}
-
-	/**
-	 * Test updated form data.
-	 */
-	public function testUpdatedFormData()
-	{
-		$form = $this->getForm();
-
-		$form->update_form_data( self::FORM1_UPDATED_FORM_DATA );
-		$this->assertSame( array_merge( self::FORM1_FORM_DATA, self::FORM1_UPDATED_FORM_DATA ), $form->get_form_data());
-	}
-}
\ No newline at end of file
diff --git a/tests/unit/TestFormCollection.php b/tests/unit/TestFormCollection.php
deleted file mode 100644
index 67bd0ae..0000000
--- a/tests/unit/TestFormCollection.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-
-namespace Tests;
-
-use WPDesk\Forms\Form\AbstractForm;
-use WPDesk\Forms\Form\FormsCollection;
-
-class TestFormCollection extends \PHPUnit\Framework\TestCase {
-
-	const FORM1_ID = 'test_form';
-	const FORM2_ID = 'test_form2';
-
-	const FORM1_FORM_DATA = [ 'test' => true ];
-	const FORM2_FORM_DATA = [ 'test2' => 'potato' ];
-
-	const FORM1_PREFIXED_FORM_DATA = [ 'test_form_test' => true ];
-	const FORM1_UPDATED_FORM_DATA  = [ 'test666' => true ];
-
-
-	private $formConditionalTrue;
-	private $formConditionalFalse;
-
-	protected function setUp() {
-		$this->formConditionalTrue = $this->getMockBuilder( AbstractForm::class )
-		                                  ->enableOriginalConstructor()
-		                                  ->setMethods( [ 'get_form_id', 'is_active' ] )
-		                                  ->getMockForAbstractClass();
-		$this->formConditionalTrue->method( 'get_form_id' )->willReturn( self::FORM1_ID );
-		$this->formConditionalTrue->method( 'is_active' )->willReturn( true );
-		$this->formConditionalTrue->method( 'create_form_data' )->willReturn( self::FORM1_FORM_DATA );
-
-		$this->formConditionalFalse = $this->getMockBuilder( AbstractForm::class )
-		                                   ->enableOriginalConstructor()
-		                                   ->setMethods( [ 'get_form_id', 'is_active' ] )
-		                                   ->getMockForAbstractClass();
-		$this->formConditionalFalse->method( 'get_form_id' )->willReturn( self::FORM2_ID );
-		$this->formConditionalFalse->method( 'is_active' )->willReturn( false );
-		$this->formConditionalFalse->method( 'create_form_data' )->willReturn( self::FORM2_FORM_DATA );
-	}
-
-	protected function getFormConditionalTrue() {
-		return clone $this->formConditionalTrue;
-	}
-
-	protected function getFormConditionalFalse() {
-		return clone $this->formConditionalFalse;
-	}
-
-	/**
-	 * Test adding and checking single form.
-	 */
-	public function testIfFormExists() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->assertTrue( $collection->is_form_exists( self::FORM1_ID ) );
-	}
-
-	/**
-	 * Test adding and checking multiple forms.
-	 */
-	public function testIfFormsExists() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertTrue( $collection->is_form_exists( self::FORM1_ID ) );
-		$this->assertTrue( $collection->is_form_exists( self::FORM2_ID ) );
-	}
-
-	/**
-	 * Test getting single form. AbstractForm object is expected
-	 */
-	public function testGettingExistingForm() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->assertInstanceOf(
-			AbstractForm::class,
-			$collection->get_form( self::FORM1_ID )
-		);
-	}
-
-	/**
-	 * Test getting not existing single form.
-	 */
-	public function testGettingNotExistingForm() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->expectException( \OutOfRangeException::class );
-		$collection->get_form( '123456' );
-	}
-
-	/**
-	 * Test returned data.
-	 */
-	public function testReturnedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertSame( self::FORM1_FORM_DATA, $collection->get_forms_data() );
-	}
-
-	/**
-	 * Test returned prefixed data.
-	 */
-	public function testReturnedPrefixedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertSame( self::FORM1_PREFIXED_FORM_DATA, $collection->get_forms_data( true ) );
-
-
-	}
-
-	/**
-	 * Test returned updated data.
-	 */
-	public function testReturnedUpdatedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$form = $collection->get_form( self::FORM1_ID );
-		$form->update_form_data( self::FORM1_UPDATED_FORM_DATA );
-		$this->assertSame( array_merge( self::FORM1_FORM_DATA, self::FORM1_UPDATED_FORM_DATA ), $collection->get_forms_data() );
-
-	}
-
-}
\ No newline at end of file
-- 
GitLab


From d6db58625a457710c01bc778d4cc86fcb18bd7e1 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Mon, 6 Sep 2021 16:19:09 +0200
Subject: [PATCH 04/39] feat: add email input field

---
 src/Field/InputEmailField.php    | 22 ++++++++++++++++++++++
 src/Sanitizer/EmailSanitizer.php | 12 ++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 src/Field/InputEmailField.php
 create mode 100644 src/Sanitizer/EmailSanitizer.php

diff --git a/src/Field/InputEmailField.php b/src/Field/InputEmailField.php
new file mode 100644
index 0000000..ee18412
--- /dev/null
+++ b/src/Field/InputEmailField.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace WPDesk\Forms\Field;
+
+use WPDesk\Forms\Sanitizer;
+use WPDesk\Forms\Sanitizer\EmailSanitizer;
+
+class InputEmailField extends BasicField {
+	public function __construct() {
+		parent::__construct();
+		$this->set_default_value( '' );
+		$this->set_attribute( 'type', 'email' );
+	}
+
+	public function get_sanitizer(): Sanitizer {
+		return new EmailSanitizer();
+	}
+
+	public function get_template_name(): string {
+		return 'input-text';
+	}
+}
diff --git a/src/Sanitizer/EmailSanitizer.php b/src/Sanitizer/EmailSanitizer.php
new file mode 100644
index 0000000..1a51a78
--- /dev/null
+++ b/src/Sanitizer/EmailSanitizer.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace WPDesk\Forms\Sanitizer;
+
+use WPDesk\Forms\Sanitizer;
+
+class EmailSanitizer implements Sanitizer {
+	public function sanitize( $value ): string {
+		return sanitize_email( $value );
+	}
+
+}
-- 
GitLab


From fb4e5c476782cb60cc0f78cfbf42ae76848cfd9b Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Tue, 7 Sep 2021 20:48:51 +0200
Subject: [PATCH 05/39] fix: add missing strong types in signatures

---
 README.md                               | 80 +++++++------------------
 changelog.txt                           |  5 +-
 src/Field.php                           |  8 +--
 src/Field/Traits/HtmlAttributes.php     |  8 +--
 src/Renderer/JsonNormalizedRenderer.php |  2 +-
 tests/docker-compose.yaml               |  2 +-
 6 files changed, 30 insertions(+), 75 deletions(-)

diff --git a/README.md b/README.md
index 06702bf..519d15f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-[![pipeline status](https://gitlab.com/wpdesk/wp-forms/badges/master/pipeline.svg)](https://gitlab.com/wpdesk/wp-forms/pipelines) 
-[![coverage report](https://gitlab.com/wpdesk/wp-forms/badges/master/coverage.svg)](https://gitlab.com/wpdesk/wp-forms/commits/master) 
-[![Latest Stable Version](https://poser.pugx.org/wpdesk/wp-forms/v/stable)](https://packagist.org/packages/wpdesk/wp-forms) 
-[![Total Downloads](https://poser.pugx.org/wpdesk/wp-forms/downloads)](https://packagist.org/packages/wpdesk/wp-forms) 
-[![Latest Unstable Version](https://poser.pugx.org/wpdesk/wp-forms/v/unstable)](https://packagist.org/packages/wpdesk/wp-forms) 
+[![pipeline status](https://gitlab.com/wpdesk/wp-forms/badges/master/pipeline.svg)](https://gitlab.com/wpdesk/wp-forms/pipelines)
+[![coverage report](https://gitlab.com/wpdesk/wp-forms/badges/master/coverage.svg)](https://gitlab.com/wpdesk/wp-forms/commits/master)
+[![Latest Stable Version](https://poser.pugx.org/wpdesk/wp-forms/v/stable)](https://packagist.org/packages/wpdesk/wp-forms)
+[![Total Downloads](https://poser.pugx.org/wpdesk/wp-forms/downloads)](https://packagist.org/packages/wpdesk/wp-forms)
+[![Latest Unstable Version](https://poser.pugx.org/wpdesk/wp-forms/v/unstable)](https://packagist.org/packages/wpdesk/wp-forms)
 [![License](https://poser.pugx.org/wpdesk/wp-forms/license)](https://packagist.org/packages/wpdesk/wp-forms)
 
 WordPress Library for Form integration
@@ -11,7 +11,7 @@ WordPress Library for Form integration
 
 ## Requirements
 
-PHP 5.6 or later.
+PHP 7.0 or later.
 
 ## Composer
 
@@ -34,26 +34,18 @@ Let's say we have an abstraction for settings tabs:
 interface SettingsTab {
 	/**
 	 * Slug name used for unique url and settings in db.
-	 *
-	 * @return string
 	 */
-	public static function get_tab_slug();
+	public static function get_tab_slug(): string;
 
 	/**
 	 * Tab name to show on settings page.
-	 *
-	 * @return string
 	 */
-	public function get_tab_name();
+	public function get_tab_name(): string;
 
 	/**
 	 * Render tab content and return it as string.
-	 *
-	 * @param Renderer $renderer
-	 *
-	 * @return string
 	 */
-	public function render( Renderer $renderer );
+	public function render( Renderer $renderer ): string;
 
 	/**
 	 * Use to set settings from database or defaults.
@@ -74,14 +66,14 @@ interface SettingsTab {
 	 *
 	 * @return void
 	 */
-	public function handle_request( $request );
+	public function handle_request( array $request );
 
 	/**
 	 * Returns valid data from Tab. Can be used after ::handle_request or ::set_data.
 	 *
 	 * @return array
 	 */
-	public function get_data();
+	public function get_data(): array;
 }
 ```
 
@@ -95,12 +87,9 @@ abstract class FieldSettingsTab implements SettingsTab {
 	/**
 	 * @return Field[]
 	 */
-	abstract protected function get_fields();
+	abstract protected function get_fields(): array;
 
-	/**
-	 * @return FormWithFields
-	 */
-	protected function get_form() {
+	protected function get_form(): FormWithFields {
 		if ( $this->form === null ) {
 			$fields     = $this->get_fields();
 			$this->form = new FormWithFields( $fields, static::get_tab_slug() );
@@ -109,7 +98,7 @@ abstract class FieldSettingsTab implements SettingsTab {
 		return $this->form;
 	}
 
-	public function render( Renderer $renderer) {
+	public function render( Renderer $renderer ) {
 		return $this->get_form()->render_form( $renderer );
 	}
 
@@ -121,7 +110,7 @@ abstract class FieldSettingsTab implements SettingsTab {
 		$this->get_form()->handle_request( $request );
 	}
 
-	public function get_data() {
+	public function get_data(): array {
 		return $this->get_form()->get_data();
 	}
 }
@@ -131,10 +120,7 @@ Then we can create a settings tab that looks like that:
 
 ```php
 final class GeneralSettings extends FieldSettingsTab {
-	/**
-	 * @inheritDoc
-	 */
-	protected function get_fields() {
+	protected function get_fields(): array {
 		return [
 			( new CheckboxField() )
 				->set_label( __( 'Subscribe on checkout', 'some-text-domain' ) )
@@ -166,23 +152,17 @@ final class GeneralSettings extends FieldSettingsTab {
 		];
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public static function get_tab_slug() {
 		return 'general';
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public function get_tab_name() {
 		return __( 'General', 'text-domain' );
 	}
 }
 ```
 
-Then class like that provides form load/save/render support for these abstraction can look like this:
+Then class like that provides form load/save/render support for this abstraction can look like this:
 
 ```php
 /**
@@ -212,8 +192,6 @@ final class Settings {
 	}
 
 	/**
-	 * Render
-	 *
 	 * @return void
 	 */
 	public function render_page_action() {
@@ -228,10 +206,7 @@ final class Settings {
 		echo $renderer->render( 'footer' );
 	}
 
-	/**
-	 * @return SettingsTab
-	 */
-	private function get_active_tab() {
+	private function get_active_tab(): SettingTab {
 		$selected_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : null;
 		$tabs         = $this->get_settings_tabs();
 		if ( ! empty( $selected_tab ) && isset( $tabs[ $selected_tab ] ) ) {
@@ -244,7 +219,7 @@ final class Settings {
 	/**
 	 * @return SettingsTab[]
 	 */
-	private function get_settings_tabs() {
+	private function get_settings_tabs(): array {
 		static $tabs = [];
 		if ( empty( $tabs ) ) {
 			$tabs = [
@@ -263,15 +238,12 @@ final class Settings {
 	 *
 	 * @return PersistentContainer
 	 */
-	public static function get_settings_persistence( $tab_slug ) {
+	public static function get_settings_persistence( string $tab_slug ): PersistentContainer {
 		return new WordpressOptionsContainer( 'some-settings-' . $tab_slug );
 	}
 
 	/**
 	 * Save data from tab to persistent container.
-	 *
-	 * @param SettingsTab $tab
-	 * @param PersistentContainer $container
 	 */
 	private function save_tab_data( SettingsTab $tab, PersistentContainer $container ) {
 		$tab_data = $tab->get_data();
@@ -282,17 +254,14 @@ final class Settings {
 		} );
 	}
 
-	/**
-	 * @return \WPDesk\View\Renderer\Renderer
-	 */
-	private function get_renderer() {
+	private function get_renderer(): \WPDesk\View\Renderer\Renderer {
 		return new SimplePhpRenderer( new DefaultFormFieldResolver() );
 	}
 
 	/**
 	 * @return string[]
 	 */
-	private function get_tabs_menu_items() {
+	private function get_tabs_menu_items(): array {
 		$menu_items = [];
 
 		foreach ( $this->get_settings_tabs() as $tab ) {
@@ -303,8 +272,3 @@ final class Settings {
 	}
 }
 ```
-
-
-## Project documentation
-
-PHPDoc: https://wpdesk.gitlab.io/wp-forms/index.html  
\ No newline at end of file
diff --git a/changelog.txt b/changelog.txt
index e6b1ae0..10aef4c 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,8 +1,11 @@
 # Changelog
 
-## [2.5.0] - 2021-09-03
+## [3.0.0] - 2021-09-08
 ### Added
+- Added strong typing to all of the interfaces
 - Added fields sorting by priority field
+###
+- Removed deprecated classes
 
 ## [2.4.6] - 2021-08-23
 ### Fixed
diff --git a/src/Field.php b/src/Field.php
index 2a6569e..22cf8d7 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -54,13 +54,7 @@ interface Field {
 	 */
 	public function get_attributes( array $except = [] ): array;
 
-	/**
-	 * @param string  $name
-	 * @param ?string $default
-	 *
-	 * @return string
-	 */
-	public function get_attribute( string $name, $default = null ): string;
+	public function get_attribute( string $name, string $default = null ): string;
 
 	public function is_attribute_set( string $name ): bool;
 
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 4e54c85..b4ee084 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -45,13 +45,7 @@ trait HtmlAttributes {
 		return isset( $this->attributes[ $name ] );
 	}
 
-	/**
-	 * @param string  $name
-	 * @param ?string $default
-	 *
-	 * @return string
-	 */
-	public function get_attribute( string $name, $default = null ): string {
+	public function get_attribute( string $name, string $default = null ): string {
 		return $this->attributes[ $name ] ?? $default;
 	}
 }
diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 371490c..82021cb 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -29,7 +29,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				'readonly' => $field->is_readonly(),
 				'required' => $field->is_required(),
 				'prefix'   => $name_prefix,
-				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
+				'value '   => $fields_data[ $field->get_name() ] ?? $field->get_default_value(),
 			];
 
 			if ( $field->has_classes() ) {
diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml
index 2a86b03..718ce5e 100644
--- a/tests/docker-compose.yaml
+++ b/tests/docker-compose.yaml
@@ -123,7 +123,7 @@ services:
       WORDPRESS_DB_HOST: mysql0
 
   mysql0:
-    image: mysql:5.7
+    image: mariadb:10.3
     environment:
       MYSQL_ROOT_PASSWORD: mysql
       MYSQL_DATABASE: wptest
-- 
GitLab


From 279be6ca23dd78a6ed4313561ae1e8527af61e6e Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 8 Sep 2021 11:31:08 +0200
Subject: [PATCH 06/39] fix: correct returning self signature

---
 src/Field.php                       |  4 ++--
 src/Field/BasicField.php            | 31 ++++++++++++++---------------
 src/Field/CheckboxField.php         |  4 +++-
 src/Field/Header.php                |  4 +++-
 src/Field/SelectField.php           |  6 ++++--
 src/Field/Traits/HtmlAttributes.php | 12 +++++++++--
 6 files changed, 37 insertions(+), 24 deletions(-)

diff --git a/src/Field.php b/src/Field.php
index 22cf8d7..42ea129 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -73,9 +73,9 @@ interface Field {
 	/** @return array<string,int> */
 	public function get_data(): array;
 
-	public function add_data( string $data_name, string $data_value ): self;
+	public function add_data( string $data_name, string $data_value ): Field;
 
-	public function unset_data( string $data_name ): self;
+	public function unset_data( string $data_name ): Field;
 
 	/** @return mixed */
 	public function get_possible_values();
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index ee7f144..842241e 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -3,7 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
-use WPDesk\Forms\Form\FormWithFields;
 use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
@@ -38,7 +37,7 @@ abstract class BasicField implements Field {
 		return $this->meta['label'];
 	}
 
-	public function set_label( string $value ): self {
+	public function set_label( string $value ): Field {
 		$this->meta['label'] = $value;
 
 		return $this;
@@ -68,13 +67,13 @@ abstract class BasicField implements Field {
 		return isset( $this->meta['description'] );
 	}
 
-	public function set_description( string $value ): self {
+	public function set_description( string $value ): Field {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( string $value ): self {
+	public function set_description_tip( string $value ): Field {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
@@ -84,7 +83,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['type'];
 	}
 
-	public function set_placeholder( string $value ): self {
+	public function set_placeholder( string $value ): Field {
 		$this->meta['placeholder'] = $value;
 
 		return $this;
@@ -98,7 +97,7 @@ abstract class BasicField implements Field {
 		return $this->meta['placeholder'];
 	}
 
-	public function set_name( string $name ): self {
+	public function set_name( string $name ): Field {
 		$this->attributes['name'] = $name;
 
 		return $this;
@@ -140,7 +139,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['multiple'] ?? false;
 	}
 
-	public function set_disabled(): self {
+	public function set_disabled(): Field {
 		$this->attributes['disabled'] = true;
 
 		return $this;
@@ -150,7 +149,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['disabled'] ?? false;
 	}
 
-	public function set_readonly(): self {
+	public function set_readonly(): Field {
 		$this->attributes['readonly'] = true;
 
 		return $this;
@@ -160,25 +159,25 @@ abstract class BasicField implements Field {
 		return $this->attributes['readonly'] ?? false;
 	}
 
-	public function set_required(): self {
+	public function set_required(): Field {
 		$this->meta['required'] = true;
 
 		return $this;
 	}
 
-	public function add_class( string $class_name ): self {
+	public function add_class( string $class_name ): Field {
 		$this->meta['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	public function unset_class( string $class_name ): self {
+	public function unset_class( string $class_name ): Field {
 		unset( $this->meta['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	public function add_data( string $data_name, string $data_value ): self {
+	public function add_data( string $data_name, string $data_value ): Field {
 		if ( ! isset( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
@@ -187,7 +186,7 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function unset_data( string $data_name ): self {
+	public function unset_data( string $data_name ): Field {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
@@ -205,7 +204,7 @@ abstract class BasicField implements Field {
 		return $this->default_value;
 	}
 
-	public function set_default_value( string $value ): self {
+	public function set_default_value( string $value ): Field {
 		$this->default_value = $value;
 
 		return $this;
@@ -236,7 +235,7 @@ abstract class BasicField implements Field {
 		return new NoSerialize();
 	}
 
-	public function set_serializer( Serializer $serializer ): self {
+	public function set_serializer( Serializer $serializer ): Field {
 		$this->meta['serializer'] = $serializer;
 
 		return $this;
@@ -251,7 +250,7 @@ abstract class BasicField implements Field {
 	 *
 	 * @see FormWithFields::get_fields()
 	 */
-	public function set_priority( int $priority ): self {
+	public function set_priority( int $priority ): Field {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index e8cc29f..507cda0 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class CheckboxField extends BasicField {
 	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
@@ -19,7 +21,7 @@ class CheckboxField extends BasicField {
 		return $this->meta['sublabel'];
 	}
 
-	public function set_sublabel( string $value ): self {
+	public function set_sublabel( string $value ): Field {
 		$this->meta['sublabel'] = $value;
 
 		return $this;
diff --git a/src/Field/Header.php b/src/Field/Header.php
index fa86700..cebe249 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class Header extends NoValueField {
 	public function __construct() {
 		parent::__construct();
@@ -16,7 +18,7 @@ class Header extends NoValueField {
 		return true;
 	}
 
-	public function set_header_size( int $value ): self {
+	public function set_header_size( int $value ): Field {
 		$this->meta['header_size'] = $value;
 
 		return $this;
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index bead3bb..ee0264c 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class SelectField extends BasicField {
 
 	public function get_template_name(): string {
@@ -9,13 +11,13 @@ class SelectField extends BasicField {
 	}
 
 	/** @param string[] $options */
-	public function set_options( array $options ): self {
+	public function set_options( array $options ): Field {
 		$this->meta['possible_values'] = $options;
 
 		return $this;
 	}
 
-	public function set_multiple(): self {
+	public function set_multiple(): Field {
 		$this->attributes['multiple'] = true;
 
 		return $this;
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index b4ee084..afc1e08 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field\Traits;
 
+use WPDesk\Forms\Field;
+
 /**
  * Implementation of HTML attributes like id, name, action etc.
  *
@@ -29,13 +31,19 @@ trait HtmlAttributes {
 		);
 	}
 
-	public function set_attribute( string $name, string $value ): self {
+	/**
+	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 */
+	public function set_attribute( string $name, string $value ) {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
 	}
 
-	public function unset_attribute( string $name ): self {
+	/**
+	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 */
+	public function unset_attribute( string $name ) {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
-- 
GitLab


From 2dda30becdb7f00ea61d159354a7b94ffbf99eb0 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 8 Sep 2021 13:45:03 +0200
Subject: [PATCH 07/39] fix: correct type issues

---
 src/ContainerForm.php               | 9 ++++++---
 src/Field/BasicField.php            | 6 ++++--
 src/Field/Traits/HtmlAttributes.php | 4 +---
 src/Form.php                        | 4 ++--
 src/Form/FormWithFields.php         | 6 ++++--
 5 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 0510706..1d4cf05 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
 /**
@@ -11,8 +10,12 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 interface ContainerForm {
-	/** @return void */
-	public function set_data( ContainerInterface $data );
+	/**
+	 * @param \Psr\Container\ContainerInterface $data
+	 *
+	 * @return void
+	 */
+	public function set_data( $data );
 
 	/**
 	 * Put data from form into a container.
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 842241e..69e460d 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -200,11 +200,13 @@ abstract class BasicField implements Field {
 		return isset( $this->meta['class'][ $name ] );
 	}
 
-	public function get_default_value(): string {
+	/** @return mixed */
+	public function get_default_value() {
 		return $this->default_value;
 	}
 
-	public function set_default_value( string $value ): Field {
+	/** @param mixed $value */
+	public function set_default_value( $value ): Field {
 		$this->default_value = $value;
 
 		return $this;
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index afc1e08..5ae190a 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms\Field\Traits;
 
-use WPDesk\Forms\Field;
-
 /**
  * Implementation of HTML attributes like id, name, action etc.
  *
@@ -54,6 +52,6 @@ trait HtmlAttributes {
 	}
 
 	public function get_attribute( string $name, string $default = null ): string {
-		return $this->attributes[ $name ] ?? $default;
+		return $this->attributes[ $name ] ?? $default ?? '';
 	}
 }
diff --git a/src/Form.php b/src/Form.php
index 8ea2d78..504ebbe 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -42,7 +42,7 @@ interface Form {
 	 *
 	 * @return void
 	 */
-	public function set_data( array $data );
+	public function set_data( $data );
 
 	/**
 	 * Use to render the form to string.
@@ -69,6 +69,6 @@ interface Form {
 	/**
 	 * Form if you ever need to have more than one form at once.
 	 */
-	public function get_form_id(): int;
+	public function get_form_id(): string;
 }
 
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index 45dc515..ba13928 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -113,7 +113,9 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
-	 * @param array|ContainerInterface $data Data consistent with Form and ContainerForm interface.
+	 * @param array|ContainerInterface $data Data consistent with Form or ContainerForm interface.
+	 *
+	 * @return void
 	 */
 	public function set_data( $data ) {
 		if ( is_array( $data ) ) {
@@ -208,7 +210,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $fields;
 	}
 
-	public function get_form_id(): int {
+	public function get_form_id(): string {
 		return $this->form_id;
 	}
 
-- 
GitLab


From ad2e49a5195719d1ac2667811a39d84bbacf6cc3 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Fri, 10 Sep 2021 02:24:11 +0200
Subject: [PATCH 08/39] fix: remove return type from NoSerialize - it passes
 any value

---
 src/Serializer/NoSerialize.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index 31a09e1..b29e88b 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ): string {
+	public function serialize( $value ) {
 		return $value;
 	}
 
-- 
GitLab


From 85ebe6b4647203068625ccc4825f452bc71fea73 Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Wed, 15 Sep 2021 12:17:59 +0200
Subject: [PATCH 09/39] fix: escaping

---
 templates/header.php      | 4 ++--
 templates/input-image.php | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/templates/header.php b/templates/header.php
index 276c103..5ff3be6 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -5,8 +5,8 @@
  * @var string $value
  */
 
-$header_size = $field->get_meta_value( 'header_size' ) ?: '2';
-$classes     = $field->has_classes() ? 'class="' . $field->get_classes() . '"' : '';
+$header_size = (int) $field->get_meta_value( 'header_size' ) ?: 2;
+$classes     = $field->has_classes() ? 'class="' . esc_attr( $field->get_classes() ) . '"' : '';
 
 ?>
 
diff --git a/templates/input-image.php b/templates/input-image.php
index 8141b2f..ebeffdb 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -7,7 +7,7 @@
 
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
-<div class="media-input-wrapper" id="<?php echo $media_container_id; ?>">
+<div class="media-input-wrapper" id="<?php echo esc_attr( $media_container_id ); ?>">
 	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
 		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
 		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
@@ -17,14 +17,14 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 		<?php endif; ?>
 	</div>
 	<p class="hide-if-no-js">
-		<a class="upload-custom-img 
+		<a class="upload-custom-img
 		<?php
 		if ( $value ) :
 			?>
 			hidden<?php endif ?>" href="<?php echo $value; ?>">
 			<?php _e( 'Set image', 'wp-forms' ); ?>
 		</a>
-		<a class="delete-custom-img 
+		<a class="delete-custom-img
 		<?php
 		if ( ! $value ) :
 			?>
@@ -36,7 +36,7 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 <script>
 	jQuery( function ( $ ) {
 		var frame,
-			metaBox = $( '#<?php echo $media_container_id; ?>' ),
+			metaBox = $( '#<?php echo esc_attr( $media_container_id ); ?>' ),
 			addImgLink = metaBox.find( '.upload-custom-img' ),
 			delImgLink = metaBox.find( '.delete-custom-img' ),
 			imgContainer = metaBox.find( '.custom-img-container' ),
-- 
GitLab


From 7596dd7241dd2f4af51515f6adabf08ca1fd295f Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Wed, 15 Sep 2021 12:54:28 +0200
Subject: [PATCH 10/39] fix: reformat

---
 src/ContainerForm.php    | 3 ++-
 src/Field/BasicField.php | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 1d4cf05..9c7e339 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms;
 
+use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
 /**
@@ -11,7 +12,7 @@ use WPDesk\Persistence\PersistentContainer;
  */
 interface ContainerForm {
 	/**
-	 * @param \Psr\Container\ContainerInterface $data
+	 * @param ContainerInterface $data
 	 *
 	 * @return void
 	 */
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 69e460d..9444933 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -124,7 +124,7 @@ abstract class BasicField implements Field {
 	}
 
 	public function get_possible_values() {
-		return isset( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
+		return $this->meta['possible_values'] ?? [];
 	}
 
 	public function get_id(): string {
-- 
GitLab


From 47c8e032d55db9d809f247c6bd220213a14811a9 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 15 Sep 2021 11:43:14 +0200
Subject: [PATCH 11/39] feat: add escaping functions in templates

---
 phpcs.xml.dist                    |  2 +-
 templates/button.php              |  3 +--
 templates/form-end.php            |  6 ++++++
 templates/form-field.php          | 22 ++++++++++++----------
 templates/form-label.php          |  5 +++--
 templates/form-start.php          |  5 +++--
 templates/header.php              |  4 ++--
 templates/input-checkbox.php      | 19 ++++++++++---------
 templates/input-date-picker.php   | 21 +++++++++++----------
 templates/input-hidden.php        | 20 +++++++++++---------
 templates/input-image.php         | 20 ++++++++++----------
 templates/input-number.php        | 21 +++++++++++----------
 templates/input-radio.php         | 20 +++++++++++---------
 templates/input-submit.php        | 14 +++++++-------
 templates/input-text-multiple.php | 12 +++++-------
 templates/input-text.php          | 22 +++++++++++-----------
 templates/input.php               | 10 ++++------
 templates/paragraph.php           |  7 +++----
 templates/product-select.php      |  8 ++++----
 templates/select.php              | 18 ++++++++++--------
 templates/textarea.php            | 13 +++++++------
 templates/wyswig.php              | 13 +++++++------
 22 files changed, 150 insertions(+), 135 deletions(-)

diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 6ef3f27..1b9bf7a 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -31,7 +31,7 @@
 	-->
 
 	<!-- Define plugin text domain for i18n. -->
-	<config name="text_domain" value="shopmagic-for-woocommerce"/>
+	<config name="text_domain" value="wp-forms"/>
 
 	<!-- This value should be aligned with WordPress support version declared in plugin header -->
 	<config name="minimum_supported_wp_version" value="5.0"/>
diff --git a/templates/button.php b/templates/button.php
index c558c6e..fd95750 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -4,7 +4,6 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
 
@@ -16,7 +15,7 @@
 <?php endif; ?>
 
 <?php foreach ( $field->get_attributes( [] ) as $key => $val ) : ?>
-	<?php echo $key . '="' . \esc_attr( $val ) . '"'; ?>
+	<?php echo \esc_attr( $key ) . '="' . \esc_attr( $val ) . '"'; ?>
 <?php endforeach; ?>
 
 	type="<?php echo \esc_attr( $field->get_type() ); ?>"
diff --git a/templates/form-end.php b/templates/form-end.php
index 7484d6e..f2a22fe 100644
--- a/templates/form-end.php
+++ b/templates/form-end.php
@@ -1,3 +1,9 @@
+<?php
+/**
+ * Form ending with hoverable tip snippet in js.
+ */
+
+?>
 </tbody>
 </table>
 </form>
diff --git a/templates/form-field.php b/templates/form-field.php
index 50f5678..0fd07d5 100644
--- a/templates/form-field.php
+++ b/templates/form-field.php
@@ -4,26 +4,28 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 
 <tr valign="top">
 	<?php if ( $field->has_label() ) : ?>
-		<?php echo $renderer->render( 'form-label', [ 'field' => $field ] ); ?>
+		<?php echo wp_kses_post( $renderer->render( 'form-label', [ 'field' => $field ] ) ); ?>
 	<?php endif; ?>
 
 	<td class="forminp">
 		<?php
-		echo $renderer->render(
-			$template_name,
-			[
-				'field'       => $field,
-				'renderer'    => $renderer,
-				'name_prefix' => $name_prefix,
-				'value'       => $value,
-			]
+		echo wp_kses_post(
+			$renderer->render(
+				$template_name,
+				[
+					'field'       => $field,
+					'renderer'    => $renderer,
+					'name_prefix' => $name_prefix,
+					'value'       => $value,
+				]
+			)
 		);
 		?>
 
diff --git a/templates/form-label.php b/templates/form-label.php
index f6268a5..8eeaf28 100644
--- a/templates/form-label.php
+++ b/templates/form-label.php
@@ -4,11 +4,12 @@
  * @var string $name_prefix
  * @var string $value
  */
+
 ?>
 <th class="titledesc" scope="row">
-	<label for="<?php echo esc_attr( $field->get_id() ); ?>"><?php echo esc_html( $field->get_label() ); ?>
+	<label for="<?php echo \esc_attr( $field->get_id() ); ?>"><?php echo \esc_html( $field->get_label() ); ?>
 		<?php if ( $field->has_description_tip() ) : ?>
-			<?php echo wc_help_tip( $field->get_description_tip() ); ?>
+			<?php echo esc_html( wc_help_tip( $field->get_description_tip() ) ); ?>
 		<?php endif ?>
 	</label>
 </th>
diff --git a/templates/form-start.php b/templates/form-start.php
index e3d4bbe..d311794 100644
--- a/templates/form-start.php
+++ b/templates/form-start.php
@@ -2,9 +2,10 @@
 /**
  * @var \WPDesk\Forms\Form\FormWithFields $form
  */
+
 ?>
-<form class="wrap woocommerce" method="<?php echo esc_attr( $form->get_method() ); ?>" action="<?php echo esc_attr( $form->get_action() ); ?>">
-	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js ?>
+<form class="wrap woocommerce" method="<?php echo \esc_attr( $form->get_method() ); ?>" action="<?php echo \esc_attr( $form->get_action() ); ?>">
+	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js. ?>
 
 	<table class="form-table">
 		<tbody>
diff --git a/templates/header.php b/templates/header.php
index 5ff3be6..e2384ea 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -11,9 +11,9 @@ $classes     = $field->has_classes() ? 'class="' . esc_attr( $field->get_classes
 ?>
 
 <?php if ( $field->has_label() ) : ?>
-	<h<?php echo $header_size; ?> <?php echo $classes; ?>><?php echo esc_html( $field->get_label() ); ?></h<?php echo $header_size; ?>>
+	<h<?php echo \esc_attr( $header_size ); ?> <?php echo \esc_attr( $classes ); ?>><?php echo \esc_html( $field->get_label() ); ?></h<?php echo \esc_attr( $header_size ); ?>>
 <?php endif; ?>
 
 <?php if ( $field->has_description() ) : ?>
-	<p <?php echo $classes; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+	<p <?php echo \esc_attr( $classes ); ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 <?php endif; ?>
diff --git a/templates/input-checkbox.php b/templates/input-checkbox.php
index d69ecec..8474091 100644
--- a/templates/input-checkbox.php
+++ b/templates/input-checkbox.php
@@ -4,19 +4,20 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
 
 ?>
 
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-date-picker.php b/templates/input-date-picker.php
index 0c5b70c..3caa4c6 100644
--- a/templates/input-date-picker.php
+++ b/templates/input-date-picker.php
@@ -1,19 +1,20 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-hidden.php b/templates/input-hidden.php
index 300944e..6388552 100644
--- a/templates/input-hidden.php
+++ b/templates/input-hidden.php
@@ -4,17 +4,19 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-image.php b/templates/input-image.php
index ebeffdb..9b5d635 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -7,13 +7,13 @@
 
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
-<div class="media-input-wrapper" id="<?php echo esc_attr( $media_container_id ); ?>">
+<div class="media-input-wrapper" id="<?php echo \esc_attr( $media_container_id ); ?>">
 	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
-		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
-		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
+			name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+			id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
 	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
-			<img src="<?php echo $value; ?>" alt="" width="100"/>
+			<img src="<?php echo \esc_attr( $value ); ?>" alt="" width="100"/>
 		<?php endif; ?>
 	</div>
 	<p class="hide-if-no-js">
@@ -21,22 +21,22 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 		<?php
 		if ( $value ) :
 			?>
-			hidden<?php endif ?>" href="<?php echo $value; ?>">
-			<?php _e( 'Set image', 'wp-forms' ); ?>
+			hidden<?php endif ?>" href="<?php echo \esc_attr( $value ); ?>">
+			<?php esc_html_e( 'Set image', 'wp-forms' ); ?>
 		</a>
 		<a class="delete-custom-img
 		<?php
 		if ( ! $value ) :
 			?>
 			hidden<?php endif ?>" href="#">
-			<?php _e( 'Remove image', 'wp-forms' ); ?>
+			<?php esc_html_e( 'Remove image', 'wp-forms' ); ?>
 		</a>
 	</p>
 </div>
 <script>
 	jQuery( function ( $ ) {
 		var frame,
-			metaBox = $( '#<?php echo esc_attr( $media_container_id ); ?>' ),
+			metaBox = $( '#<?php echo \esc_attr( $media_container_id ); ?>' ),
 			addImgLink = metaBox.find( '.upload-custom-img' ),
 			delImgLink = metaBox.find( '.delete-custom-img' ),
 			imgContainer = metaBox.find( '.custom-img-container' ),
@@ -50,9 +50,9 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 			}
 
 			frame = wp.media( {
-				title: <?php _e( 'Select or Upload Media', 'wp-forms' ); ?>,
+				title: <?php esc_html_e( 'Select or Upload Media', 'wp-forms' ); ?>,
 				button: {
-					text: <?php _e( 'Use this media', 'wp-forms' ); ?>
+					text: <?php esc_html_e( 'Use this media', 'wp-forms' ); ?>
 				},
 				library: {
 					type: ['image']
diff --git a/templates/input-number.php b/templates/input-number.php
index 0c5b70c..3caa4c6 100644
--- a/templates/input-number.php
+++ b/templates/input-number.php
@@ -1,19 +1,20 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-radio.php b/templates/input-radio.php
index 300944e..6388552 100644
--- a/templates/input-radio.php
+++ b/templates/input-radio.php
@@ -4,17 +4,19 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-submit.php b/templates/input-submit.php
index 5c11fc8..bae3ce3 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -4,9 +4,9 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 
 <tr>
@@ -16,14 +16,14 @@
 				<?php
 				if ( $field->has_classes() ) :
 					?>
-					class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+					class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
 				<?php foreach ( $field->get_attributes( [] ) as $key => $value ) : ?>
-					<?php echo $key; ?>="<?php echo esc_attr( $value ); ?>"
+					<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $value ); ?>"
 				<?php endforeach; ?>
-				type="<?php echo esc_attr( $field->get_type() ); ?>"
-				name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
-				id="<?php echo esc_attr( $field->get_id() ); ?>"
-				value="<?php echo esc_html( $field->get_label() ); ?>"
+				type="<?php echo \esc_attr( $field->get_type() ); ?>"
+				name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
+				id="<?php echo \esc_attr( $field->get_id() ); ?>"
+				value="<?php echo \esc_html( $field->get_label() ); ?>"
 				<?php
 				if ( $field->is_required() ) :
 					?>
diff --git a/templates/input-text-multiple.php b/templates/input-text-multiple.php
index f278729..371013d 100644
--- a/templates/input-text-multiple.php
+++ b/templates/input-text-multiple.php
@@ -4,11 +4,9 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-?>
-<?php
+
 if ( empty( $value ) || is_string( $value ) ) {
 	$input_values[] = '';
 } else {
@@ -17,8 +15,8 @@ if ( empty( $value ) || is_string( $value ) ) {
 ?>
 <div class="clone-element-container">
 <?php foreach ( $input_values as $text_value ) : ?>
-	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
-	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
+	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
+	<input type="hidden" name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>" value="no"/>
 <?php endif; ?>
 
 	<?php
@@ -41,7 +39,7 @@ if ( empty( $value ) || is_string( $value ) ) {
 
 		<?php
 		foreach ( $field->get_attributes() as $key => $atr_val ) :
-			echo $key . '="' . \esc_attr( $atr_val ) . '"';
+			echo \esc_attr( $key ) . '="' . \esc_attr( $atr_val ) . '"';
 			?>
 		<?php endforeach; ?>
 
@@ -57,7 +55,7 @@ if ( empty( $value ) || is_string( $value ) ) {
 		if ( $field->is_readonly() ) :
 			?>
 			readonly="readonly"<?php endif; ?>
-		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 			value="<?php echo \esc_html( $text_value ); ?>"
 		<?php else : ?>
 			value="yes"
diff --git a/templates/input-text.php b/templates/input-text.php
index 300944e..3caa4c6 100644
--- a/templates/input-text.php
+++ b/templates/input-text.php
@@ -4,17 +4,17 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-?>
-<?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input.php b/templates/input.php
index 83448ea..a4844b1 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -1,14 +1,12 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string $value
  */
-?>
 
-<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
-	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
+if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
+	<input type="hidden" name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>" value="no"/>
 <?php endif; ?>
 
 <?php
@@ -31,7 +29,7 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 
 	<?php
 	foreach ( $field->get_attributes() as $key => $atr_val ) :
-		echo $key . '="' . \esc_attr( $atr_val ) . '"';
+		echo \esc_attr( $key ) . '="' . \esc_attr( $atr_val ) . '"';
 		?>
 	<?php endforeach; ?>
 
@@ -47,7 +45,7 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 	if ( $field->is_readonly() ) :
 		?>
 		readonly="readonly"<?php endif; ?>
-	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 		value="<?php echo \esc_html( $value ); ?>"
 	<?php else : ?>
 		value="yes"
diff --git a/templates/paragraph.php b/templates/paragraph.php
index 9d29015..85fb04c 100644
--- a/templates/paragraph.php
+++ b/templates/paragraph.php
@@ -4,16 +4,15 @@
  * @var string $name_prefix
  * @var string $value
  */
-?>
 
-<?php if ( $field->has_description() ) : ?>
+if ( $field->has_description() ) : ?>
 	<tr>
 		<td style="padding-left:0;" colspan="2">
-			<p 
+			<p
 			<?php
 			if ( $field->has_classes() ) :
 				?>
-				class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+				class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		</td>
 	</tr>
 <?php endif; ?>
diff --git a/templates/product-select.php b/templates/product-select.php
index bf545ba..57dd47e 100644
--- a/templates/product-select.php
+++ b/templates/product-select.php
@@ -8,15 +8,15 @@
 ?>
 
 <select class="wc-product-search" multiple="multiple" style="width: 50%;"
-		id="<?php echo esc_attr( $field->get_id() ); ?>"
-		name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
-		data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
+		id="<?php echo \esc_attr( $field->get_id() ); ?>"
+		name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>][]"
+		data-placeholder="<?php \esc_attr_e( 'Search for a product&hellip;', 'wp-forms' ); ?>"
 		data-action="woocommerce_json_search_products_and_variations">
 	<?php
 	foreach ( (array) $value as $product_id ) {
 		$product = wc_get_product( $product_id );
 		if ( is_object( $product ) ) {
-			echo '<option value="' . esc_attr( $product_id ) . '"' . selected(
+			echo '<option value="' . \esc_attr( $product_id ) . '"' . selected(
 				true,
 				true,
 				false
diff --git a/templates/select.php b/templates/select.php
index e437efc..625c316 100644
--- a/templates/select.php
+++ b/templates/select.php
@@ -4,16 +4,18 @@
  * @var string $name_prefix
  * @var mixed $value
  */
+
 ?>
+
 <select
-	id="<?php echo esc_attr( $field->get_id() ); ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 	<?php
 	if ( $field->has_classes() ) :
 		?>
-		class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple() ? '[]' : ''; ?>"
+		class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]<?php echo \esc_attr( $field->is_multiple() ) ? '[]' : ''; ?>"
 	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
-		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
 	<?php
@@ -36,15 +38,15 @@
 	<?php
 	if ( $field->has_placeholder() ) :
 		?>
-		<option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
+		<option value=""><?php echo \esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
 
 	<?php foreach ( $field->get_possible_values() as $possible_value => $label ) : ?>
 		<option
 			<?php
-			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
+			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value, true ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
 				?>
 				selected="selected"<?php endif; ?>
-			value="<?php echo esc_attr( $possible_value ); ?>"
-		><?php echo esc_html( $label ); ?></option>
+			value="<?php echo \esc_attr( $possible_value ); ?>"
+		><?php echo \esc_html( $label ); ?></option>
 	<?php endforeach; ?>
 </select>
diff --git a/templates/textarea.php b/templates/textarea.php
index 4d140fa..8cf3846 100644
--- a/templates/textarea.php
+++ b/templates/textarea.php
@@ -4,17 +4,18 @@
  * @var string $name_prefix
  * @var string $value
  */
+
 ?>
 
 <textarea
-	id="<?php echo esc_attr( $field->get_id() ); ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 		<?php
 		if ( $field->has_classes() ) :
 			?>
-			class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
+			class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
 	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
-		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
 	<?php
@@ -37,5 +38,5 @@
 	<?php
 	if ( $field->has_placeholder() ) :
 		?>
-		placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
-><?php echo esc_html( $value ); ?></textarea>
+		placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
+><?php echo \esc_html( $value ); ?></textarea>
diff --git a/templates/wyswig.php b/templates/wyswig.php
index 6bf06d3..893aec9 100644
--- a/templates/wyswig.php
+++ b/templates/wyswig.php
@@ -4,23 +4,24 @@
  * @var string $name_prefix
  * @var string $value
  */
-?>
-<?php wp_print_styles( 'media-views' ); ?>
+
+wp_print_styles( 'media-views' ); ?>
+
 <script>
 	window.SM_EditorInitialized = true;
 </script>
 
 
 <?php
-$id              = uniqid( 'wyswig_' );
+$editor_id       = uniqid( 'wyswig_' );
 $editor_settings = [
-	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']',
+	'textarea_name' => \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']',
 ];
 
-wp_editor( wp_kses_post( $value ), $id, $editor_settings );
+wp_editor( wp_kses_post( $value ), $editor_id, $editor_settings );
 ?>
 <script type="text/javascript">
 	(function () {
-		ShopMagic.wyswig.init('<?php echo esc_attr( $id ); ?>');
+		ShopMagic.wyswig.init('<?php echo \esc_attr( $editor_id ); ?>');
 	}());
 </script>
-- 
GitLab


From deee969042d4643c1571bd880ad338ca6516ea7d Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 15 Sep 2021 13:21:39 +0200
Subject: [PATCH 12/39] feat: hermetize BasicField methods

---
 src/ContainerForm.php                      |   3 +-
 src/Field.php                              |   7 +-
 src/Field/BasicField.php                   | 151 ++++++++++-----------
 src/Field/ButtonField.php                  |   2 +-
 src/Field/CheckboxField.php                |   5 +-
 src/Field/DatePickerField.php              |   3 -
 src/Field/Header.php                       |   1 -
 src/Field/HiddenField.php                  |   6 +-
 src/Field/ImageInputField.php              |   6 -
 src/Field/InputEmailField.php              |   6 +-
 src/Field/InputNumberField.php             |   6 +-
 src/Field/InputTextField.php               |   6 -
 src/Field/MultipleInputTextField.php       |   1 -
 src/Field/NoOnceField.php                  |   3 +-
 src/Field/ProductSelect.php                |   1 -
 src/Field/TextAreaField.php                |   4 -
 src/Field/Traits/HtmlAttributes.php        |  42 ++++--
 src/Field/WooSelect.php                    |   1 -
 src/Field/WyswigField.php                  |   5 -
 src/FieldsDataReceiver.php                 |   4 +-
 src/Form.php                               |  12 +-
 src/Form/FormWithFields.php                |  12 +-
 src/Sanitizer.php                          |   8 +-
 src/Sanitizer/NoSanitize.php               |   2 +-
 src/Serializer.php                         |   8 +-
 src/Serializer/JsonSerializer.php          |   2 +-
 src/Serializer/NoSerialize.php             |   6 +-
 src/Serializer/ProductSelectSerializer.php |   6 +-
 src/Serializer/SerializeSerializer.php     |   4 +-
 src/Validator/NonceValidator.php           |   4 +-
 30 files changed, 149 insertions(+), 178 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 9c7e339..bd5fc82 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -4,6 +4,7 @@ namespace WPDesk\Forms;
 
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
+use Psr\Container\ContainerInterface;
 
 /**
  * Persistent container support for forms.
@@ -16,7 +17,7 @@ interface ContainerForm {
 	 *
 	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Put data from form into a container.
diff --git a/src/Field.php b/src/Field.php
index 42ea129..311d8eb 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -58,19 +58,22 @@ interface Field {
 
 	public function is_attribute_set( string $name ): bool;
 
-	public function get_meta_value( string $name ): string;
+	/** @return mixed */
+	public function get_meta_value( string $name );
 
 	public function is_meta_value_set( string $name ): bool;
 
 	public function get_classes(): string;
 
+	public function get_type(): string;
+
 	public function has_classes(): bool;
 
 	public function is_class_set( string $name ): bool;
 
 	public function has_data(): bool;
 
-	/** @return array<string,int> */
+	/** @return array<string|int> */
 	public function get_data(): array;
 
 	public function add_data( string $data_name, string $data_value ): Field;
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 9444933..2855357 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -22,112 +22,113 @@ abstract class BasicField implements Field {
 
 	const DEFAULT_PRIORITY = 10;
 
-	/** @var array<string,int,bool> */
-	protected $meta;
-
-	/** @var string */
-	protected $default_value;
-
-	public function __construct() {
-		$this->meta['class']    = [];
-		$this->meta['priority'] = self::DEFAULT_PRIORITY;
-	}
-
-	public function get_label(): string {
+	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>, serializer: ?Serializer} */
+	protected $meta = [
+		'priority'          => self::DEFAULT_PRIORITY,
+		'default_value'     => '',
+		'label'             => '',
+		'description'       => '',
+		'description_tip'   => '',
+		'data'              => [],
+		'serializer'        => null,
+	];
+
+	final public function get_label(): string {
 		return $this->meta['label'];
 	}
 
-	public function set_label( string $value ): Field {
+	final public function set_label( string $value ): Field {
 		$this->meta['label'] = $value;
 
 		return $this;
 	}
 
-	public function get_description_tip(): string {
+	final public function get_description_tip(): string {
 		return $this->meta['description_tip'];
 	}
 
-	public function has_description_tip(): bool {
-		return isset( $this->meta['description_tip'] );
+	final public function has_description_tip(): bool {
+		return ! empty( $this->meta['description_tip'] );
 	}
 
+	/** Override method if you need. */
 	public function should_override_form_template(): bool {
-		return $this->attributes['overrite_template'] ?? false;
+		return false;
 	}
 
-	public function get_description(): string {
+	final public function get_description(): string {
 		return $this->meta['description'];
 	}
 
-	public function has_label(): bool {
-		return isset( $this->meta['label'] );
+	final public function has_label(): bool {
+		return ! empty( $this->meta['label'] );
 	}
 
-	public function has_description(): bool {
-		return isset( $this->meta['description'] );
+	final public function has_description(): bool {
+		return ! empty( $this->meta['description'] );
 	}
 
-	public function set_description( string $value ): Field {
+	final public function set_description( string $value ): Field {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( string $value ): Field {
+	final public function set_description_tip( string $value ): Field {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
 	}
 
 	public function get_type(): string {
-		return $this->attributes['type'];
+		return 'text';
 	}
 
-	public function set_placeholder( string $value ): Field {
-		$this->meta['placeholder'] = $value;
+	final public function set_placeholder( string $value ): Field {
+		$this->attributes['placeholder'] = $value;
 
 		return $this;
 	}
 
-	public function has_placeholder(): bool {
-		return isset( $this->meta['placeholder'] );
+	final public function has_placeholder(): bool {
+		return ! empty( $this->attributes['placeholder'] );
 	}
 
-	public function get_placeholder(): string {
-		return $this->meta['placeholder'];
+	final public function get_placeholder(): string {
+		return $this->attributes['placeholder'];
 	}
 
-	public function set_name( string $name ): Field {
+	final public function set_name( string $name ): Field {
 		$this->attributes['name'] = $name;
 
 		return $this;
 	}
 
-	public function get_meta_value( string $name ): string {
+	final public function get_meta_value( string $name ) {
 		return $this->meta[ $name ];
 	}
 
-	public function get_classes(): string {
-		return implode( ' ', $this->meta['class'] );
+	final public function get_classes(): string {
+		return implode( ' ', $this->attributes['class'] );
 	}
 
-	public function has_classes(): bool {
-		return ! empty( $this->meta['class'] );
+	final public function has_classes(): bool {
+		return ! empty( $this->attributes['class'] );
 	}
 
-	public function has_data(): bool {
+	final public function has_data(): bool {
 		return ! empty( $this->meta['data'] );
 	}
 
-	public function get_data(): array {
-		return $this->meta['data'] ?: [];
+	final public function get_data(): array {
+		return $this->meta['data'];
 	}
 
-	public function get_possible_values() {
-		return $this->meta['possible_values'] ?? [];
+	final public function get_possible_values() {
+		return ! empty( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
 	}
 
-	public function get_id(): string {
+	final public function get_id(): string {
 		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
@@ -135,50 +136,50 @@ abstract class BasicField implements Field {
 		return $this->attributes['name'];
 	}
 
-	public function is_multiple(): bool {
-		return $this->attributes['multiple'] ?? false;
+	final public function is_multiple(): bool {
+		return $this->attributes['multiple'];
 	}
 
-	public function set_disabled(): Field {
+	final public function set_disabled(): Field {
 		$this->attributes['disabled'] = true;
 
 		return $this;
 	}
 
-	public function is_disabled(): bool {
-		return $this->attributes['disabled'] ?? false;
+	final public function is_disabled(): bool {
+		return $this->attributes['disabled'];
 	}
 
-	public function set_readonly(): Field {
+	final public function set_readonly(): Field {
 		$this->attributes['readonly'] = true;
 
 		return $this;
 	}
 
-	public function is_readonly(): bool {
-		return $this->attributes['readonly'] ?? false;
+	final public function is_readonly(): bool {
+		return $this->attributes['readonly'];
 	}
 
-	public function set_required(): Field {
-		$this->meta['required'] = true;
+	final public function set_required(): Field {
+		$this->attributes['required'] = true;
 
 		return $this;
 	}
 
-	public function add_class( string $class_name ): Field {
-		$this->meta['class'][ $class_name ] = $class_name;
+	final public function add_class( string $class_name ): Field {
+		$this->attributes['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	public function unset_class( string $class_name ): Field {
-		unset( $this->meta['class'][ $class_name ] );
+	final public function unset_class( string $class_name ): Field {
+		unset( $this->attributes['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	public function add_data( string $data_name, string $data_value ): Field {
-		if ( ! isset( $this->meta['data'] ) ) {
+	final public function add_data( string $data_name, string $data_value ): Field {
+		if ( empty( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
 		$this->meta['data'][ $data_name ] = $data_value;
@@ -186,28 +187,26 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function unset_data( string $data_name ): Field {
+	final public function unset_data( string $data_name ): Field {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
 	}
 
-	public function is_meta_value_set( string $name ): bool {
-		return isset( $this->meta[ $name ] );
+	final public function is_meta_value_set( string $name ): bool {
+		return ! empty( $this->meta[ $name ] );
 	}
 
-	public function is_class_set( string $name ): bool {
-		return isset( $this->meta['class'][ $name ] );
+	final public function is_class_set( string $name ): bool {
+		return ! empty( $this->attributes['class'][ $name ] );
 	}
 
-	/** @return mixed */
-	public function get_default_value() {
-		return $this->default_value;
+	final public function get_default_value(): string {
+		return $this->meta['default_value'];
 	}
 
-	/** @param mixed $value */
-	public function set_default_value( $value ): Field {
-		$this->default_value = $value;
+	final public function set_default_value( string $value ): Field {
+		$this->meta['default_value'] = $value;
 
 		return $this;
 	}
@@ -221,16 +220,16 @@ abstract class BasicField implements Field {
 		return $chain;
 	}
 
-	public function is_required(): bool {
-		return $this->meta['required'] ?? false;
+	final public function is_required(): bool {
+		return $this->attributes['required'];
 	}
 
 	public function get_sanitizer(): Sanitizer {
 		return new NoSanitize();
 	}
 
-	public function get_serializer(): Serializer {
-		if ( isset( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
+	final public function get_serializer(): Serializer {
+		if ( ! empty( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
 			return $this->meta['serializer'];
 		}
 
@@ -243,7 +242,7 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_priority(): int {
+	final public function get_priority(): int {
 		return $this->meta['priority'];
 	}
 
@@ -252,7 +251,7 @@ abstract class BasicField implements Field {
 	 *
 	 * @see FormWithFields::get_fields()
 	 */
-	public function set_priority( int $priority ): Field {
+	final public function set_priority( int $priority ): Field {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/src/Field/ButtonField.php b/src/Field/ButtonField.php
index f0a4023..6d01a1f 100644
--- a/src/Field/ButtonField.php
+++ b/src/Field/ButtonField.php
@@ -3,10 +3,10 @@
 namespace WPDesk\Forms\Field;
 
 class ButtonField extends NoValueField {
-
 	public function get_template_name(): string {
 		return 'button';
 	}
+
 	public function get_type(): string {
 		return 'button';
 	}
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index 507cda0..d55269e 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -8,9 +8,8 @@ class CheckboxField extends BasicField {
 	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
 
-	public function __construct() {
-		parent::__construct();
-		$this->set_attribute( 'type', 'checkbox' );
+	public function get_type(): string {
+		return 'checkbox';
 	}
 
 	public function get_template_name(): string {
diff --git a/src/Field/DatePickerField.php b/src/Field/DatePickerField.php
index 7060d90..7a69247 100644
--- a/src/Field/DatePickerField.php
+++ b/src/Field/DatePickerField.php
@@ -7,11 +7,8 @@ use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class DatePickerField extends BasicField {
 	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
 		$this->add_class( 'date-picker' );
 		$this->set_placeholder( 'YYYY-MM-DD' );
-		$this->set_attribute( 'type', 'text' );
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/Header.php b/src/Field/Header.php
index cebe249..a704f40 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -6,7 +6,6 @@ use WPDesk\Forms\Field;
 
 class Header extends NoValueField {
 	public function __construct() {
-		parent::__construct();
 		$this->meta['header_size'] = '';
 	}
 
diff --git a/src/Field/HiddenField.php b/src/Field/HiddenField.php
index 9c3856c..e48742c 100644
--- a/src/Field/HiddenField.php
+++ b/src/Field/HiddenField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class HiddenField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'hidden' );
+	public function get_type(): string {
+		return 'hidden';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/ImageInputField.php b/src/Field/ImageInputField.php
index 74c8410..1f58ec5 100644
--- a/src/Field/ImageInputField.php
+++ b/src/Field/ImageInputField.php
@@ -4,12 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class ImageInputField extends BasicField {
 
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'text' );
-	}
-
 	public function get_template_name(): string {
 		return 'input-image';
 	}
diff --git a/src/Field/InputEmailField.php b/src/Field/InputEmailField.php
index ee18412..a54ab4a 100644
--- a/src/Field/InputEmailField.php
+++ b/src/Field/InputEmailField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\EmailSanitizer;
 
 class InputEmailField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'email' );
+	public function get_type(): string {
+		return 'email';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/InputNumberField.php b/src/Field/InputNumberField.php
index 9ee7405..380da44 100644
--- a/src/Field/InputNumberField.php
+++ b/src/Field/InputNumberField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputNumberField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'number' );
+	public function get_type(): string {
+		return 'number';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/InputTextField.php b/src/Field/InputTextField.php
index 7ca6a96..24b0fa6 100644
--- a/src/Field/InputTextField.php
+++ b/src/Field/InputTextField.php
@@ -6,12 +6,6 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputTextField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'text' );
-	}
-
 	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
diff --git a/src/Field/MultipleInputTextField.php b/src/Field/MultipleInputTextField.php
index cf976fe..6648e2a 100644
--- a/src/Field/MultipleInputTextField.php
+++ b/src/Field/MultipleInputTextField.php
@@ -3,7 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class MultipleInputTextField extends InputTextField {
-
 	public function get_template_name(): string {
 		return 'input-text-multiple';
 	}
diff --git a/src/Field/NoOnceField.php b/src/Field/NoOnceField.php
index 6419a37..17ac6e0 100644
--- a/src/Field/NoOnceField.php
+++ b/src/Field/NoOnceField.php
@@ -7,8 +7,7 @@ use WPDesk\Forms\Validator\NonceValidator;
 
 class NoOnceField extends BasicField {
 
-	public function __construct( $action_name ) {
-		parent::__construct();
+	public function __construct( string $action_name ) {
 		$this->meta['action'] = $action_name;
 	}
 
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 8960304..2a10e46 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class ProductSelect extends SelectField {
 	public function __construct() {
-		parent::__construct();
 		$this->set_multiple();
 	}
 
diff --git a/src/Field/TextAreaField.php b/src/Field/TextAreaField.php
index 0f83ffe..f22b2bb 100644
--- a/src/Field/TextAreaField.php
+++ b/src/Field/TextAreaField.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class TextAreaField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-	}
 
 	public function get_template_name(): string {
 		return 'textarea';
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 5ae190a..71eccba 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -9,30 +9,44 @@ namespace WPDesk\Forms\Field\Traits;
  */
 trait HtmlAttributes {
 
-	/** @var string[] */
-	protected $attributes;
+	/** @var array{placeholder: string, name: string, id: string, class: string[], readonly: bool, multiple: bool, disabled: bool, required: bool, method: string, action: string} */
+	protected $attributes = [
+		'placeholder' => '',
+		'name'        => '',
+		'id'          => '',
+		'class'       => [],
+		'action'      => '',
+		'method'      => 'POST',
+		'readonly'    => false,
+		'multiple'    => false,
+		'disabled'    => false,
+		'required'    => false,
+	];
 
 	/**
 	 * Get list of all attributes except given.
 	 *
 	 * @param string[] $except
 	 *
-	 * @return string[]
+	 * @return array<string[]|string|bool>
 	 */
-	public function get_attributes( array $except = [ 'name', 'type' ] ): array {
+	final public function get_attributes( array $except = [ 'name' ] ): array {
 		return array_filter(
 			$this->attributes,
-			static function ( $value, $key ) use ( $except ) {
+			static function ( $key ) use ( $except ) {
 				return ! in_array( $key, $except, true );
 			},
-			ARRAY_FILTER_USE_BOTH
+			ARRAY_FILTER_USE_KEY
 		);
 	}
 
 	/**
+	 * @param string $name
+	 * @param string[]|string|bool $value
+	 *
 	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
 	 */
-	public function set_attribute( string $name, string $value ) {
+	final public function set_attribute( string $name, $value ) {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
@@ -41,17 +55,21 @@ trait HtmlAttributes {
 	/**
 	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
 	 */
-	public function unset_attribute( string $name ) {
+	final public function unset_attribute( string $name ) {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
 	}
 
-	public function is_attribute_set( string $name ): bool {
-		return isset( $this->attributes[ $name ] );
+	final public function is_attribute_set( string $name ): bool {
+		return ! empty( $this->attributes[ $name ] );
 	}
 
-	public function get_attribute( string $name, string $default = null ): string {
-		return $this->attributes[ $name ] ?? $default ?? '';
+	final public function get_attribute( string $name, string $default = null ): string {
+		if ( is_array( $this->attributes[ $name ] ) ) {
+			// Be aware of coercing - if implode returns string(0) '', then return $default value.
+			return implode( ' ', $this->attributes[ $name ] ) ?: $default ?? '';
+		}
+		return (string) $this->attributes[ $name ] ?? $default ?? '';
 	}
 }
diff --git a/src/Field/WooSelect.php b/src/Field/WooSelect.php
index bc59f9c..ec2719c 100644
--- a/src/Field/WooSelect.php
+++ b/src/Field/WooSelect.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class WooSelect extends SelectField {
 	public function __construct() {
-		parent::__construct();
 		$this->set_multiple();
 		$this->add_class( 'wc-enhanced-select' );
 	}
diff --git a/src/Field/WyswigField.php b/src/Field/WyswigField.php
index 06db980..a2f4168 100644
--- a/src/Field/WyswigField.php
+++ b/src/Field/WyswigField.php
@@ -3,11 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class WyswigField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-	}
-
 	public function get_template_name(): string {
 		return 'wyswig';
 	}
diff --git a/src/FieldsDataReceiver.php b/src/FieldsDataReceiver.php
index 86a1583..e41743d 100644
--- a/src/FieldsDataReceiver.php
+++ b/src/FieldsDataReceiver.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use Psr\Container\ContainerInterface;
-
 /**
  * Some field owners can receive and process field data.
  * Probably should be used with FieldProvider interface.
@@ -16,5 +14,5 @@ interface FieldsDataReceiver {
 	 *
 	 * @return void
 	 */
-	public function update_fields_data( ContainerInterface $data );
+	public function update_fields_data( \Psr\Container\ContainerInterface $data );
 }
diff --git a/src/Form.php b/src/Form.php
index 504ebbe..5f8725d 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms;
 
+use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
 
 /**
@@ -35,15 +36,6 @@ interface Form {
 	 */
 	public function handle_request( array $request = [] );
 
-	/**
-	 * Data could be saved in some place. Use this method to transmit them to form.
-	 *
-	 * @param array $data Data for form.
-	 *
-	 * @return void
-	 */
-	public function set_data( $data );
-
 	/**
 	 * Use to render the form to string.
 	 *
@@ -54,7 +46,7 @@ interface Form {
 	/**
 	 * Get data from form. Use after handle_request or set_data.
 	 *
-	 * @return array<int,string>
+	 * @return array<int|string>
 	 */
 	public function get_data(): array;
 
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index ba13928..ac0f159 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -7,7 +7,6 @@ use WPDesk\Forms\ContainerForm;
 use WPDesk\Forms\Field;
 use WPDesk\Forms\FieldProvider;
 use WPDesk\Forms\Form;
-use WPDesk\Persistence\Adapter\ArrayContainer;
 use WPDesk\Persistence\ElementNotExistsException;
 use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
@@ -50,11 +49,11 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	}
 
 	public function get_method(): string {
-		return $this->attributes['method'] ?? 'POST';
+		return $this->attributes['method'];
 	}
 
 	public function get_action(): string {
-		return $this->attributes['action'] ?? '';
+		return $this->attributes['action'];
 	}
 
 	public function is_submitted(): bool {
@@ -113,14 +112,9 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
-	 * @param array|ContainerInterface $data Data consistent with Form or ContainerForm interface.
-	 *
 	 * @return void
 	 */
-	public function set_data( $data ) {
-		if ( is_array( $data ) ) {
-			$data = new ArrayContainer( $data );
-		}
+	public function set_data( ContainerInterface $data ) {
 		foreach ( $this->fields as $field ) {
 			$data_key = $field->get_name();
 			if ( $data->has( $data_key ) ) {
diff --git a/src/Sanitizer.php b/src/Sanitizer.php
index bc8f207..3f57eac 100644
--- a/src/Sanitizer.php
+++ b/src/Sanitizer.php
@@ -3,6 +3,10 @@
 namespace WPDesk\Forms;
 
 interface Sanitizer {
-	/** @param mixed $value */
-	public function sanitize( $value ): string;
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
+	public function sanitize( $value );
 }
diff --git a/src/Sanitizer/NoSanitize.php b/src/Sanitizer/NoSanitize.php
index 21bce01..a3fe4a6 100644
--- a/src/Sanitizer/NoSanitize.php
+++ b/src/Sanitizer/NoSanitize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class NoSanitize implements Sanitizer {
-	public function sanitize( $value ): string {
+	public function sanitize( $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer.php b/src/Serializer.php
index 8302325..2096b0f 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -5,15 +5,11 @@ namespace WPDesk\Forms;
 interface Serializer {
 	/**
 	 * @param mixed $value
-	 *
-	 * @return mixed
 	 */
-	public function serialize( $value );
+	public function serialize( $value ): string;
 
 	/**
-	 * @param mixed $value
-	 *
 	 * @return mixed
 	 */
-	public function unserialize( $value );
+	public function unserialize( string $value );
 }
diff --git a/src/Serializer/JsonSerializer.php b/src/Serializer/JsonSerializer.php
index bc8c0e0..9ded064 100644
--- a/src/Serializer/JsonSerializer.php
+++ b/src/Serializer/JsonSerializer.php
@@ -9,7 +9,7 @@ class JsonSerializer implements Serializer {
 		return (string) json_encode( $value );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return json_decode( $value, true );
 	}
 }
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index b29e88b..371e8e7 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ) {
-		return $value;
+	public function serialize( $value ): string {
+		return (string) $value;
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer/ProductSelectSerializer.php b/src/Serializer/ProductSelectSerializer.php
index e801d4d..7c4f0e8 100644
--- a/src/Serializer/ProductSelectSerializer.php
+++ b/src/Serializer/ProductSelectSerializer.php
@@ -10,7 +10,7 @@ use WPDesk\Forms\Serializer;
  * @package WPDesk\Forms\Serializer
  */
 class ProductSelectSerializer implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		$products_with_names = [];
 		if ( is_array( $value ) ) {
 			foreach ( $value as $product_id ) {
@@ -22,10 +22,10 @@ class ProductSelectSerializer implements Serializer {
 			}
 		}
 
-		return $products_with_names;
+		return implode( ' ', $products_with_names );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer/SerializeSerializer.php b/src/Serializer/SerializeSerializer.php
index 79d13f6..dde47cc 100644
--- a/src/Serializer/SerializeSerializer.php
+++ b/src/Serializer/SerializeSerializer.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class SerializeSerializer implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		return serialize( $value );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return unserialize( $value );
 	}
 
diff --git a/src/Validator/NonceValidator.php b/src/Validator/NonceValidator.php
index 8709af6..b887428 100644
--- a/src/Validator/NonceValidator.php
+++ b/src/Validator/NonceValidator.php
@@ -6,14 +6,16 @@ use WPDesk\Forms\Validator;
 
 class NonceValidator implements Validator {
 
+	/** @var string */
 	private $action;
 
+	/** @param string $action */
 	public function __construct( $action ) {
 		$this->action = $action;
 	}
 
 	public function is_valid( $value ): bool {
-		return wp_verify_nonce( $value, $this->action );
+		return (bool) wp_verify_nonce( $value, $this->action );
 	}
 
 	public function get_messages(): array {
-- 
GitLab


From d9cb7e31dd52bcc469a4cb24aad0fb54e2b8bc23 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Thu, 2 Sep 2021 23:15:03 +0200
Subject: [PATCH 13/39] feat(fields): #1 add sorting fields by priority field

---
 .gitlab-ci.yml                                |  1 -
 composer.json                                 |  2 +-
 phpunit-integration.xml                       |  7 +-
 src/Field.php                                 |  3 +
 src/Field/BasicField.php                      | 11 +++
 src/Form/FormWithFields.php                   | 11 ++-
 tests/integration/Form/FormWithFieldsTest.php | 71 +++++++++++++++++++
 tests/integration/bootstrap.php               | 12 +---
 8 files changed, 98 insertions(+), 20 deletions(-)
 create mode 100644 tests/integration/Form/FormWithFieldsTest.php

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 38447e9..b865367 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,6 @@ variables:
   DISABLE_ACCEPTANCE: 1
   DISABLE_PHP_5_5: 1
   DISABLE_CODECEPTION: 1
-  DISABLE_INTEGRATION_TESTS: 1
   IS_LIBRARY: 1
 
 include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml'
diff --git a/composer.json b/composer.json
index 6a79cb8..afcddb9 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,7 @@
     }
   ],
   "require": {
-    "php": ">=5.6",
+    "php": ">=7.0",
     "ext-curl": "*",
     "ext-json": "*",
     "wpdesk/wp-persistence": "^2.0|^3.0",
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
index 4a342ab..c78958b 100644
--- a/phpunit-integration.xml
+++ b/phpunit-integration.xml
@@ -3,7 +3,7 @@
      >
     <testsuites>
         <testsuite>
-            <directory prefix="Test" suffix=".php">./tests/integration</directory>
+            <directory suffix="Test.php">./tests/integration</directory>
         </testsuite>
     </testsuites>
 
@@ -20,9 +20,4 @@
         <log type="coverage-clover" target="build-coverage/clover.xml"/>
     </logging>
 
-    <php>
-        <env name="WP_DEVELOP_DIR" value="/tmp/wordpress-develop"/>
-        <env name="WC_DEVELOP_DIR" value="/tmp/woocommerce"/>
-    </php>
-
 </phpunit>
\ No newline at end of file
diff --git a/src/Field.php b/src/Field.php
index 458bb38..4205df4 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -163,4 +163,7 @@ interface Field {
 
 	/** @return Serializer */
 	public function get_serializer();
+
+	/** @return int */
+	public function get_priority();
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index da93922..7158b73 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -298,4 +298,15 @@ abstract class BasicField implements Field {
 
 		return $this;
 	}
+
+	/** @return int */
+	public function get_priority() {
+		return $this->meta['priority'] ?? 10;
+	}
+
+	public function set_priority( int $priority ) {
+		$this->meta['priority'] = $priority;
+
+		return $this;
+	}
 }
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index 4b5819c..a5a494c 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -243,7 +243,16 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 * @inheritDoc
 	 */
 	public function get_fields() {
-		return $this->fields;
+		$fields = $this->fields;
+
+		usort(
+			$fields,
+			static function ( Field $a, Field $b ) {
+				return $a->get_priority() <=> $b->get_priority();
+			}
+		);
+
+		return $fields;
 	}
 
 	/**
diff --git a/tests/integration/Form/FormWithFieldsTest.php b/tests/integration/Form/FormWithFieldsTest.php
new file mode 100644
index 0000000..9d8c2b2
--- /dev/null
+++ b/tests/integration/Form/FormWithFieldsTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace integration\Form;
+
+use WPDesk\Forms\Field\InputNumberField;
+use WPDesk\Forms\Field\InputTextField;
+use WPDesk\Forms\Field\SelectField;
+use WPDesk\Forms\Form\FormWithFields;
+use PHPUnit\Framework\TestCase;
+
+class FormWithFieldsTest extends TestCase {
+
+	/** @var FormWithFields */
+	private $form;
+
+	protected function setUp() {
+		$this->form = new FormWithFields([]);
+	}
+
+	public function test_should_return_fields_sorted_by_priority() {
+		$this->form->add_fields(
+			[
+				( new InputTextField() )
+				->set_label('third'),
+				( new SelectField() )
+				->set_label('second')
+				->set_priority(5),
+				( new InputNumberField() )
+				->set_label('first')
+				->set_priority(1)
+			]
+		);
+
+		$expected = [
+			( new InputNumberField() )
+			->set_label('first')
+			->set_priority(1),
+			( new SelectField() )
+			->set_label('second')
+			->set_priority(5),
+			( new InputTextField() )
+			->set_label('third')
+		];
+
+		self::assertEquals($expected, $this->form->get_fields());
+	}
+
+	public function test_should_return_fields_by_adding_order_if_no_priority_set() {
+		$this->form->add_fields(
+			[
+				( new InputTextField() )
+					->set_label('first'),
+				( new SelectField() )
+					->set_label('second'),
+				( new InputNumberField() )
+					->set_label('third'),
+			]
+		);
+
+		$expected = [
+			( new InputTextField() )
+				->set_label('first'),
+			( new SelectField() )
+				->set_label('second'),
+			( new InputNumberField() )
+				->set_label('third'),
+		];
+
+		self::assertEquals($expected, $this->form->get_fields());
+	}
+}
diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php
index a422fd9..bbe2889 100644
--- a/tests/integration/bootstrap.php
+++ b/tests/integration/bootstrap.php
@@ -15,14 +15,4 @@ if ( getenv( 'PLUGIN_PATH' ) !== false ) {
 	define( 'PLUGIN_PATH', getenv( 'PLUGIN_PATH' ) );
 } else {
 	define( 'PLUGIN_PATH', __DIR__ . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR );
-}
-
-require_once( getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit/includes/functions.php' );
-
-tests_add_filter( 'muplugins_loaded', function () {
-}, 100 );
-
-putenv('WP_TESTS_DIR=' . getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit');
-require_once( getenv( 'WC_DEVELOP_DIR' ) . '/tests/bootstrap.php' );
-
-do_action('plugins_loaded');
\ No newline at end of file
+}
\ No newline at end of file
-- 
GitLab


From e4208af73d59d2f37e78194fdaa94d83f6d9877a Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Fri, 3 Sep 2021 10:41:06 +0200
Subject: [PATCH 14/39] refactor: add consistency in typing and inline docs

---
 src/Field/BasicField.php                      | 14 ++++++++++----
 tests/integration/Form/FormWithFieldsTest.php | 10 ++++++++--
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 7158b73..54ef3cc 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
+use WPDesk\Forms\Form\FormWithFields;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer\NoSerialize;
@@ -25,6 +26,7 @@ abstract class BasicField implements Field {
 
 	public function __construct() {
 		$this->meta['class'] = [];
+		$this->meta['priority'] = 10;
 	}
 
 	public function get_label() {
@@ -299,12 +301,16 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	/** @return int */
-	public function get_priority() {
-		return $this->meta['priority'] ?? 10;
+	public function get_priority(): int {
+		return $this->meta['priority'];
 	}
 
-	public function set_priority( int $priority ) {
+	/**
+	 * Fields are sorted by lowest priority value first, when getting FormWithFields
+	 *
+	 * @see FormWithFields::get_fields()
+	 */
+	public function set_priority( int $priority ): self {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/tests/integration/Form/FormWithFieldsTest.php b/tests/integration/Form/FormWithFieldsTest.php
index 9d8c2b2..165592d 100644
--- a/tests/integration/Form/FormWithFieldsTest.php
+++ b/tests/integration/Form/FormWithFieldsTest.php
@@ -21,10 +21,13 @@ class FormWithFieldsTest extends TestCase {
 		$this->form->add_fields(
 			[
 				( new InputTextField() )
-				->set_label('third'),
+				->set_label('fourth'),
 				( new SelectField() )
 				->set_label('second')
 				->set_priority(5),
+				( new SelectField() )
+				->set_label('third')
+				->set_priority(7),
 				( new InputNumberField() )
 				->set_label('first')
 				->set_priority(1)
@@ -38,8 +41,11 @@ class FormWithFieldsTest extends TestCase {
 			( new SelectField() )
 			->set_label('second')
 			->set_priority(5),
-			( new InputTextField() )
+			( new SelectField() )
 			->set_label('third')
+			->set_priority(7),
+			( new InputTextField() )
+			->set_label('fourth')
 		];
 
 		self::assertEquals($expected, $this->form->get_fields());
-- 
GitLab


From 35715e1a9fe1e13a7ceb370785bcb66a2573ef93 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Mon, 6 Sep 2021 13:58:59 +0200
Subject: [PATCH 15/39] feat: add strong typing to the package

---
 .editorconfig                                |  91 ++++++++++
 .env.testing                                 |  17 ++
 .gitignore                                   |   3 +-
 composer.json                                | 101 +++++------
 phpcs.xml.dist                               |  48 +++++
 phpstan.neon.dist                            |   4 +
 phpunit-integration.xml                      |   6 -
 src/ContainerForm.php                        |  11 +-
 src/Escaper.php                              |   8 +-
 src/Field.php                                | 149 +++++-----------
 src/Field/BasicField.php                     | 173 ++++++-------------
 src/Field/ButtonField.php                    |  18 +-
 src/Field/CheckboxField.php                  |  11 +-
 src/Field/DatePickerField.php                |   9 +-
 src/Field/Header.php                         |   6 +-
 src/Field/HiddenField.php                    |   5 +-
 src/Field/ImageInputField.php                |   5 +-
 src/Field/InputNumberField.php               |   5 +-
 src/Field/InputTextField.php                 |   5 +-
 src/Field/MultipleInputTextField.php         |   5 +-
 src/Field/NoOnceField.php                    |   5 +-
 src/Field/NoValueField.php                   |   2 +-
 src/Field/Paragraph.php                      |   4 +-
 src/Field/ProductSelect.php                  |   2 +-
 src/Field/RadioField.php                     |   2 +-
 src/Field/SelectField.php                    |   7 +-
 src/Field/SubmitField.php                    |   6 +-
 src/Field/TextAreaField.php                  |   2 +-
 src/Field/TimepickerField.php                |   5 +-
 src/Field/Traits/HtmlAttributes.php          |  40 ++---
 src/Field/WooSelect.php                      |   2 +-
 src/Field/WyswigField.php                    |   4 +-
 src/FieldProvider.php                        |   2 +-
 src/FieldRenderer.php                        |  13 +-
 src/FieldsDataReceiver.php                   |   2 -
 src/Form.php                                 |  36 ++--
 src/Form/AbstractForm.php                    |  94 ----------
 src/Form/FormWithFields.php                  | 145 +++++-----------
 src/Form/FormsCollection.php                 | 115 ------------
 src/Persistence/FieldPersistenceStrategy.php |  10 +-
 src/Renderer/JsonNormalizedRenderer.php      |   8 +-
 src/Resolver/DefaultFormFieldResolver.php    |   5 +-
 src/Sanitizer.php                            |   8 +-
 src/Sanitizer/CallableSanitizer.php          |   6 +-
 src/Sanitizer/NoSanitize.php                 |   2 +-
 src/Sanitizer/TextFieldSanitizer.php         |   2 +-
 src/Serializer.php                           |  10 ++
 src/Serializer/JsonSerializer.php            |   4 +-
 src/Serializer/NoSerialize.php               |   2 +-
 src/Serializer/ProductSelectSerializer.php   |   3 -
 src/Validator.php                            |  14 +-
 src/Validator/ChainValidator.php             |   8 +-
 src/Validator/NoValidateValidator.php        |   4 +-
 src/Validator/NonceValidator.php             |   9 +-
 src/Validator/RequiredValidator.php          |   4 +-
 templates/button.php                         |  31 ++--
 templates/form-field.php                     |  22 ++-
 templates/form-label.php                     |   4 +-
 templates/form-start.php                     |   2 +-
 templates/header.php                         |   4 +-
 templates/input-checkbox.php                 |  18 +-
 templates/input-date-picker.php              |  11 +-
 templates/input-hidden.php                   |  17 +-
 templates/input-image.php                    |   8 +-
 templates/input-number.php                   |  11 +-
 templates/input-radio.php                    |  17 +-
 templates/input-submit.php                   |  25 ++-
 templates/input-text-multiple.php            |  85 +++++----
 templates/input-text.php                     |  17 +-
 templates/input.php                          |  56 +++---
 templates/noonce.php                         |   4 +-
 templates/paragraph.php                      |   8 +-
 templates/product-select.php                 |  17 +-
 templates/select.php                         |  43 +++--
 templates/textarea.php                       |  38 ++--
 templates/wyswig.php                         |   8 +-
 tests/unit/TestForm.php                      |  58 -------
 tests/unit/TestFormCollection.php            | 141 ---------------
 78 files changed, 774 insertions(+), 1138 deletions(-)
 create mode 100644 .editorconfig
 create mode 100644 .env.testing
 create mode 100644 phpcs.xml.dist
 create mode 100644 phpstan.neon.dist
 delete mode 100644 src/Form/AbstractForm.php
 delete mode 100644 src/Form/FormsCollection.php
 delete mode 100644 tests/unit/TestForm.php
 delete mode 100644 tests/unit/TestFormCollection.php

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..3fe55c8
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,91 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# WordPress Coding Standards
+# https://make.wordpress.org/core/handbook/coding-standards/
+
+# Configuration for PhpStorm
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
+tab_width = 4
+ij_continuation_indent_size = 4
+
+[*.scss]
+ij_scss_enforce_quotes_on_format = true
+ij_scss_hex_color_long_format = true
+ij_scss_hex_color_lower_case = true
+
+[{*.cjs,*.js}]
+indent_style = space
+indent_size = 2
+ij_javascript_do_while_brace_force = always
+ij_javascript_if_brace_force = always
+ij_javascript_import_sort_module_name = true
+ij_javascript_reformat_c_style_comments = true
+ij_javascript_space_after_unary_not = true
+ij_javascript_space_before_unary_not = true
+ij_javascript_spaces_within_array_initializer_brackets = true
+ij_javascript_spaces_within_brackets = true
+ij_javascript_spaces_within_catch_parentheses = true
+ij_javascript_spaces_within_for_parentheses = true
+ij_javascript_spaces_within_if_parentheses = true
+ij_javascript_spaces_within_imports = true
+ij_javascript_spaces_within_interpolation_expressions = true
+ij_javascript_spaces_within_method_call_parentheses = true
+ij_javascript_spaces_within_method_parentheses = true
+ij_javascript_spaces_within_object_literal_braces = true
+ij_javascript_spaces_within_parentheses = true
+ij_javascript_spaces_within_switch_parentheses = true
+ij_javascript_spaces_within_while_parentheses = true
+ij_javascript_while_brace_force = always
+
+[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
+ij_php_align_assignments = true
+ij_php_align_class_constants = true
+ij_php_align_key_value_pairs = true
+ij_php_align_phpdoc_comments = true
+ij_php_align_phpdoc_param_names = true
+ij_php_class_brace_style = end_of_line
+ij_php_comma_after_last_array_element = true
+ij_php_else_if_style = combine
+ij_php_force_short_declaration_array_style = true
+ij_php_getters_setters_naming_style = snake_case
+ij_php_if_brace_force = always
+ij_php_lower_case_boolean_const = true
+ij_php_lower_case_null_const = true
+ij_php_method_brace_style = end_of_line
+ij_php_phpdoc_blank_line_before_tags = true
+ij_php_phpdoc_blank_lines_around_parameters = true
+ij_php_phpdoc_keep_blank_lines = false
+ij_php_phpdoc_wrap_long_lines = true
+ij_php_space_after_type_cast = true
+ij_php_space_after_unary_not = true
+ij_php_space_before_unary_not = true
+ij_php_spaces_around_var_within_brackets = true
+ij_php_spaces_within_array_initializer_braces = true
+ij_php_spaces_within_catch_parentheses = true
+ij_php_spaces_within_for_parentheses = true
+ij_php_spaces_within_if_parentheses = true
+ij_php_spaces_within_method_call_parentheses = true
+ij_php_spaces_within_method_parentheses = true
+ij_php_spaces_within_parentheses = true
+ij_php_spaces_within_switch_parentheses = true
+ij_php_spaces_within_while_parentheses = true
+ij_php_ternary_operation_signs_on_next_line = true
+ij_php_variable_naming_style = snake_case
+
+[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
+ij_html_add_new_line_before_tags = div,p,a
+ij_html_align_attributes = false
+ij_html_do_not_indent_children_of_tags = html,thead,tbody,tfoot
+ij_html_new_line_after_last_attribute = when multiline
+ij_html_space_inside_empty_tag = true
+ij_html_uniform_ident = true
diff --git a/.env.testing b/.env.testing
new file mode 100644
index 0000000..3aa2f5f
--- /dev/null
+++ b/.env.testing
@@ -0,0 +1,17 @@
+WP_ROOT_FOLDER="${APACHE_DOCUMENT_ROOT}"
+TEST_SITE_WP_ADMIN_PATH="/wp-admin"
+TEST_SITE_DB_NAME="wptest"
+TEST_SITE_DB_HOST="mysqltests"
+TEST_SITE_DB_USER="mysql"
+TEST_SITE_DB_PASSWORD="mysql"
+TEST_SITE_TABLE_PREFIX="wp_"
+TEST_DB_NAME="wptest"
+TEST_DB_HOST="mysqltests"
+TEST_DB_USER="mysql"
+TEST_DB_PASSWORD="mysql"
+TEST_TABLE_PREFIX="wp_"
+TEST_SITE_WP_URL="http://${WOOTESTS_IP}"
+TEST_SITE_WP_DOMAIN="${WOOTESTS_IP}"
+TEST_SITE_ADMIN_EMAIL="grola@seostudio.pl"
+TEST_SITE_ADMIN_USERNAME="admin"
+TEST_SITE_ADMIN_PASSWORD="admin"
diff --git a/.gitignore b/.gitignore
index 4b86223..16e7a8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
 .idea
 composer.lock
 build-coverage
-swagger
\ No newline at end of file
+swagger
+.phpcs-cache
diff --git a/composer.json b/composer.json
index afcddb9..8150bcf 100644
--- a/composer.json
+++ b/composer.json
@@ -1,52 +1,53 @@
 {
-  "name": "wpdesk/wp-forms",
-  "description": "WP Forms",
-  "authors": [
-    {
-      "name": "Marcin",
-      "email": "marcin@wpdesk.pl"
-    },
-    {
-      "name": "Krzysiek",
-      "email": "krzysiek@wpdesk.pl"
-    },
-    {
-      "name": "Piotr Potrebka",
-      "email": "piotr.potrebka@wpdesk.pl"
-    }
-  ],
-  "require": {
-    "php": ">=7.0",
-    "ext-curl": "*",
-    "ext-json": "*",
-    "wpdesk/wp-persistence": "^2.0|^3.0",
-    "wpdesk/wp-view": "^1.1"
-  },
-  "require-dev": {
-    "phpunit/phpunit": "<7",
-    "wp-coding-standards/wpcs": "^0.14.1",
-    "squizlabs/php_codesniffer": "^3.0.2",
-    "mockery/mockery": "*",
-    "10up/wp_mock": "*"
-  },
-  "autoload": {
-    "psr-4": {
-      "WPDesk\\Forms\\": "src/"
-    }
-  },
-  "autoload-dev": {
-  },
-  "extra": {
-    "text-domain": "wp-forms",
-    "translations-folder": "lang",
-    "po-files": {
-      "pl_PL": "pl_PL.po"
-    }
-  },
-  "scripts": {
-    "phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
-    "phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
-    "phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
-    "phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
-  }
+	"name": "wpdesk/wp-forms",
+	"description": "WP Forms",
+	"authors": [
+		{
+			"name": "Marcin",
+			"email": "marcin@wpdesk.pl"
+		},
+		{
+			"name": "Krzysiek",
+			"email": "krzysiek@wpdesk.pl"
+		},
+		{
+			"name": "Piotr Potrebka",
+			"email": "piotr.potrebka@wpdesk.pl"
+		}
+	],
+	"require": {
+		"php": ">=7.0",
+		"ext-curl": "*",
+		"ext-json": "*",
+		"wpdesk/wp-persistence": "^2.0|^3.0",
+		"wpdesk/wp-view": "^1.1"
+	},
+	"require-dev": {
+		"phpunit/phpunit": "<7",
+		"phpstan/phpstan": "^0.12",
+		"wpdesk/wp-code-sniffer": "^1.2.3",
+		"10up/wp_mock": "*",
+		"szepeviktor/phpstan-wordpress": "^0.7.7",
+		"phpstan/extension-installer": "^1.1"
+	},
+	"autoload": {
+		"psr-4": {
+			"WPDesk\\Forms\\": "src/"
+		}
+	},
+	"autoload-dev": {
+	},
+	"extra": {
+		"text-domain": "wp-forms",
+		"translations-folder": "lang",
+		"po-files": {
+			"pl_PL": "pl_PL.po"
+		}
+	},
+	"scripts": {
+		"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
+		"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
+		"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
+		"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
+	}
 }
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..6ef3f27
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<ruleset name="WordPress Coding Standards for WP Desk Plugin">
+
+	<!--
+	#############################################################################
+	COMMAND LINE ARGUMENTS
+	https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml
+	#############################################################################
+	-->
+
+	<!-- Scan all files. -->
+	<file>./src</file>
+	<file>./templates</file>
+
+	<!-- Only check PHP files. -->
+	<arg name="extensions" value="php"/>
+
+	<!-- Show progress, show the error codes for each message (source). -->
+	<arg value="sp"/>
+
+	<!-- Check up to 8 files simultaneously. -->
+	<arg name="parallel" value="8"/>
+
+	<!-- Cache outcomes for better performance. Remember to add the file to .gitignore. -->
+	<arg name="cache" value="./.phpcs-cache"/>
+
+	<!--
+	#############################################################################
+	USE THE WPDeskCS RULESET
+	#############################################################################
+	-->
+
+	<!-- Define plugin text domain for i18n. -->
+	<config name="text_domain" value="shopmagic-for-woocommerce"/>
+
+	<!-- This value should be aligned with WordPress support version declared in plugin header -->
+	<config name="minimum_supported_wp_version" value="5.0"/>
+
+	<!-- Set value aligned with supported PHP Version for PHPCompatibilityWP check. -->
+	<config name="testVersion" value="7.0-"/>
+
+	<rule ref="WPDeskPlugin"/>
+
+	<rule ref="Squiz.Commenting.ClassComment.Missing">
+		<exclude name="Squiz.Commenting.ClassComment.Missing"/>
+	</rule>
+
+</ruleset>
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..200d200
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,4 @@
+parameters:
+    level: max
+    paths:
+        - src/
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
index c78958b..8341e36 100644
--- a/phpunit-integration.xml
+++ b/phpunit-integration.xml
@@ -13,11 +13,5 @@
         </whitelist>
     </filter>
 
-    <logging>
-        <log type="junit" target="build-coverage/report.junit.xml"/>
-        <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/>
-        <log type="coverage-text" target="build-coverage/coverage.txt"/>
-        <log type="coverage-clover" target="build-coverage/clover.xml"/>
-    </logging>
 
 </phpunit>
\ No newline at end of file
diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 1d056b6..0510706 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
@@ -12,18 +11,12 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 interface ContainerForm {
-	/**
-	 * @param ContainerInterface $data
-	 *
-	 * @return void
-	 */
-	public function set_data( $data );
+	/** @return void */
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Put data from form into a container.
 	 *
-	 * @param PersistentContainer $container Target container.
-	 *
 	 * @return void
 	 */
 	public function put_data( PersistentContainer $container );
diff --git a/src/Escaper.php b/src/Escaper.php
index cb20d58..8c460dd 100644
--- a/src/Escaper.php
+++ b/src/Escaper.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms;
 
 interface Escaper {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return string
-	 */
-	public function escape( $value );
+	/** @param mixed $value */
+	public function escape( $value ): string;
 }
diff --git a/src/Field.php b/src/Field.php
index 4205df4..2a6569e 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use WPDesk\Forms\Field\BasicField;
-
 /**
  * The idea is that from the moment the factory returns this interface it's values cannot be changed.
  * And that is why here are only the getters.
@@ -13,157 +11,88 @@ use WPDesk\Forms\Field\BasicField;
  * @package WPDesk\Forms
  */
 interface Field {
-	/** @return string */
-	public function get_name();
+	public function get_name(): string;
 
 	/** @return mixed */
 	public function get_default_value();
 
-	/** @return string */
-	public function get_template_name();
+	public function get_template_name(): string;
 
-	/**
-	 * When this field is used on form this field will force it's own template.
-	 *
-	 * return bool
-	 */
-	public function should_override_form_template();
+	/** When this field is used on form this field will force it's own template. */
+	public function should_override_form_template(): bool;
 
-	/**
-	 * HTML label.
-	 *
-	 * @return string
-	 */
-	public function get_label();
+	/** HTML label. */
+	public function get_label(): string;
 
-	/** bool */
-	public function has_label();
+	public function has_label(): bool;
 
-	/**
-	 * Description for field. It can be shown near the field.
-	 *
-	 * @return string
-	 */
-	public function get_description();
+	public function get_description(): string;
 
-	/**
-	 * Additional field description that should be shown in optional hover tip.
-	 *
-	 * @return string
-	 */
-	public function get_description_tip();
+	/** Additional field description that should be shown in optional hover tip. */
+	public function get_description_tip(): string;
 
-	/** @return bool */
-	public function has_description_tip();
+	public function has_description_tip(): bool;
 
-	/** @return bool */
-	public function has_description();
+	public function has_description(): bool;
 
-	/**
-	 * @return bool
-	 */
-	public function is_readonly();
+	public function is_readonly(): bool;
 
-	/** @return bool */
-	public function is_disabled();
+	public function is_disabled(): bool;
 
-	/** @return string */
-	public function get_id();
+	public function get_id(): string;
 
-	/** @bool */
-	public function is_required();
+	public function is_required(): bool;
 
-	/** @return bool */
-	public function has_placeholder();
+	public function has_placeholder(): bool;
 
-	/** @return string */
-	public function get_placeholder();
+	public function get_placeholder(): string;
 
 	/**
 	 * @param string[] $except
 	 *
 	 * @return string[] name->value
 	 */
-	public function get_attributes( $except = [] );
+	public function get_attributes( array $except = [] ): array;
 
 	/**
-	 * @param string $name
-	 * @param string $default
+	 * @param string  $name
+	 * @param ?string $default
 	 *
 	 * @return string
 	 */
-	public function get_attribute( $name, $default = null );
+	public function get_attribute( string $name, $default = null ): string;
 
-	/** @return bool */
-	public function is_attribute_set( $name );
+	public function is_attribute_set( string $name ): bool;
 
-	/**
-	 * @param string $name
-	 *
-	 * @return string
-	 */
-	public function get_meta_value( $name );
+	public function get_meta_value( string $name ): string;
 
-	/** @return bool */
-	public function is_meta_value_set( $name );
+	public function is_meta_value_set( string $name ): bool;
 
-	/**
-	 * @return string
-	 */
-	public function get_classes();
+	public function get_classes(): string;
 
-	/** bool */
-	public function has_classes();
+	public function has_classes(): bool;
 
-	/** @return bool */
-	public function is_class_set( $name );
+	public function is_class_set( string $name ): bool;
 
-	/** bool */
-	public function has_data();
+	public function has_data(): bool;
 
-	/**
-	 * @return array
-	 */
-	public function get_data();
+	/** @return array<string,int> */
+	public function get_data(): array;
 
-	/**
-	 * @param string $data_name
-	 * @param string $data_value
-	 *
-	 * @return $this
-	 */
-	public function add_data( $data_name, $data_value );
+	public function add_data( string $data_name, string $data_value ): self;
 
-	/**
-	 * @param string $data_name
-	 *
-	 * @return $this
-	 */
-	public function unset_data( $data_name );
+	public function unset_data( string $data_name ): self;
 
-	/**
-	 * @return mixed
-	 */
+	/** @return mixed */
 	public function get_possible_values();
 
-	/**
-	 * @return bool
-	 */
-	public function is_multiple();
+	public function is_multiple(): bool;
 
-	/**
-	 * @return Validator
-	 */
-	public function get_validator();
+	public function get_validator(): Validator;
 
-	/**
-	 * @return Sanitizer
-	 */
-	public function get_sanitizer();
+	public function get_sanitizer(): Sanitizer;
 
-	/** @return Serializer */
-	public function get_serializer();
+	public function get_serializer(): Serializer;
 
-	/** @return int */
-	public function get_priority();
+	public function get_priority(): int;
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 54ef3cc..ee7f144 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -4,9 +4,11 @@ namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
 use WPDesk\Forms\Form\FormWithFields;
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer\NoSerialize;
+use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\ChainValidator;
 use WPDesk\Forms\Validator\RequiredValidator;
 
@@ -19,210 +21,165 @@ use WPDesk\Forms\Validator\RequiredValidator;
 abstract class BasicField implements Field {
 	use Field\Traits\HtmlAttributes;
 
-	/** @var array[] */
+	const DEFAULT_PRIORITY = 10;
+
+	/** @var array<string,int,bool> */
 	protected $meta;
 
+	/** @var string */
 	protected $default_value;
 
 	public function __construct() {
-		$this->meta['class'] = [];
-		$this->meta['priority'] = 10;
+		$this->meta['class']    = [];
+		$this->meta['priority'] = self::DEFAULT_PRIORITY;
 	}
 
-	public function get_label() {
+	public function get_label(): string {
 		return $this->meta['label'];
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_label( $value ) {
+	public function set_label( string $value ): self {
 		$this->meta['label'] = $value;
 
 		return $this;
 	}
 
-	public function get_description_tip() {
+	public function get_description_tip(): string {
 		return $this->meta['description_tip'];
 	}
 
-	public function has_description_tip() {
+	public function has_description_tip(): bool {
 		return isset( $this->meta['description_tip'] );
 	}
 
-	public function should_override_form_template() {
-		return isset( $this->attributes['overrite_template'] ) ? $this->attributes['overrite_template'] : false;
+	public function should_override_form_template(): bool {
+		return $this->attributes['overrite_template'] ?? false;
 	}
 
-	public function get_description() {
+	public function get_description(): string {
 		return $this->meta['description'];
 	}
 
-	public function has_label() {
+	public function has_label(): bool {
 		return isset( $this->meta['label'] );
 	}
 
-	public function has_description() {
+	public function has_description(): bool {
 		return isset( $this->meta['description'] );
 	}
 
-	public function set_description( $value ) {
+	public function set_description( string $value ): self {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( $value ) {
+	public function set_description_tip( string $value ): self {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @return array
-	 *
-	 * @deprecated not sure if needed. TODO: Check later.
-	 */
-	public function get_type() {
+	public function get_type(): string {
 		return $this->attributes['type'];
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_placeholder( $value ) {
+	public function set_placeholder( string $value ): self {
 		$this->meta['placeholder'] = $value;
 
 		return $this;
 	}
 
-	public function has_placeholder() {
+	public function has_placeholder(): bool {
 		return isset( $this->meta['placeholder'] );
 	}
 
-	public function get_placeholder() {
+	public function get_placeholder(): string {
 		return $this->meta['placeholder'];
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return $this
-	 */
-	public function set_name( $name ) {
+	public function set_name( string $name ): self {
 		$this->attributes['name'] = $name;
 
 		return $this;
 	}
 
-	public function get_meta_value( $name ) {
+	public function get_meta_value( string $name ): string {
 		return $this->meta[ $name ];
 	}
 
-	public function get_classes() {
+	public function get_classes(): string {
 		return implode( ' ', $this->meta['class'] );
 	}
 
-	public function has_classes() {
+	public function has_classes(): bool {
 		return ! empty( $this->meta['class'] );
 	}
 
-	public function has_data() {
+	public function has_data(): bool {
 		return ! empty( $this->meta['data'] );
 	}
 
-	/**
-	 * @return array
-	 */
-	public function get_data() {
-		return empty( $this->meta['data'] ) ? [] : $this->meta['data'];
+	public function get_data(): array {
+		return $this->meta['data'] ?: [];
 	}
 
 	public function get_possible_values() {
 		return isset( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
 	}
 
-	public function get_id() {
-		return isset( $this->attributes['id'] ) ? $this->attributes['id'] : sanitize_title( $this->get_name() );
+	public function get_id(): string {
+		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
-	public function get_name() {
+	public function get_name(): string {
 		return $this->attributes['name'];
 	}
 
-	public function is_multiple() {
-		return isset( $this->attributes['multiple'] ) ? $this->attributes['multiple'] : false;
+	public function is_multiple(): bool {
+		return $this->attributes['multiple'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_disabled() {
+	public function set_disabled(): self {
 		$this->attributes['disabled'] = true;
 
 		return $this;
 	}
 
-	public function is_disabled() {
-		return isset( $this->attributes['disabled'] ) ? $this->attributes['disabled'] : false;
+	public function is_disabled(): bool {
+		return $this->attributes['disabled'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_readonly() {
+	public function set_readonly(): self {
 		$this->attributes['readonly'] = true;
 
 		return $this;
 	}
 
-	public function is_readonly() {
-		return isset( $this->attributes['readonly'] ) ? $this->attributes['readonly'] : false;
+	public function is_readonly(): bool {
+		return $this->attributes['readonly'] ?? false;
 	}
 
-	/**
-	 * @return $this
-	 */
-	public function set_required() {
+	public function set_required(): self {
 		$this->meta['required'] = true;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $class_name
-	 *
-	 * @return $this
-	 */
-	public function add_class( $class_name ) {
+	public function add_class( string $class_name ): self {
 		$this->meta['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $class_name
-	 *
-	 * @return $this
-	 */
-	public function unset_class( $class_name ) {
+	public function unset_class( string $class_name ): self {
 		unset( $this->meta['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	/**
-	 * @param string $data_name
-	 * @param string $data_value
-	 *
-	 * @return $this
-	 */
-	public function add_data( $data_name, $data_value ) {
-		if ( !isset( $this->meta['data'] ) ) {
+	public function add_data( string $data_name, string $data_value ): self {
+		if ( ! isset( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
 		$this->meta['data'][ $data_name ] = $data_value;
@@ -230,44 +187,31 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	/**
-	 * @param string $data_name
-	 *
-	 * @return $this
-	 */
-	public function unset_data( $data_name ) {
+	public function unset_data( string $data_name ): self {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
 	}
 
-	public function is_meta_value_set( $name ) {
+	public function is_meta_value_set( string $name ): bool {
 		return isset( $this->meta[ $name ] );
 	}
 
-	public function is_class_set( $name ) {
+	public function is_class_set( string $name ): bool {
 		return isset( $this->meta['class'][ $name ] );
 	}
 
-	public function get_default_value() {
+	public function get_default_value(): string {
 		return $this->default_value;
 	}
 
-	/**
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_default_value( $value ) {
+	public function set_default_value( string $value ): self {
 		$this->default_value = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @return ChainValidator
-	 */
-	public function get_validator() {
+	public function get_validator(): Validator {
 		$chain = new ChainValidator();
 		if ( $this->is_required() ) {
 			$chain->attach( new RequiredValidator() );
@@ -276,18 +220,15 @@ abstract class BasicField implements Field {
 		return $chain;
 	}
 
-	public function is_required() {
-		return isset( $this->meta['required'] ) ? $this->meta['required'] : false;
+	public function is_required(): bool {
+		return $this->meta['required'] ?? false;
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new NoSanitize();
 	}
 
-	/**
-	 * @return Serializer
-	 */
-	public function get_serializer() {
+	public function get_serializer(): Serializer {
 		if ( isset( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
 			return $this->meta['serializer'];
 		}
@@ -295,7 +236,7 @@ abstract class BasicField implements Field {
 		return new NoSerialize();
 	}
 
-	public function set_serializer( Serializer $serializer ) {
+	public function set_serializer( Serializer $serializer ): self {
 		$this->meta['serializer'] = $serializer;
 
 		return $this;
diff --git a/src/Field/ButtonField.php b/src/Field/ButtonField.php
index 86312d0..f0a4023 100644
--- a/src/Field/ButtonField.php
+++ b/src/Field/ButtonField.php
@@ -2,14 +2,12 @@
 
 namespace WPDesk\Forms\Field;
 
-class ButtonField extends NoValueField
-{
-    public function get_template_name()
-    {
-        return 'button';
-    }
-    public function get_type()
-    {
-        return 'button';
-    }
+class ButtonField extends NoValueField {
+
+	public function get_template_name(): string {
+		return 'button';
+	}
+	public function get_type(): string {
+		return 'button';
+	}
 }
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index 705c4fe..e8cc29f 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -2,9 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
-
 class CheckboxField extends BasicField {
-	const VALUE_TRUE = 'yes';
+	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
 
 	public function __construct() {
@@ -12,21 +11,21 @@ class CheckboxField extends BasicField {
 		$this->set_attribute( 'type', 'checkbox' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-checkbox';
 	}
 
-	public function get_sublabel() {
+	public function get_sublabel(): string {
 		return $this->meta['sublabel'];
 	}
 
-	public function set_sublabel( $value ) {
+	public function set_sublabel( string $value ): self {
 		$this->meta['sublabel'] = $value;
 
 		return $this;
 	}
 
-	public function has_sublabel() {
+	public function has_sublabel(): bool {
 		return isset( $this->meta['sublabel'] );
 	}
 }
diff --git a/src/Field/DatePickerField.php b/src/Field/DatePickerField.php
index 8b50df8..7060d90 100644
--- a/src/Field/DatePickerField.php
+++ b/src/Field/DatePickerField.php
@@ -2,22 +2,23 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class DatePickerField extends BasicField {
 	public function __construct() {
 		parent::__construct();
 		$this->set_default_value( '' );
-		$this->add_class('date-picker');
-		$this->set_placeholder('YYYY-MM-DD');
+		$this->add_class( 'date-picker' );
+		$this->set_placeholder( 'YYYY-MM-DD' );
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-date-picker';
 	}
 }
diff --git a/src/Field/Header.php b/src/Field/Header.php
index 491d99c..fa86700 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -8,15 +8,15 @@ class Header extends NoValueField {
 		$this->meta['header_size'] = '';
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'header';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 
-	public function set_header_size( $value ) {
+	public function set_header_size( int $value ): self {
 		$this->meta['header_size'] = $value;
 
 		return $this;
diff --git a/src/Field/HiddenField.php b/src/Field/HiddenField.php
index 51b7808..9c3856c 100644
--- a/src/Field/HiddenField.php
+++ b/src/Field/HiddenField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class HiddenField extends BasicField {
@@ -11,11 +12,11 @@ class HiddenField extends BasicField {
 		$this->set_attribute( 'type', 'hidden' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-hidden';
 	}
 }
diff --git a/src/Field/ImageInputField.php b/src/Field/ImageInputField.php
index 95d4bb6..74c8410 100644
--- a/src/Field/ImageInputField.php
+++ b/src/Field/ImageInputField.php
@@ -10,10 +10,7 @@ class ImageInputField extends BasicField {
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-image';
 	}
 }
diff --git a/src/Field/InputNumberField.php b/src/Field/InputNumberField.php
index a563cd2..9ee7405 100644
--- a/src/Field/InputNumberField.php
+++ b/src/Field/InputNumberField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputNumberField extends BasicField {
@@ -11,11 +12,11 @@ class InputNumberField extends BasicField {
 		$this->set_attribute( 'type', 'number' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-number';
 	}
 }
diff --git a/src/Field/InputTextField.php b/src/Field/InputTextField.php
index 2070412..7ca6a96 100644
--- a/src/Field/InputTextField.php
+++ b/src/Field/InputTextField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputTextField extends BasicField {
@@ -11,11 +12,11 @@ class InputTextField extends BasicField {
 		$this->set_attribute( 'type', 'text' );
 	}
 
-	public function get_sanitizer() {
+	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-text';
 	}
 }
diff --git a/src/Field/MultipleInputTextField.php b/src/Field/MultipleInputTextField.php
index fab8398..cf976fe 100644
--- a/src/Field/MultipleInputTextField.php
+++ b/src/Field/MultipleInputTextField.php
@@ -4,10 +4,7 @@ namespace WPDesk\Forms\Field;
 
 class MultipleInputTextField extends InputTextField {
 
-	/**
-	 * @return string
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-text-multiple';
 	}
 }
diff --git a/src/Field/NoOnceField.php b/src/Field/NoOnceField.php
index 0b6eeaf..6419a37 100644
--- a/src/Field/NoOnceField.php
+++ b/src/Field/NoOnceField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\NonceValidator;
 
 class NoOnceField extends BasicField {
@@ -11,11 +12,11 @@ class NoOnceField extends BasicField {
 		$this->meta['action'] = $action_name;
 	}
 
-	public function get_validator() {
+	public function get_validator(): Validator {
 		return new NonceValidator( $this->get_meta_value( 'action' ) );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'noonce';
 	}
 }
diff --git a/src/Field/NoValueField.php b/src/Field/NoValueField.php
index 830f47e..90bbecb 100644
--- a/src/Field/NoValueField.php
+++ b/src/Field/NoValueField.php
@@ -8,7 +8,7 @@ namespace WPDesk\Forms\Field;
  * @package WPDesk\Forms
  */
 abstract class NoValueField extends BasicField {
-	public function get_name() {
+	public function get_name(): string {
 		return '';
 	}
 }
diff --git a/src/Field/Paragraph.php b/src/Field/Paragraph.php
index c62cb6b..6e74de3 100644
--- a/src/Field/Paragraph.php
+++ b/src/Field/Paragraph.php
@@ -3,11 +3,11 @@
 namespace WPDesk\Forms\Field;
 
 class Paragraph extends NoValueField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'paragraph';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 19b14ae..8960304 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -8,7 +8,7 @@ class ProductSelect extends SelectField {
 		$this->set_multiple();
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'product-select';
 	}
 }
diff --git a/src/Field/RadioField.php b/src/Field/RadioField.php
index 69630bf..3e20d1b 100644
--- a/src/Field/RadioField.php
+++ b/src/Field/RadioField.php
@@ -3,7 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class RadioField extends BasicField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-radio';
 	}
 }
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index 0578379..bead3bb 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -4,17 +4,18 @@ namespace WPDesk\Forms\Field;
 
 class SelectField extends BasicField {
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'select';
 	}
 
-	public function set_options( $options ) {
+	/** @param string[] $options */
+	public function set_options( array $options ): self {
 		$this->meta['possible_values'] = $options;
 
 		return $this;
 	}
 
-	public function set_multiple() {
+	public function set_multiple(): self {
 		$this->attributes['multiple'] = true;
 
 		return $this;
diff --git a/src/Field/SubmitField.php b/src/Field/SubmitField.php
index c8e1f79..bcb00f7 100644
--- a/src/Field/SubmitField.php
+++ b/src/Field/SubmitField.php
@@ -3,15 +3,15 @@
 namespace WPDesk\Forms\Field;
 
 class SubmitField extends NoValueField {
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'input-submit';
 	}
 
-	public function get_type() {
+	public function get_type(): string {
 		return 'submit';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/Field/TextAreaField.php b/src/Field/TextAreaField.php
index 94873b3..0f83ffe 100644
--- a/src/Field/TextAreaField.php
+++ b/src/Field/TextAreaField.php
@@ -8,7 +8,7 @@ class TextAreaField extends BasicField {
 		$this->set_default_value( '' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'textarea';
 	}
 }
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index 55b1fb1..8468254 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -3,10 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class TimepickerField extends BasicField {
-	/**
-	 * @inheritDoc
-	 */
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'timepicker';
 	}
 }
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 8116ee9..4e54c85 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -19,51 +19,39 @@ trait HtmlAttributes {
 	 *
 	 * @return string[]
 	 */
-	public function get_attributes( $except = [ 'name', 'type' ] ) {
-		return array_filter( $this->attributes, function ( $value, $key ) use ( $except ) {
-			return ! in_array( $key, $except, true );
-		}, ARRAY_FILTER_USE_BOTH );
+	public function get_attributes( array $except = [ 'name', 'type' ] ): array {
+		return array_filter(
+			$this->attributes,
+			static function ( $value, $key ) use ( $except ) {
+				return ! in_array( $key, $except, true );
+			},
+			ARRAY_FILTER_USE_BOTH
+		);
 	}
 
-	/**
-	 * @param string $name
-	 * @param string $value
-	 *
-	 * @return $this
-	 */
-	public function set_attribute( $name, $value ) {
+	public function set_attribute( string $name, string $value ): self {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return $this
-	 */
-	public function unset_attribute( $name ) {
+	public function unset_attribute( string $name ): self {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
 	}
 
-	/**
-	 * @param string $name
-	 *
-	 * @return bool
-	 */
-	public function is_attribute_set( $name ) {
+	public function is_attribute_set( string $name ): bool {
 		return isset( $this->attributes[ $name ] );
 	}
 
 	/**
-	 * @param string $name
-	 * @param mixed $default
+	 * @param string  $name
+	 * @param ?string $default
 	 *
 	 * @return string
 	 */
-	public function get_attribute( $name, $default = null ) {
+	public function get_attribute( string $name, $default = null ): string {
 		return $this->attributes[ $name ] ?? $default;
 	}
 }
diff --git a/src/Field/WooSelect.php b/src/Field/WooSelect.php
index b8d9538..bc59f9c 100644
--- a/src/Field/WooSelect.php
+++ b/src/Field/WooSelect.php
@@ -9,7 +9,7 @@ class WooSelect extends SelectField {
 		$this->add_class( 'wc-enhanced-select' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'woo-select';
 	}
 }
diff --git a/src/Field/WyswigField.php b/src/Field/WyswigField.php
index 846c919..06db980 100644
--- a/src/Field/WyswigField.php
+++ b/src/Field/WyswigField.php
@@ -8,11 +8,11 @@ class WyswigField extends BasicField {
 		$this->set_default_value( '' );
 	}
 
-	public function get_template_name() {
+	public function get_template_name(): string {
 		return 'wyswig';
 	}
 
-	public function should_override_form_template() {
+	public function should_override_form_template(): bool {
 		return true;
 	}
 }
diff --git a/src/FieldProvider.php b/src/FieldProvider.php
index f7f3841..e693d00 100644
--- a/src/FieldProvider.php
+++ b/src/FieldProvider.php
@@ -11,5 +11,5 @@ interface FieldProvider {
 	 *
 	 * @return Field[]
 	 */
-	public function get_fields();
+	public function get_fields(): array;
 }
diff --git a/src/FieldRenderer.php b/src/FieldRenderer.php
index 37a356d..f60c1b0 100644
--- a/src/FieldRenderer.php
+++ b/src/FieldRenderer.php
@@ -2,16 +2,7 @@
 
 namespace WPDesk\Forms;
 
-/**
- * @class FieldRenderer
- */
 interface FieldRenderer {
-	/**
-	 * @param FieldProvider $provider
-	 * @param array $fields_data
-	 * @param string $name_prefix
-	 *
-	 * @return string|array String or normalized array
-	 */
-	public function render_fields( FieldProvider $provider, array $fields_data, $name_prefix = '' );
+	/** @return string|array String or normalized array */
+	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' );
 }
diff --git a/src/FieldsDataReceiver.php b/src/FieldsDataReceiver.php
index 9e2bdc9..86a1583 100644
--- a/src/FieldsDataReceiver.php
+++ b/src/FieldsDataReceiver.php
@@ -14,8 +14,6 @@ interface FieldsDataReceiver {
 	/**
 	 * Set values corresponding to fields.
 	 *
-	 * @param ContainerInterface $data
-	 *
 	 * @return void
 	 */
 	public function update_fields_data( ContainerInterface $data );
diff --git a/src/Form.php b/src/Form.php
index 7450b2b..8ea2d78 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -12,55 +12,51 @@ use WPDesk\View\Renderer\Renderer;
 interface Form {
 	/**
 	 * For some reason you may want to disable a form. Returns false when disabled.
-	 *
-	 * @return bool
 	 */
-	public function is_active();
+	public function is_active(): bool;
 
 	/**
 	 * Whether form handle_request method was successfully executed.
-	 *
-	 * @return bool
 	 */
-	public function is_submitted();
+	public function is_submitted(): bool;
 
 	/**
 	 * After handle_request or set_data the data in form can be invalid according to field validators.
-	 * Returns false when onle of them says the data is invalid.
-	 *
-	 * @return bool
+	 * Returns false when one of them says the data is invalid.
 	 */
-	public function is_valid();
+	public function is_valid(): bool;
 
 	/**
 	 * Add array to update data.
 	 *
 	 * @param array $request New data to update.
+	 *
+	 * @return void
 	 */
-	public function handle_request( $request = array() );
+	public function handle_request( array $request = [] );
 
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
 	 * @param array $data Data for form.
+	 *
+	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( array $data );
 
 	/**
 	 * Use to render the form to string.
 	 *
 	 * @param Renderer $renderer Renderer to render form fields and form-templates.
-	 *
-	 * @return string
 	 */
-	public function render_form( Renderer $renderer );
+	public function render_form( Renderer $renderer ): string;
 
 	/**
 	 * Get data from form. Use after handle_request or set_data.
 	 *
-	 * @return array
+	 * @return array<int,string>
 	 */
-	public function get_data();
+	public function get_data(): array;
 
 	/**
 	 * Get data from form. Use after handle_request or set_data.
@@ -68,13 +64,11 @@ interface Form {
 	 *
 	 * @return array
 	 */
-	public function get_normalized_data();
+	public function get_normalized_data(): array;
 
 	/**
 	 * Form if you ever need to have more than one form at once.
-	 *
-	 * @return string
 	 */
-	public function get_form_id();
+	public function get_form_id(): int;
 }
 
diff --git a/src/Form/AbstractForm.php b/src/Form/AbstractForm.php
deleted file mode 100644
index b51a0e3..0000000
--- a/src/Form/AbstractForm.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Form;
-
-
-/**
- * Old abstraction layer for forms.
- *
- * @package WPDesk\Forms
- *
- * @deprecated Use ony for backward compatibility with Forms 1.x
- */
-abstract class AbstractForm {
-
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
-	protected $form_id = 'form';
-
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
-	protected $updated_data = array();
-
-
-	/**
-	 * Checks if form should be active.
-	 *
-	 * @return bool
-	 */
-	public function is_active() {
-		return true;
-	}
-
-	/**
-	 * Create form data and return an associative array.
-	 *
-	 * @return array
-	 */
-	abstract protected function create_form_data();
-
-	/**
-	 * Add array to update data.
-	 *
-	 * @param array $new_data new data to update.
-	 */
-	public function update_form_data( array $new_data = array() ) {
-		$this->updated_data = $new_data;
-	}
-
-	/**
-	 * Merge created and updated data and return associative array. Add to all keys form prefix.
-	 *
-	 * @return array
-	 */
-	public function get_form_data() {
-		return array_merge(
-			$this->create_form_data(),
-			$this->updated_data
-		);
-	}
-
-	/**
-	 * Get prefixed array returns array with prefixed form_id
-	 *
-	 * @return array
-	 */
-	public function get_prefixed_form_data() {
-		$array   = $this->get_form_data();
-		$form_id = $this->get_form_id();
-
-		return array_combine(
-			array_map( function ( $k ) use ( $form_id ) {
-				return $form_id . '_' . $k;
-			}, array_keys( $array ) ),
-			$array
-		);
-	}
-
-	/**
-	 * return form Id
-	 *
-	 * @return string
-	 */
-	public function get_form_id() {
-		return $this->form_id;
-	}
-
-}
-
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index a5a494c..45dc515 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -15,91 +15,58 @@ use WPDesk\View\Renderer\Renderer;
 class FormWithFields implements Form, ContainerForm, FieldProvider {
 	use Field\Traits\HtmlAttributes;
 
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
+	/** @var string Unique form_id. */
 	protected $form_id = 'form';
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
+
+	/** @var array Updated data. */
 	private $updated_data;
-	/**
-	 * Form fields.
-	 *
-	 * @var Field[]
-	 */
+
+	/** @var Field[] Form fields. */
 	private $fields;
 
 	/**
 	 * FormWithFields constructor.
 	 *
-	 * @param array $fields Form fields.
-	 * @param string $form_id Unique form id.
+	 * @param Field[]  $fields
+	 * @param string $form_id
 	 */
-	public function __construct( array $fields, $form_id = 'form' ) {
-		$this->fields       = $fields;
-		$this->form_id      = $form_id;
-		$this->updated_data = null;
+	public function __construct( array $fields, string $form_id = 'form' ) {
+		$this->fields  = $fields;
+		$this->form_id = $form_id;
 	}
 
-	/**
-	 * Set Form action attribute.
-	 *
-	 * @param string $action
-	 */
-	public function set_action( $action ) {
+	/** Set Form action attribute. */
+	public function set_action( string $action ): self {
 		$this->attributes['action'] = $action;
 
 		return $this;
 	}
 
-	/**
-	 * Set Form method attribute ie. GET/POST.
-	 *
-	 * @param string $method
-	 */
-	public function set_method( $method ) {
+	/** Set Form method attribute ie. GET/POST. */
+	public function set_method( string $method ): self {
 		$this->attributes['method'] = $method;
 
 		return $this;
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_method() {
-		return isset( $this->attributes['method'] ) ? $this->attributes['method'] : 'POST';
+	public function get_method(): string {
+		return $this->attributes['method'] ?? 'POST';
 	}
 
-	/**
-	 * @return string
-	 */
-	public function get_action() {
-		return isset( $this->attributes['action'] ) ? $this->attributes['action'] : '';
+	public function get_action(): string {
+		return $this->attributes['action'] ?? '';
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_submitted() {
+	public function is_submitted(): bool {
 		return null !== $this->updated_data;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
+	/** @return void */
 	public function add_field( Field $field ) {
 		$this->fields[] = $field;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_active() {
+	public function is_active(): bool {
 		return true;
 	}
 
@@ -107,17 +74,16 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 * Add more fields to form.
 	 *
 	 * @param Field[] $fields Field to add to form.
+	 *
+	 * @return void
 	 */
 	public function add_fields( array $fields ) {
 		array_map( [ $this, 'add_field' ], $fields );
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function is_valid() {
+	public function is_valid(): bool {
 		foreach ( $this->fields as $field ) {
-			$field_value     = isset( $this->updated_data[ $field->get_name() ] ) ? $this->updated_data[ $field->get_name() ] : $field->get_default_value();
+			$field_value     = $this->updated_data[ $field->get_name() ] ?? $field->get_default_value();
 			$field_validator = $field->get_validator();
 			if ( ! $field_validator->is_valid( $field_value ) ) {
 				return false;
@@ -132,7 +98,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	 *
 	 * @param array|ContainerInterface $request new data to update.
 	 */
-	public function handle_request( $request = array() ) {
+	public function handle_request( array $request = [] ) {
 		if ( $this->updated_data === null ) {
 			$this->updated_data = [];
 		}
@@ -165,48 +131,41 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		}
 	}
 
-	/**
-	 * Renders only fields without form.
-	 *
-	 * @param Renderer $renderer
-	 *
-	 * @return string
-	 */
-	public function render_fields( Renderer $renderer ) {
+	/** Renders only fields without form. */
+	public function render_fields( Renderer $renderer ): string {
 		$content     = '';
 		$fields_data = $this->get_data();
 		foreach ( $this->get_fields() as $field ) {
-			$content .= $renderer->render( $field->should_override_form_template() ? $field->get_template_name() : 'form-field',
+			$content .= $renderer->render(
+				$field->should_override_form_template() ? $field->get_template_name() : 'form-field',
 				[
 					'field'         => $field,
 					'renderer'      => $renderer,
 					'name_prefix'   => $this->get_form_id(),
-					'value'         => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
+					'value'         => $fields_data[ $field->get_name() ] ?? $field->get_default_value(),
 					'template_name' => $field->get_template_name(),
-				] );
+				]
+			);
 		}
 
 		return $content;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function render_form( Renderer $renderer ) {
-		$content = $renderer->render( 'form-start', [
-			'form'   => $this,
-			'method' => $this->get_method(), // backward compat
-			'action' => $this->get_action(),  // backward compat
-		] );
+	public function render_form( Renderer $renderer ): string {
+		$content  = $renderer->render(
+			'form-start',
+			[
+				'form'   => $this,
+				'method' => $this->get_method(), // backward compat.
+				'action' => $this->get_action(),  // backward compat.
+			]
+		);
 		$content .= $this->render_fields( $renderer );
 		$content .= $renderer->render( 'form-end' );
 
 		return $content;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public function put_data( PersistentContainer $container ) {
 		foreach ( $this->get_fields() as $field ) {
 			$data_key = $field->get_name();
@@ -223,10 +182,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		}
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_data() {
+	public function get_data(): array {
 		$data = $this->updated_data;
 
 		foreach ( $this->get_fields() as $field ) {
@@ -239,10 +195,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $data;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_fields() {
+	public function get_fields(): array {
 		$fields = $this->fields;
 
 		usort(
@@ -255,17 +208,11 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $fields;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_form_id() {
+	public function get_form_id(): int {
 		return $this->form_id;
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	public function get_normalized_data() {
+	public function get_normalized_data(): array {
 		return $this->get_data();
 	}
 }
diff --git a/src/Form/FormsCollection.php b/src/Form/FormsCollection.php
deleted file mode 100644
index f2603a3..0000000
--- a/src/Form/FormsCollection.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Form;
-
-use WPDesk\Forms\Form;
-
-/**
- * FormsCollection class store AbstractForm instances and merges forms data from all collections
- *
- * @deprecated Use ony for backward compatibility with Forms 1.x
- *
- * @package WPDesk\Forms
- */
-class FormsCollection {
-	/**
-	 * AbstractForm array collection.
-	 *
-	 * @var Form[]
-	 */
-	protected $forms = array();
-
-	/**
-	 * Unique form_id.
-	 *
-	 * @var string
-	 */
-	protected $form_id = 'form';
-
-	/**
-	 * Updated data.
-	 *
-	 * @var array
-	 */
-	protected $updated_data = array();
-
-	/**
-	 * Add forms. All keys in this array must be unique, otherwise add_form will throw exception.
-	 *
-	 * @param Form[] $forms
-	 */
-	public function add_forms( array $forms = array() ) {
-		foreach ( $forms as $form_object ) {
-			$this->add_form( $form_object );
-		}
-	}
-
-	/**
-	 * Add form. If key is not unique throw exception.
-	 *
-	 * @param Form $form
-	 *
-	 * @throws \OutOfBoundsException
-	 */
-	public function add_form( AbstractForm $form ) {
-		if ( ! $this->is_form_exists( $form->get_form_id() ) ) {
-			$this->forms[ $form->get_form_id() ] = $form;
-		} else {
-			throw new \OutOfBoundsException( 'Form with this key already exists' );
-		}
-	}
-
-	/**
-	 * Is form exists. Checks if key exists in the array of forms and return bool.
-	 *
-	 * @param string $form_id
-	 *
-	 * @return bool
-	 */
-	public function is_form_exists( $form_id ) {
-		return isset( $this->forms[ (string) $form_id ] );
-	}
-
-	/**
-	 * Get form.
-	 *
-	 * @param string $form_id
-	 *
-	 * @return Form
-	 * @throws \OutOfRangeException
-	 */
-	public function get_form( $form_id ) {
-		if ( $this->is_form_exists( $form_id ) ) {
-			return $this->forms[ (string) $form_id ];
-		}
-
-		throw new \OutOfRangeException( 'Form with this key not exists' );
-	}
-
-	/**
-	 * Get forms data. This method merge all arrays from forms and return associative array for woocommerce form_fields.
-	 *
-	 * @param bool $prefixed if true add form_id as prefix to form keys
-	 *
-	 * @return array
-	 */
-	public function get_forms_data( $prefixed = false ) {
-
-		$forms_data = array();
-
-		foreach ( $this->forms as $form ) {
-			if ( ! $form->is_active() ) {
-				continue;
-			}
-
-			if ( $prefixed ) {
-				$forms_data = array_merge( $forms_data, $form->get_prefixed_form_data() );
-			} else {
-				$forms_data = array_merge( $forms_data, $form->get_form_data() );
-			}
-		}
-
-		return $forms_data;
-	}
-
-}
diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php
index 092a01a..02f2d4f 100644
--- a/src/Persistence/FieldPersistenceStrategy.php
+++ b/src/Persistence/FieldPersistenceStrategy.php
@@ -12,6 +12,7 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 class FieldPersistenceStrategy {
+
 	/** @var PersistentContainer */
 	private $persistence;
 
@@ -21,9 +22,6 @@ class FieldPersistenceStrategy {
 
 	/**
 	 * Save fields data.
-	 *
-	 * @param FieldProvider $fields_provider
-	 * @param array $data
 	 */
 	public function persist_fields( FieldProvider $fields_provider, array $data ) {
 		foreach ( $fields_provider->get_fields() as $field ) {
@@ -34,10 +32,8 @@ class FieldPersistenceStrategy {
 
 	/**
 	 * Load fields data.
-	 *
-	 * @return array
 	 */
-	public function load_fields( FieldProvider $fields_provider ) {
+	public function load_fields( FieldProvider $fields_provider ): array {
 		$data = [];
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
@@ -45,7 +41,7 @@ class FieldPersistenceStrategy {
 				$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
 			} catch ( NotFoundExceptionInterface $not_found ) {
 				// TODO: Logger
-//				LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
+				// LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
 			}
 		}
 
diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 4d078ac..371490c 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -18,7 +18,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 	 *
 	 * @return array Normalized fields with data.
 	 */
-	public function render_fields( FieldProvider $provider, array $fields_data, $name_prefix = '' ) {
+	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' ): array {
 		$rendered_fields = [];
 		foreach ( $provider->get_fields() as $field ) {
 			$rendered = [
@@ -29,7 +29,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				'readonly' => $field->is_readonly(),
 				'required' => $field->is_required(),
 				'prefix'   => $name_prefix,
-				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value()
+				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
 			];
 
 			if ( $field->has_classes() ) {
@@ -52,7 +52,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				$rendered['options'] = $options;
 			}
 			if ( $field->has_data() ) {
-				$data = $field->get_data();
+				$data             = $field->get_data();
 				$rendered['data'] = [];
 				foreach ( $data as $data_name => $data_value ) {
 					$rendered['data'][] = [
@@ -61,7 +61,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 					];
 				}
 			}
-			if (json_encode($rendered) !== false) {
+			if ( json_encode( $rendered ) !== false ) {
 				$rendered_fields[] = $rendered;
 			}
 		}
diff --git a/src/Resolver/DefaultFormFieldResolver.php b/src/Resolver/DefaultFormFieldResolver.php
index 3609a69..b5c1675 100644
--- a/src/Resolver/DefaultFormFieldResolver.php
+++ b/src/Resolver/DefaultFormFieldResolver.php
@@ -12,6 +12,7 @@ use WPDesk\View\Resolver\Resolver;
  * @package WPDesk\Forms\Resolver
  */
 class DefaultFormFieldResolver implements Resolver {
+
 	/** @var Resolver */
 	private $dir_resolver;
 
@@ -19,8 +20,8 @@ class DefaultFormFieldResolver implements Resolver {
 		$this->dir_resolver = new DirResolver( __DIR__ . '/../../templates' );
 	}
 
-	public function resolve( $name, Renderer $renderer = null ) {
+	public function resolve( $name, Renderer $renderer = null ): string {
 		return $this->dir_resolver->resolve( $name, $renderer );
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/Sanitizer.php b/src/Sanitizer.php
index a7883dc..bc8f207 100644
--- a/src/Sanitizer.php
+++ b/src/Sanitizer.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms;
 
 interface Sanitizer {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return string
-	 */
-	public function sanitize( $value );
+	/** @param mixed $value */
+	public function sanitize( $value ): string;
 }
diff --git a/src/Sanitizer/CallableSanitizer.php b/src/Sanitizer/CallableSanitizer.php
index c0a28b9..da916ab 100644
--- a/src/Sanitizer/CallableSanitizer.php
+++ b/src/Sanitizer/CallableSanitizer.php
@@ -5,13 +5,15 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class CallableSanitizer implements Sanitizer {
+
+	/** @var callable */
 	private $callable;
 
-	public function __construct( $callable ) {
+	public function __construct( callable $callable ) {
 		$this->callable = $callable;
 	}
 
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return call_user_func( $this->callable, $value );
 	}
 
diff --git a/src/Sanitizer/NoSanitize.php b/src/Sanitizer/NoSanitize.php
index a3fe4a6..21bce01 100644
--- a/src/Sanitizer/NoSanitize.php
+++ b/src/Sanitizer/NoSanitize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class NoSanitize implements Sanitizer {
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return $value;
 	}
 
diff --git a/src/Sanitizer/TextFieldSanitizer.php b/src/Sanitizer/TextFieldSanitizer.php
index 0a1bbcb..325c652 100644
--- a/src/Sanitizer/TextFieldSanitizer.php
+++ b/src/Sanitizer/TextFieldSanitizer.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class TextFieldSanitizer implements Sanitizer {
-	public function sanitize( $value ) {
+	public function sanitize( $value ): string {
 		return sanitize_text_field( $value );
 	}
 
diff --git a/src/Serializer.php b/src/Serializer.php
index 9105400..8302325 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -3,7 +3,17 @@
 namespace WPDesk\Forms;
 
 interface Serializer {
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
 	public function serialize( $value );
 
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
 	public function unserialize( $value );
 }
diff --git a/src/Serializer/JsonSerializer.php b/src/Serializer/JsonSerializer.php
index d7e5ca0..bc8c0e0 100644
--- a/src/Serializer/JsonSerializer.php
+++ b/src/Serializer/JsonSerializer.php
@@ -5,8 +5,8 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class JsonSerializer implements Serializer {
-	public function serialize( $value ) {
-		return json_encode( $value );
+	public function serialize( $value ): string {
+		return (string) json_encode( $value );
 	}
 
 	public function unserialize( $value ) {
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index b29e88b..31a09e1 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		return $value;
 	}
 
diff --git a/src/Serializer/ProductSelectSerializer.php b/src/Serializer/ProductSelectSerializer.php
index 2adf327..e801d4d 100644
--- a/src/Serializer/ProductSelectSerializer.php
+++ b/src/Serializer/ProductSelectSerializer.php
@@ -10,9 +10,6 @@ use WPDesk\Forms\Serializer;
  * @package WPDesk\Forms\Serializer
  */
 class ProductSelectSerializer implements Serializer {
-	/**
-	 * @param $value
-	 */
 	public function serialize( $value ) {
 		$products_with_names = [];
 		if ( is_array( $value ) ) {
diff --git a/src/Validator.php b/src/Validator.php
index d953702..2281820 100644
--- a/src/Validator.php
+++ b/src/Validator.php
@@ -3,15 +3,9 @@
 namespace WPDesk\Forms;
 
 interface Validator {
-	/**
-	 * @param mixed $value
-	 *
-	 * @return bool
-	 */
-	public function is_valid( $value );
+	/** @param mixed $value */
+	public function is_valid( $value ): bool;
 
-	/**
-	 * @return string[]
-	 */
-	public function get_messages();
+	/** @return string[] */
+	public function get_messages(): array;
 }
diff --git a/src/Validator/ChainValidator.php b/src/Validator/ChainValidator.php
index d3549d5..341abee 100644
--- a/src/Validator/ChainValidator.php
+++ b/src/Validator/ChainValidator.php
@@ -5,9 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class ChainValidator implements Validator {
+
 	/** @var Validator[] */
 	private $validators;
 
+	/** @var array */
 	private $messages;
 
 	public function __construct() {
@@ -20,13 +22,13 @@ class ChainValidator implements Validator {
 	 *
 	 * @return $this
 	 */
-	public function attach( Validator $validator ) {
+	public function attach( Validator $validator ): self {
 		$this->validators[] = $validator;
 
 		return $this;
 	}
 
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		$result   = true;
 		$messages = [ [] ];
 		foreach ( $this->validators as $validator ) {
@@ -40,7 +42,7 @@ class ChainValidator implements Validator {
 		return $result;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return $this->messages;
 	}
 
diff --git a/src/Validator/NoValidateValidator.php b/src/Validator/NoValidateValidator.php
index dbc9966..04cf59c 100644
--- a/src/Validator/NoValidateValidator.php
+++ b/src/Validator/NoValidateValidator.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class NoValidateValidator implements Validator {
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		return true;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/src/Validator/NonceValidator.php b/src/Validator/NonceValidator.php
index 8768225..8709af6 100644
--- a/src/Validator/NonceValidator.php
+++ b/src/Validator/NonceValidator.php
@@ -5,19 +5,18 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class NonceValidator implements Validator {
+
 	private $action;
 
 	public function __construct( $action ) {
 		$this->action = $action;
 	}
 
-	public function is_valid( $value ) {
-		$valid = wp_verify_nonce( $value, $this->action );
-
-		return $valid;
+	public function is_valid( $value ): bool {
+		return wp_verify_nonce( $value, $this->action );
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/src/Validator/RequiredValidator.php b/src/Validator/RequiredValidator.php
index 016d803..4e78faf 100644
--- a/src/Validator/RequiredValidator.php
+++ b/src/Validator/RequiredValidator.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class RequiredValidator implements Validator {
-	public function is_valid( $value ) {
+	public function is_valid( $value ): bool {
 		return $value !== null;
 	}
 
-	public function get_messages() {
+	public function get_messages(): array {
 		return [];
 	}
 
diff --git a/templates/button.php b/templates/button.php
index 43c2119..c558c6e 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -6,26 +6,31 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
+
 ?>
 
 <button
-<?php if ($field->has_classes()): ?>
-	class="<?php echo \esc_attr($field->get_classes()); ?>"
+<?php if ( $field->has_classes() ) : ?>
+	class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 <?php endif; ?>
 
-<?php foreach ($field->get_attributes([]) as $key => $val): ?>
-	<?php echo $key.'="'.\esc_attr($val).'"'; ?>
+<?php foreach ( $field->get_attributes( [] ) as $key => $val ) : ?>
+	<?php echo $key . '="' . \esc_attr( $val ) . '"'; ?>
 <?php endforeach; ?>
 
-	type="<?php echo \esc_attr($field->get_type()); ?>"
-	name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).']'?>"
-	id="<?php echo \esc_attr($field->get_id()); ?>"
-	value="<?php echo \esc_html($value); ?>"
+	type="<?php echo \esc_attr( $field->get_type() ); ?>"
+	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
+	value="<?php echo \esc_html( $value ); ?>"
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
 
-><?php echo \esc_html($field->get_label()); ?></button>
+><?php echo \esc_html( $field->get_label() ); ?></button>
diff --git a/templates/form-field.php b/templates/form-field.php
index 971e53b..50f5678 100644
--- a/templates/form-field.php
+++ b/templates/form-field.php
@@ -6,24 +6,28 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 
 <tr valign="top">
-	<?php if ( $field->has_label() ): ?>
+	<?php if ( $field->has_label() ) : ?>
 		<?php echo $renderer->render( 'form-label', [ 'field' => $field ] ); ?>
 	<?php endif; ?>
 
 	<td class="forminp">
-		<?php echo $renderer->render( $template_name, [
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		] ); ?>
+		<?php
+		echo $renderer->render(
+			$template_name,
+			[
+				'field'       => $field,
+				'renderer'    => $renderer,
+				'name_prefix' => $name_prefix,
+				'value'       => $value,
+			]
+		);
+		?>
 
-		<?php if ( $field->has_description() ): ?>
+		<?php if ( $field->has_description() ) : ?>
 			<p class="description"><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		<?php endif; ?>
 	</td>
diff --git a/templates/form-label.php b/templates/form-label.php
index 703ed78..f6268a5 100644
--- a/templates/form-label.php
+++ b/templates/form-label.php
@@ -7,8 +7,8 @@
 ?>
 <th class="titledesc" scope="row">
 	<label for="<?php echo esc_attr( $field->get_id() ); ?>"><?php echo esc_html( $field->get_label() ); ?>
-		<?php if ( $field->has_description_tip() ): ?>
-			<?php echo wc_help_tip($field->get_description_tip()); ?>
+		<?php if ( $field->has_description_tip() ) : ?>
+			<?php echo wc_help_tip( $field->get_description_tip() ); ?>
 		<?php endif ?>
 	</label>
 </th>
diff --git a/templates/form-start.php b/templates/form-start.php
index 10d7686..e3d4bbe 100644
--- a/templates/form-start.php
+++ b/templates/form-start.php
@@ -3,7 +3,7 @@
  * @var \WPDesk\Forms\Form\FormWithFields $form
  */
 ?>
-<form class="wrap woocommerce" method="<?php echo esc_attr($form->get_method()); ?>" action="<?php echo esc_attr($form->get_action()); ?>">
+<form class="wrap woocommerce" method="<?php echo esc_attr( $form->get_method() ); ?>" action="<?php echo esc_attr( $form->get_action() ); ?>">
 	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js ?>
 
 	<table class="form-table">
diff --git a/templates/header.php b/templates/header.php
index db07896..07a9a6e 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -9,10 +9,10 @@ $header_size = (int) $field->get_meta_value( 'header_size' ) ?: 2;
 $classes     = $field->has_classes() ? 'class="' . esc_attr( $field->get_classes() ) . '"' : '';
 ?>
 
-<?php if ( $field->has_label() ): ?>
+<?php if ( $field->has_label() ) : ?>
 	<h<?php echo $header_size; ?> <?php echo $classes; ?>><?php echo esc_html( $field->get_label() ); ?></h<?php echo $header_size; ?>>
 <?php endif; ?>
 
-<?php if ( $field->has_description() ): ?>
+<?php if ( $field->has_description() ) : ?>
 	<p <?php echo $classes; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 <?php endif; ?>
diff --git a/templates/input-checkbox.php b/templates/input-checkbox.php
index 61dc39f..d69ecec 100644
--- a/templates/input-checkbox.php
+++ b/templates/input-checkbox.php
@@ -6,13 +6,17 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
+
 ?>
 
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-date-picker.php b/templates/input-date-picker.php
index 7dea702..0c5b70c 100644
--- a/templates/input-date-picker.php
+++ b/templates/input-date-picker.php
@@ -7,6 +7,13 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
-echo $renderer->render('input', ['field' => $field, 'renderer' => $renderer, 'name_prefix' => $name_prefix, 'value' => $value]);
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-hidden.php b/templates/input-hidden.php
index 3effbd2..300944e 100644
--- a/templates/input-hidden.php
+++ b/templates/input-hidden.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-image.php b/templates/input-image.php
index 34d1388..af9f792 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -8,10 +8,10 @@
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
 <div class="media-input-wrapper" id="<?php echo $media_container_id; ?>">
-    <input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
-           name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
-           id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
-    <div class="custom-img-container">
+	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
+		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
+	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
             <img src="<?php echo \esc_html( $value ) ?>" alt="" width="100"/>
 		<?php endif; ?>
diff --git a/templates/input-number.php b/templates/input-number.php
index 7dea702..0c5b70c 100644
--- a/templates/input-number.php
+++ b/templates/input-number.php
@@ -7,6 +7,13 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
-echo $renderer->render('input', ['field' => $field, 'renderer' => $renderer, 'name_prefix' => $name_prefix, 'value' => $value]);
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-radio.php b/templates/input-radio.php
index 3effbd2..300944e 100644
--- a/templates/input-radio.php
+++ b/templates/input-radio.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input-submit.php b/templates/input-submit.php
index 5f67645..5c11fc8 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -6,7 +6,6 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 
@@ -14,17 +13,29 @@
 	<td style="padding-left:0;">
 		<p class="submit">
 			<input
-				<?php if ( $field->has_classes() ): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-				<?php foreach ( $field->get_attributes( [] ) as $key => $value ): ?>
-					<?php echo $key ?>="<?php echo esc_attr( $value ); ?>"
+				<?php
+				if ( $field->has_classes() ) :
+					?>
+					class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+				<?php foreach ( $field->get_attributes( [] ) as $key => $value ) : ?>
+					<?php echo $key; ?>="<?php echo esc_attr( $value ); ?>"
 				<?php endforeach; ?>
 				type="<?php echo esc_attr( $field->get_type() ); ?>"
 				name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
 				id="<?php echo esc_attr( $field->get_id() ); ?>"
 				value="<?php echo esc_html( $field->get_label() ); ?>"
-				<?php if ( $field->is_required() ): ?>required="required"<?php endif; ?>
-				<?php if ( $field->is_disabled() ): ?>disabled="disabled"<?php endif; ?>
-				<?php if ( $field->is_readonly() ): ?>readonly="readonly"<?php endif; ?>
+				<?php
+				if ( $field->is_required() ) :
+					?>
+					required="required"<?php endif; ?>
+				<?php
+				if ( $field->is_disabled() ) :
+					?>
+					disabled="disabled"<?php endif; ?>
+				<?php
+				if ( $field->is_readonly() ) :
+					?>
+					readonly="readonly"<?php endif; ?>
 			/>
 		</p>
 	</td>
diff --git a/templates/input-text-multiple.php b/templates/input-text-multiple.php
index 7d3fff8..f278729 100644
--- a/templates/input-text-multiple.php
+++ b/templates/input-text-multiple.php
@@ -6,49 +6,62 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
 <?php
-if( empty( $value ) || is_string( $value ) ) {
+if ( empty( $value ) || is_string( $value ) ) {
 	$input_values[] = '';
 } else {
 	$input_values = $value;
 }
 ?>
 <div class="clone-element-container">
-<?php foreach( $input_values as $text_value ): ?>
-<?php if (!\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-	<input type="hidden" name="<?php echo $name_prefix.'['.$field->get_name().']'; ?>" value="no"/>
+<?php foreach ( $input_values as $text_value ) : ?>
+	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
 <?php endif; ?>
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?><label><?php endif; ?>
+	<?php
+	if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
+		?>
+		<label><?php endif; ?>
 	<div class="clone-wrapper">
 	<input
-		type="<?php echo \esc_attr($field->get_type()); ?>"
-		name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).'][]'; ?>"
-		id="<?php echo \esc_attr($field->get_id()); ?>"
+		type="<?php echo \esc_attr( $field->get_type() ); ?>"
+		name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . '][]'; ?>"
+		id="<?php echo \esc_attr( $field->get_id() ); ?>"
 
-		<?php if ($field->has_classes()): ?>
-			class="<?php echo \esc_attr($field->get_classes()); ?>"
+		<?php if ( $field->has_classes() ) : ?>
+			class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 		<?php endif; ?>
 
-		<?php if ($field->get_type() === 'text' && $field->has_placeholder()):?>
-			placeholder="<?php echo \esc_html($field->get_placeholder());?>"
+		<?php if ( $field->get_type() === 'text' && $field->has_placeholder() ) : ?>
+			placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"
 		<?php endif; ?>
 
-		<?php foreach ($field->get_attributes() as $key => $atr_val):
-			echo $key.'="'.\esc_attr($atr_val).'"'; ?>
+		<?php
+		foreach ( $field->get_attributes() as $key => $atr_val ) :
+			echo $key . '="' . \esc_attr( $atr_val ) . '"';
+			?>
 		<?php endforeach; ?>
 
-		<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-		<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-		<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-		<?php if (\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-			value="<?php echo \esc_html($text_value); ?>"
-		<?php else: ?>
+		<?php
+		if ( $field->is_required() ) :
+			?>
+			required="required"<?php endif; ?>
+		<?php
+		if ( $field->is_disabled() ) :
+			?>
+			disabled="disabled"<?php endif; ?>
+		<?php
+		if ( $field->is_readonly() ) :
+			?>
+			readonly="readonly"<?php endif; ?>
+		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+			value="<?php echo \esc_html( $text_value ); ?>"
+		<?php else : ?>
 			value="yes"
-			<?php if ($value === 'yes'): ?>
+			<?php if ( $value === 'yes' ) : ?>
 				checked="checked"
 			<?php endif; ?>
 		<?php endif; ?>
@@ -57,25 +70,25 @@ if( empty( $value ) || is_string( $value ) ) {
 		<span class="remove-field hidden"><span class="dashicons dashicons-remove"></span></span>
 	</div>
 
-	<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?>
-	<?php echo \esc_html($field->get_sublabel()); ?></label>
+	<?php if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) : ?>
+		<?php echo \esc_html( $field->get_sublabel() ); ?></label>
 <?php endif; ?>
 <?php endforeach; ?>
 </div>
 <style>
-    .clone-element-container .clone-wrapper .add-field {
-        display: none;
-    }
-    .clone-element-container .clone-wrapper:first-child .add-field {
-        display: inline-block;
-    }
+	.clone-element-container .clone-wrapper .add-field {
+		display: none;
+	}
+	.clone-element-container .clone-wrapper:first-child .add-field {
+		display: inline-block;
+	}
 
-    .clone-element-container .clone-wrapper .remove-field {
-        display: inline-block;
-    }
-    .clone-element-container .clone-wrapper:first-child .remove-field {
-        display: none;
-    }
+	.clone-element-container .clone-wrapper .remove-field {
+		display: inline-block;
+	}
+	.clone-element-container .clone-wrapper:first-child .remove-field {
+		display: none;
+	}
 </style>
 <script>
 	jQuery( function ( $ ) {
diff --git a/templates/input-text.php b/templates/input-text.php
index 3effbd2..300944e 100644
--- a/templates/input-text.php
+++ b/templates/input-text.php
@@ -6,12 +6,15 @@
  * @var string $value
  *
  * @var string $template_name Real field template.
- *
  */
 ?>
-<?php echo $renderer->render('input', [
-	'field' => $field,
-	'renderer' => $renderer,
-	'name_prefix' => $name_prefix,
-	'value' => $value,
-]); ?>
+<?php
+echo $renderer->render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
+);
diff --git a/templates/input.php b/templates/input.php
index b02e5ea..83448ea 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -7,42 +7,56 @@
  */
 ?>
 
-<?php if (!\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-	<input type="hidden" name="<?php echo $name_prefix.'['.$field->get_name().']'; ?>" value="no"/>
+<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
 <?php endif; ?>
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?><label><?php endif; ?>
+<?php
+if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
+	?>
+	<label><?php endif; ?>
 
 <input
-	type="<?php echo \esc_attr($field->get_type()); ?>"
-	name="<?php echo \esc_attr($name_prefix).'['.\esc_attr($field->get_name()).']'; ?>"
-	id="<?php echo \esc_attr($field->get_id()); ?>"
+	type="<?php echo \esc_attr( $field->get_type() ); ?>"
+	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 
-	<?php if ($field->has_classes()): ?>
-		class="<?php echo \esc_attr($field->get_classes()); ?>"
+	<?php if ( $field->has_classes() ) : ?>
+		class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 	<?php endif; ?>
 
-	<?php if ($field->get_type() === 'text' && $field->has_placeholder()):?>
-		placeholder="<?php echo \esc_html($field->get_placeholder());?>"
+	<?php if ( $field->get_type() === 'text' && $field->has_placeholder() ) : ?>
+		placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"
 	<?php endif; ?>
 
-	<?php foreach ($field->get_attributes() as $key => $atr_val):
-        echo $key.'="'.\esc_attr($atr_val).'"'; ?>
+	<?php
+	foreach ( $field->get_attributes() as $key => $atr_val ) :
+		echo $key . '="' . \esc_attr( $atr_val ) . '"';
+		?>
 	<?php endforeach; ?>
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-	<?php if (\in_array($field->get_type(), ['number', 'text', 'hidden'])): ?>
-		value="<?php echo \esc_html($value); ?>"
-	<?php else: ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+		value="<?php echo \esc_html( $value ); ?>"
+	<?php else : ?>
 		value="yes"
-		<?php if ($value === 'yes'): ?>
+		<?php if ( $value === 'yes' ) : ?>
 			checked="checked"
 		<?php endif; ?>
 	<?php endif; ?>
 />
 
-<?php if ($field->get_type() === 'checkbox' && $field->has_sublabel()): ?>
-	<?php echo \esc_html($field->get_sublabel()); ?></label>
+<?php if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) : ?>
+	<?php echo \esc_html( $field->get_sublabel() ); ?></label>
 <?php endif; ?>
diff --git a/templates/noonce.php b/templates/noonce.php
index 0cd58a5..edc9522 100644
--- a/templates/noonce.php
+++ b/templates/noonce.php
@@ -1,8 +1,8 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string $value
  */
-\wp_nonce_field($field->get_meta_value('action'), $name_prefix .'['. $field->get_name().']');
+
+\wp_nonce_field( $field->get_meta_value( 'action' ), $name_prefix . '[' . $field->get_name() . ']' );
diff --git a/templates/paragraph.php b/templates/paragraph.php
index 184e394..9d29015 100644
--- a/templates/paragraph.php
+++ b/templates/paragraph.php
@@ -6,10 +6,14 @@
  */
 ?>
 
-<?php if ( $field->has_description() ): ?>
+<?php if ( $field->has_description() ) : ?>
 	<tr>
 		<td style="padding-left:0;" colspan="2">
-			<p <?php if ( $field->has_classes() ): ?>class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+			<p 
+			<?php
+			if ( $field->has_classes() ) :
+				?>
+				class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		</td>
 	</tr>
 <?php endif; ?>
diff --git a/templates/product-select.php b/templates/product-select.php
index 3efbbaf..bf545ba 100644
--- a/templates/product-select.php
+++ b/templates/product-select.php
@@ -1,23 +1,26 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string[] $value
  */
+
 ?>
 
 <select class="wc-product-search" multiple="multiple" style="width: 50%;"
-        id="<?php echo esc_attr( $field->get_id() ); ?>"
-        name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
-        data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
-        data-action="woocommerce_json_search_products_and_variations">
+		id="<?php echo esc_attr( $field->get_id() ); ?>"
+		name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
+		data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
+		data-action="woocommerce_json_search_products_and_variations">
 	<?php
 	foreach ( (array) $value as $product_id ) {
 		$product = wc_get_product( $product_id );
 		if ( is_object( $product ) ) {
-			echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true,
-					false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
+			echo '<option value="' . esc_attr( $product_id ) . '"' . selected(
+				true,
+				true,
+				false
+			) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
 		}
 	}
 	?>
diff --git a/templates/select.php b/templates/select.php
index 0c53396..e437efc 100644
--- a/templates/select.php
+++ b/templates/select.php
@@ -7,22 +7,43 @@
 ?>
 <select
 	id="<?php echo esc_attr( $field->get_id() ); ?>"
-	<?php if ($field->has_classes()): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple()? '[]' : ''; ?>"
-	<?php foreach ($field->get_attributes() as $key => $attr_val): ?>
-		<?php echo esc_attr($key); ?>="<?php echo esc_attr($attr_val); ?>"
+	<?php
+	if ( $field->has_classes() ) :
+		?>
+		class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple() ? '[]' : ''; ?>"
+	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
+		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
-	<?php if ($field->is_required()): ?>required="required"<?php endif; ?>
-	<?php if ($field->is_disabled()): ?>disabled="disabled"<?php endif; ?>
-	<?php if ($field->is_readonly()): ?>readonly="readonly"<?php endif; ?>
-	<?php if ($field->is_multiple()): ?>multiple="multiple"<?php endif; ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_multiple() ) :
+		?>
+		multiple="multiple"<?php endif; ?>
 >
-	<?php if ( $field->has_placeholder() ): ?><option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
+	<?php
+	if ( $field->has_placeholder() ) :
+		?>
+		<option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
 
-	<?php foreach ( $field->get_possible_values() as $possible_value => $label ): ?>
+	<?php foreach ( $field->get_possible_values() as $possible_value => $label ) : ?>
 		<option
-			<?php if ( $possible_value === $value || (is_array($value) && in_array($possible_value, $value)) || (is_numeric($possible_value) && is_numeric($value) && (int) $possible_value === (int) $value )): ?>selected="selected"<?php endif; ?>
+			<?php
+			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
+				?>
+				selected="selected"<?php endif; ?>
 			value="<?php echo esc_attr( $possible_value ); ?>"
 		><?php echo esc_html( $label ); ?></option>
 	<?php endforeach; ?>
diff --git a/templates/textarea.php b/templates/textarea.php
index cf2f2a7..4d140fa 100644
--- a/templates/textarea.php
+++ b/templates/textarea.php
@@ -7,17 +7,35 @@
 ?>
 
 <textarea
-    id="<?php echo esc_attr( $field->get_id() ); ?>"
-		<?php if ( $field->has_classes() ): ?>class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	id="<?php echo esc_attr( $field->get_id() ); ?>"
+		<?php
+		if ( $field->has_classes() ) :
+			?>
+			class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
 	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
-    <?php foreach ( $field->get_attributes() as $key => $attr_val ): ?>
-    <?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
-    <?php endforeach; ?>
+	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
+		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+	<?php endforeach; ?>
 
-    <?php if ( $field->is_required() ): ?>required="required"<?php endif; ?>
-    <?php if ( $field->is_disabled() ): ?>disabled="disabled"<?php endif; ?>
-    <?php if ( $field->is_readonly() ): ?>readonly="readonly"<?php endif; ?>
-    <?php if ( $field->is_multiple() ): ?>multiple="multiple"<?php endif; ?>
+	<?php
+	if ( $field->is_required() ) :
+		?>
+		required="required"<?php endif; ?>
+	<?php
+	if ( $field->is_disabled() ) :
+		?>
+		disabled="disabled"<?php endif; ?>
+	<?php
+	if ( $field->is_readonly() ) :
+		?>
+		readonly="readonly"<?php endif; ?>
+	<?php
+	if ( $field->is_multiple() ) :
+		?>
+		multiple="multiple"<?php endif; ?>
 
-    <?php if ( $field->has_placeholder() ): ?>placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
+	<?php
+	if ( $field->has_placeholder() ) :
+		?>
+		placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
 ><?php echo esc_html( $value ); ?></textarea>
diff --git a/templates/wyswig.php b/templates/wyswig.php
index fd1ea9d..6bf06d3 100644
--- a/templates/wyswig.php
+++ b/templates/wyswig.php
@@ -13,14 +13,14 @@
 
 <?php
 $id              = uniqid( 'wyswig_' );
-$editor_settings = array(
-	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']'
-);
+$editor_settings = [
+	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']',
+];
 
 wp_editor( wp_kses_post( $value ), $id, $editor_settings );
 ?>
 <script type="text/javascript">
 	(function () {
-		ShopMagic.wyswig.init('<?php echo $id; ?>');
+		ShopMagic.wyswig.init('<?php echo esc_attr( $id ); ?>');
 	}());
 </script>
diff --git a/tests/unit/TestForm.php b/tests/unit/TestForm.php
deleted file mode 100644
index a0702cf..0000000
--- a/tests/unit/TestForm.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Tests;
-
-use WPDesk\Forms\Form\AbstractForm;
-
-class TestForm extends \PHPUnit\Framework\TestCase
-{
-
-	const FORM1_ID                = 'test_form';
-	const FORM1_FORM_DATA         = [ 'test' => true ];
-	const FORM1_UPDATED_FORM_DATA = [ 'test666' => true ];
-
-	private $form;
-
-	protected function setUp(){
-		// Create a new instance from the Abstract Class
-		$this->form = $this->getMockBuilder( AbstractForm::class )
-		                   ->enableOriginalConstructor()
-		                   ->setMethods(['get_form_id'])
-		                   ->getMockForAbstractClass();
-		$this->form->method( 'get_form_id' )->willReturn( self::FORM1_ID );
-		$this->form->method( 'create_form_data' )->willReturn( self::FORM1_FORM_DATA );
-	}
-
-	protected function getForm(){
-		return clone $this->form;
-	}
-
-    /**
-     * Test getting form id.
-     */
-    public function testFormId()
-    {
-    	$form = $this->getForm();
-	    $this->assertEquals(self::FORM1_ID, $form->get_form_id());
-    }
-
-	/**
-	 * Test getting form data.
-	 */
-	public function testFormData()
-	{
-		$form = $this->getForm();
-		$this->assertSame( self::FORM1_FORM_DATA, $form->get_form_data());
-	}
-
-	/**
-	 * Test updated form data.
-	 */
-	public function testUpdatedFormData()
-	{
-		$form = $this->getForm();
-
-		$form->update_form_data( self::FORM1_UPDATED_FORM_DATA );
-		$this->assertSame( array_merge( self::FORM1_FORM_DATA, self::FORM1_UPDATED_FORM_DATA ), $form->get_form_data());
-	}
-}
\ No newline at end of file
diff --git a/tests/unit/TestFormCollection.php b/tests/unit/TestFormCollection.php
deleted file mode 100644
index 67bd0ae..0000000
--- a/tests/unit/TestFormCollection.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-
-namespace Tests;
-
-use WPDesk\Forms\Form\AbstractForm;
-use WPDesk\Forms\Form\FormsCollection;
-
-class TestFormCollection extends \PHPUnit\Framework\TestCase {
-
-	const FORM1_ID = 'test_form';
-	const FORM2_ID = 'test_form2';
-
-	const FORM1_FORM_DATA = [ 'test' => true ];
-	const FORM2_FORM_DATA = [ 'test2' => 'potato' ];
-
-	const FORM1_PREFIXED_FORM_DATA = [ 'test_form_test' => true ];
-	const FORM1_UPDATED_FORM_DATA  = [ 'test666' => true ];
-
-
-	private $formConditionalTrue;
-	private $formConditionalFalse;
-
-	protected function setUp() {
-		$this->formConditionalTrue = $this->getMockBuilder( AbstractForm::class )
-		                                  ->enableOriginalConstructor()
-		                                  ->setMethods( [ 'get_form_id', 'is_active' ] )
-		                                  ->getMockForAbstractClass();
-		$this->formConditionalTrue->method( 'get_form_id' )->willReturn( self::FORM1_ID );
-		$this->formConditionalTrue->method( 'is_active' )->willReturn( true );
-		$this->formConditionalTrue->method( 'create_form_data' )->willReturn( self::FORM1_FORM_DATA );
-
-		$this->formConditionalFalse = $this->getMockBuilder( AbstractForm::class )
-		                                   ->enableOriginalConstructor()
-		                                   ->setMethods( [ 'get_form_id', 'is_active' ] )
-		                                   ->getMockForAbstractClass();
-		$this->formConditionalFalse->method( 'get_form_id' )->willReturn( self::FORM2_ID );
-		$this->formConditionalFalse->method( 'is_active' )->willReturn( false );
-		$this->formConditionalFalse->method( 'create_form_data' )->willReturn( self::FORM2_FORM_DATA );
-	}
-
-	protected function getFormConditionalTrue() {
-		return clone $this->formConditionalTrue;
-	}
-
-	protected function getFormConditionalFalse() {
-		return clone $this->formConditionalFalse;
-	}
-
-	/**
-	 * Test adding and checking single form.
-	 */
-	public function testIfFormExists() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->assertTrue( $collection->is_form_exists( self::FORM1_ID ) );
-	}
-
-	/**
-	 * Test adding and checking multiple forms.
-	 */
-	public function testIfFormsExists() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertTrue( $collection->is_form_exists( self::FORM1_ID ) );
-		$this->assertTrue( $collection->is_form_exists( self::FORM2_ID ) );
-	}
-
-	/**
-	 * Test getting single form. AbstractForm object is expected
-	 */
-	public function testGettingExistingForm() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->assertInstanceOf(
-			AbstractForm::class,
-			$collection->get_form( self::FORM1_ID )
-		);
-	}
-
-	/**
-	 * Test getting not existing single form.
-	 */
-	public function testGettingNotExistingForm() {
-		$collection = new FormsCollection();
-		$collection->add_form( $this->getFormConditionalTrue() );
-
-		$this->expectException( \OutOfRangeException::class );
-		$collection->get_form( '123456' );
-	}
-
-	/**
-	 * Test returned data.
-	 */
-	public function testReturnedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertSame( self::FORM1_FORM_DATA, $collection->get_forms_data() );
-	}
-
-	/**
-	 * Test returned prefixed data.
-	 */
-	public function testReturnedPrefixedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$this->assertSame( self::FORM1_PREFIXED_FORM_DATA, $collection->get_forms_data( true ) );
-
-
-	}
-
-	/**
-	 * Test returned updated data.
-	 */
-	public function testReturnedUpdatedFormsData() {
-		$collection = new FormsCollection();
-		$collection->add_forms( [
-			$this->getFormConditionalTrue(),
-			$this->getFormConditionalFalse(),
-		] );
-
-		$form = $collection->get_form( self::FORM1_ID );
-		$form->update_form_data( self::FORM1_UPDATED_FORM_DATA );
-		$this->assertSame( array_merge( self::FORM1_FORM_DATA, self::FORM1_UPDATED_FORM_DATA ), $collection->get_forms_data() );
-
-	}
-
-}
\ No newline at end of file
-- 
GitLab


From b646e8b22b3cd05ed90726442943fb4e1ebf6bde Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Mon, 6 Sep 2021 16:19:09 +0200
Subject: [PATCH 16/39] feat: add email input field

---
 src/Field/InputEmailField.php    | 22 ++++++++++++++++++++++
 src/Sanitizer/EmailSanitizer.php | 12 ++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 src/Field/InputEmailField.php
 create mode 100644 src/Sanitizer/EmailSanitizer.php

diff --git a/src/Field/InputEmailField.php b/src/Field/InputEmailField.php
new file mode 100644
index 0000000..ee18412
--- /dev/null
+++ b/src/Field/InputEmailField.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace WPDesk\Forms\Field;
+
+use WPDesk\Forms\Sanitizer;
+use WPDesk\Forms\Sanitizer\EmailSanitizer;
+
+class InputEmailField extends BasicField {
+	public function __construct() {
+		parent::__construct();
+		$this->set_default_value( '' );
+		$this->set_attribute( 'type', 'email' );
+	}
+
+	public function get_sanitizer(): Sanitizer {
+		return new EmailSanitizer();
+	}
+
+	public function get_template_name(): string {
+		return 'input-text';
+	}
+}
diff --git a/src/Sanitizer/EmailSanitizer.php b/src/Sanitizer/EmailSanitizer.php
new file mode 100644
index 0000000..1a51a78
--- /dev/null
+++ b/src/Sanitizer/EmailSanitizer.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace WPDesk\Forms\Sanitizer;
+
+use WPDesk\Forms\Sanitizer;
+
+class EmailSanitizer implements Sanitizer {
+	public function sanitize( $value ): string {
+		return sanitize_email( $value );
+	}
+
+}
-- 
GitLab


From eb83afaada1f060ee49ce599b994822d10335c4a Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Tue, 7 Sep 2021 20:48:51 +0200
Subject: [PATCH 17/39] fix: add missing strong types in signatures

---
 README.md                               | 80 +++++++------------------
 src/Field.php                           |  8 +--
 src/Field/Traits/HtmlAttributes.php     |  8 +--
 src/Renderer/JsonNormalizedRenderer.php |  2 +-
 tests/docker-compose.yaml               |  2 +-
 5 files changed, 26 insertions(+), 74 deletions(-)

diff --git a/README.md b/README.md
index 06702bf..519d15f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-[![pipeline status](https://gitlab.com/wpdesk/wp-forms/badges/master/pipeline.svg)](https://gitlab.com/wpdesk/wp-forms/pipelines) 
-[![coverage report](https://gitlab.com/wpdesk/wp-forms/badges/master/coverage.svg)](https://gitlab.com/wpdesk/wp-forms/commits/master) 
-[![Latest Stable Version](https://poser.pugx.org/wpdesk/wp-forms/v/stable)](https://packagist.org/packages/wpdesk/wp-forms) 
-[![Total Downloads](https://poser.pugx.org/wpdesk/wp-forms/downloads)](https://packagist.org/packages/wpdesk/wp-forms) 
-[![Latest Unstable Version](https://poser.pugx.org/wpdesk/wp-forms/v/unstable)](https://packagist.org/packages/wpdesk/wp-forms) 
+[![pipeline status](https://gitlab.com/wpdesk/wp-forms/badges/master/pipeline.svg)](https://gitlab.com/wpdesk/wp-forms/pipelines)
+[![coverage report](https://gitlab.com/wpdesk/wp-forms/badges/master/coverage.svg)](https://gitlab.com/wpdesk/wp-forms/commits/master)
+[![Latest Stable Version](https://poser.pugx.org/wpdesk/wp-forms/v/stable)](https://packagist.org/packages/wpdesk/wp-forms)
+[![Total Downloads](https://poser.pugx.org/wpdesk/wp-forms/downloads)](https://packagist.org/packages/wpdesk/wp-forms)
+[![Latest Unstable Version](https://poser.pugx.org/wpdesk/wp-forms/v/unstable)](https://packagist.org/packages/wpdesk/wp-forms)
 [![License](https://poser.pugx.org/wpdesk/wp-forms/license)](https://packagist.org/packages/wpdesk/wp-forms)
 
 WordPress Library for Form integration
@@ -11,7 +11,7 @@ WordPress Library for Form integration
 
 ## Requirements
 
-PHP 5.6 or later.
+PHP 7.0 or later.
 
 ## Composer
 
@@ -34,26 +34,18 @@ Let's say we have an abstraction for settings tabs:
 interface SettingsTab {
 	/**
 	 * Slug name used for unique url and settings in db.
-	 *
-	 * @return string
 	 */
-	public static function get_tab_slug();
+	public static function get_tab_slug(): string;
 
 	/**
 	 * Tab name to show on settings page.
-	 *
-	 * @return string
 	 */
-	public function get_tab_name();
+	public function get_tab_name(): string;
 
 	/**
 	 * Render tab content and return it as string.
-	 *
-	 * @param Renderer $renderer
-	 *
-	 * @return string
 	 */
-	public function render( Renderer $renderer );
+	public function render( Renderer $renderer ): string;
 
 	/**
 	 * Use to set settings from database or defaults.
@@ -74,14 +66,14 @@ interface SettingsTab {
 	 *
 	 * @return void
 	 */
-	public function handle_request( $request );
+	public function handle_request( array $request );
 
 	/**
 	 * Returns valid data from Tab. Can be used after ::handle_request or ::set_data.
 	 *
 	 * @return array
 	 */
-	public function get_data();
+	public function get_data(): array;
 }
 ```
 
@@ -95,12 +87,9 @@ abstract class FieldSettingsTab implements SettingsTab {
 	/**
 	 * @return Field[]
 	 */
-	abstract protected function get_fields();
+	abstract protected function get_fields(): array;
 
-	/**
-	 * @return FormWithFields
-	 */
-	protected function get_form() {
+	protected function get_form(): FormWithFields {
 		if ( $this->form === null ) {
 			$fields     = $this->get_fields();
 			$this->form = new FormWithFields( $fields, static::get_tab_slug() );
@@ -109,7 +98,7 @@ abstract class FieldSettingsTab implements SettingsTab {
 		return $this->form;
 	}
 
-	public function render( Renderer $renderer) {
+	public function render( Renderer $renderer ) {
 		return $this->get_form()->render_form( $renderer );
 	}
 
@@ -121,7 +110,7 @@ abstract class FieldSettingsTab implements SettingsTab {
 		$this->get_form()->handle_request( $request );
 	}
 
-	public function get_data() {
+	public function get_data(): array {
 		return $this->get_form()->get_data();
 	}
 }
@@ -131,10 +120,7 @@ Then we can create a settings tab that looks like that:
 
 ```php
 final class GeneralSettings extends FieldSettingsTab {
-	/**
-	 * @inheritDoc
-	 */
-	protected function get_fields() {
+	protected function get_fields(): array {
 		return [
 			( new CheckboxField() )
 				->set_label( __( 'Subscribe on checkout', 'some-text-domain' ) )
@@ -166,23 +152,17 @@ final class GeneralSettings extends FieldSettingsTab {
 		];
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public static function get_tab_slug() {
 		return 'general';
 	}
 
-	/**
-	 * @inheritDoc
-	 */
 	public function get_tab_name() {
 		return __( 'General', 'text-domain' );
 	}
 }
 ```
 
-Then class like that provides form load/save/render support for these abstraction can look like this:
+Then class like that provides form load/save/render support for this abstraction can look like this:
 
 ```php
 /**
@@ -212,8 +192,6 @@ final class Settings {
 	}
 
 	/**
-	 * Render
-	 *
 	 * @return void
 	 */
 	public function render_page_action() {
@@ -228,10 +206,7 @@ final class Settings {
 		echo $renderer->render( 'footer' );
 	}
 
-	/**
-	 * @return SettingsTab
-	 */
-	private function get_active_tab() {
+	private function get_active_tab(): SettingTab {
 		$selected_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : null;
 		$tabs         = $this->get_settings_tabs();
 		if ( ! empty( $selected_tab ) && isset( $tabs[ $selected_tab ] ) ) {
@@ -244,7 +219,7 @@ final class Settings {
 	/**
 	 * @return SettingsTab[]
 	 */
-	private function get_settings_tabs() {
+	private function get_settings_tabs(): array {
 		static $tabs = [];
 		if ( empty( $tabs ) ) {
 			$tabs = [
@@ -263,15 +238,12 @@ final class Settings {
 	 *
 	 * @return PersistentContainer
 	 */
-	public static function get_settings_persistence( $tab_slug ) {
+	public static function get_settings_persistence( string $tab_slug ): PersistentContainer {
 		return new WordpressOptionsContainer( 'some-settings-' . $tab_slug );
 	}
 
 	/**
 	 * Save data from tab to persistent container.
-	 *
-	 * @param SettingsTab $tab
-	 * @param PersistentContainer $container
 	 */
 	private function save_tab_data( SettingsTab $tab, PersistentContainer $container ) {
 		$tab_data = $tab->get_data();
@@ -282,17 +254,14 @@ final class Settings {
 		} );
 	}
 
-	/**
-	 * @return \WPDesk\View\Renderer\Renderer
-	 */
-	private function get_renderer() {
+	private function get_renderer(): \WPDesk\View\Renderer\Renderer {
 		return new SimplePhpRenderer( new DefaultFormFieldResolver() );
 	}
 
 	/**
 	 * @return string[]
 	 */
-	private function get_tabs_menu_items() {
+	private function get_tabs_menu_items(): array {
 		$menu_items = [];
 
 		foreach ( $this->get_settings_tabs() as $tab ) {
@@ -303,8 +272,3 @@ final class Settings {
 	}
 }
 ```
-
-
-## Project documentation
-
-PHPDoc: https://wpdesk.gitlab.io/wp-forms/index.html  
\ No newline at end of file
diff --git a/src/Field.php b/src/Field.php
index 2a6569e..22cf8d7 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -54,13 +54,7 @@ interface Field {
 	 */
 	public function get_attributes( array $except = [] ): array;
 
-	/**
-	 * @param string  $name
-	 * @param ?string $default
-	 *
-	 * @return string
-	 */
-	public function get_attribute( string $name, $default = null ): string;
+	public function get_attribute( string $name, string $default = null ): string;
 
 	public function is_attribute_set( string $name ): bool;
 
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 4e54c85..b4ee084 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -45,13 +45,7 @@ trait HtmlAttributes {
 		return isset( $this->attributes[ $name ] );
 	}
 
-	/**
-	 * @param string  $name
-	 * @param ?string $default
-	 *
-	 * @return string
-	 */
-	public function get_attribute( string $name, $default = null ): string {
+	public function get_attribute( string $name, string $default = null ): string {
 		return $this->attributes[ $name ] ?? $default;
 	}
 }
diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 371490c..82021cb 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -29,7 +29,7 @@ class JsonNormalizedRenderer implements FieldRenderer {
 				'readonly' => $field->is_readonly(),
 				'required' => $field->is_required(),
 				'prefix'   => $name_prefix,
-				'value '   => isset( $fields_data[ $field->get_name() ] ) ? $fields_data[ $field->get_name() ] : $field->get_default_value(),
+				'value '   => $fields_data[ $field->get_name() ] ?? $field->get_default_value(),
 			];
 
 			if ( $field->has_classes() ) {
diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml
index 2a86b03..718ce5e 100644
--- a/tests/docker-compose.yaml
+++ b/tests/docker-compose.yaml
@@ -123,7 +123,7 @@ services:
       WORDPRESS_DB_HOST: mysql0
 
   mysql0:
-    image: mysql:5.7
+    image: mariadb:10.3
     environment:
       MYSQL_ROOT_PASSWORD: mysql
       MYSQL_DATABASE: wptest
-- 
GitLab


From 53a227a8aa99d0193678696f21354a1d167baa15 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 8 Sep 2021 11:31:08 +0200
Subject: [PATCH 18/39] fix: correct returning self signature

---
 src/Field.php                       |  4 ++--
 src/Field/BasicField.php            | 31 ++++++++++++++---------------
 src/Field/CheckboxField.php         |  4 +++-
 src/Field/Header.php                |  4 +++-
 src/Field/SelectField.php           |  6 ++++--
 src/Field/Traits/HtmlAttributes.php | 12 +++++++++--
 6 files changed, 37 insertions(+), 24 deletions(-)

diff --git a/src/Field.php b/src/Field.php
index 22cf8d7..42ea129 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -73,9 +73,9 @@ interface Field {
 	/** @return array<string,int> */
 	public function get_data(): array;
 
-	public function add_data( string $data_name, string $data_value ): self;
+	public function add_data( string $data_name, string $data_value ): Field;
 
-	public function unset_data( string $data_name ): self;
+	public function unset_data( string $data_name ): Field;
 
 	/** @return mixed */
 	public function get_possible_values();
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index ee7f144..842241e 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -3,7 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 use WPDesk\Forms\Field;
-use WPDesk\Forms\Form\FormWithFields;
 use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
@@ -38,7 +37,7 @@ abstract class BasicField implements Field {
 		return $this->meta['label'];
 	}
 
-	public function set_label( string $value ): self {
+	public function set_label( string $value ): Field {
 		$this->meta['label'] = $value;
 
 		return $this;
@@ -68,13 +67,13 @@ abstract class BasicField implements Field {
 		return isset( $this->meta['description'] );
 	}
 
-	public function set_description( string $value ): self {
+	public function set_description( string $value ): Field {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( string $value ): self {
+	public function set_description_tip( string $value ): Field {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
@@ -84,7 +83,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['type'];
 	}
 
-	public function set_placeholder( string $value ): self {
+	public function set_placeholder( string $value ): Field {
 		$this->meta['placeholder'] = $value;
 
 		return $this;
@@ -98,7 +97,7 @@ abstract class BasicField implements Field {
 		return $this->meta['placeholder'];
 	}
 
-	public function set_name( string $name ): self {
+	public function set_name( string $name ): Field {
 		$this->attributes['name'] = $name;
 
 		return $this;
@@ -140,7 +139,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['multiple'] ?? false;
 	}
 
-	public function set_disabled(): self {
+	public function set_disabled(): Field {
 		$this->attributes['disabled'] = true;
 
 		return $this;
@@ -150,7 +149,7 @@ abstract class BasicField implements Field {
 		return $this->attributes['disabled'] ?? false;
 	}
 
-	public function set_readonly(): self {
+	public function set_readonly(): Field {
 		$this->attributes['readonly'] = true;
 
 		return $this;
@@ -160,25 +159,25 @@ abstract class BasicField implements Field {
 		return $this->attributes['readonly'] ?? false;
 	}
 
-	public function set_required(): self {
+	public function set_required(): Field {
 		$this->meta['required'] = true;
 
 		return $this;
 	}
 
-	public function add_class( string $class_name ): self {
+	public function add_class( string $class_name ): Field {
 		$this->meta['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	public function unset_class( string $class_name ): self {
+	public function unset_class( string $class_name ): Field {
 		unset( $this->meta['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	public function add_data( string $data_name, string $data_value ): self {
+	public function add_data( string $data_name, string $data_value ): Field {
 		if ( ! isset( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
@@ -187,7 +186,7 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function unset_data( string $data_name ): self {
+	public function unset_data( string $data_name ): Field {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
@@ -205,7 +204,7 @@ abstract class BasicField implements Field {
 		return $this->default_value;
 	}
 
-	public function set_default_value( string $value ): self {
+	public function set_default_value( string $value ): Field {
 		$this->default_value = $value;
 
 		return $this;
@@ -236,7 +235,7 @@ abstract class BasicField implements Field {
 		return new NoSerialize();
 	}
 
-	public function set_serializer( Serializer $serializer ): self {
+	public function set_serializer( Serializer $serializer ): Field {
 		$this->meta['serializer'] = $serializer;
 
 		return $this;
@@ -251,7 +250,7 @@ abstract class BasicField implements Field {
 	 *
 	 * @see FormWithFields::get_fields()
 	 */
-	public function set_priority( int $priority ): self {
+	public function set_priority( int $priority ): Field {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index e8cc29f..507cda0 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class CheckboxField extends BasicField {
 	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
@@ -19,7 +21,7 @@ class CheckboxField extends BasicField {
 		return $this->meta['sublabel'];
 	}
 
-	public function set_sublabel( string $value ): self {
+	public function set_sublabel( string $value ): Field {
 		$this->meta['sublabel'] = $value;
 
 		return $this;
diff --git a/src/Field/Header.php b/src/Field/Header.php
index fa86700..cebe249 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class Header extends NoValueField {
 	public function __construct() {
 		parent::__construct();
@@ -16,7 +18,7 @@ class Header extends NoValueField {
 		return true;
 	}
 
-	public function set_header_size( int $value ): self {
+	public function set_header_size( int $value ): Field {
 		$this->meta['header_size'] = $value;
 
 		return $this;
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index bead3bb..ee0264c 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Field;
+
 class SelectField extends BasicField {
 
 	public function get_template_name(): string {
@@ -9,13 +11,13 @@ class SelectField extends BasicField {
 	}
 
 	/** @param string[] $options */
-	public function set_options( array $options ): self {
+	public function set_options( array $options ): Field {
 		$this->meta['possible_values'] = $options;
 
 		return $this;
 	}
 
-	public function set_multiple(): self {
+	public function set_multiple(): Field {
 		$this->attributes['multiple'] = true;
 
 		return $this;
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index b4ee084..afc1e08 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms\Field\Traits;
 
+use WPDesk\Forms\Field;
+
 /**
  * Implementation of HTML attributes like id, name, action etc.
  *
@@ -29,13 +31,19 @@ trait HtmlAttributes {
 		);
 	}
 
-	public function set_attribute( string $name, string $value ): self {
+	/**
+	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 */
+	public function set_attribute( string $name, string $value ) {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
 	}
 
-	public function unset_attribute( string $name ): self {
+	/**
+	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 */
+	public function unset_attribute( string $name ) {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
-- 
GitLab


From ce4ed432cf63078026b70ef9ec06c5dc3c2de6db Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 8 Sep 2021 13:45:03 +0200
Subject: [PATCH 19/39] fix: correct type issues

---
 src/ContainerForm.php               | 9 ++++++---
 src/Field/BasicField.php            | 6 ++++--
 src/Field/Traits/HtmlAttributes.php | 4 +---
 src/Form.php                        | 4 ++--
 src/Form/FormWithFields.php         | 6 ++++--
 5 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 0510706..1d4cf05 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
 /**
@@ -11,8 +10,12 @@ use WPDesk\Persistence\PersistentContainer;
  * @package WPDesk\Forms
  */
 interface ContainerForm {
-	/** @return void */
-	public function set_data( ContainerInterface $data );
+	/**
+	 * @param \Psr\Container\ContainerInterface $data
+	 *
+	 * @return void
+	 */
+	public function set_data( $data );
 
 	/**
 	 * Put data from form into a container.
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 842241e..69e460d 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -200,11 +200,13 @@ abstract class BasicField implements Field {
 		return isset( $this->meta['class'][ $name ] );
 	}
 
-	public function get_default_value(): string {
+	/** @return mixed */
+	public function get_default_value() {
 		return $this->default_value;
 	}
 
-	public function set_default_value( string $value ): Field {
+	/** @param mixed $value */
+	public function set_default_value( $value ): Field {
 		$this->default_value = $value;
 
 		return $this;
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index afc1e08..5ae190a 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms\Field\Traits;
 
-use WPDesk\Forms\Field;
-
 /**
  * Implementation of HTML attributes like id, name, action etc.
  *
@@ -54,6 +52,6 @@ trait HtmlAttributes {
 	}
 
 	public function get_attribute( string $name, string $default = null ): string {
-		return $this->attributes[ $name ] ?? $default;
+		return $this->attributes[ $name ] ?? $default ?? '';
 	}
 }
diff --git a/src/Form.php b/src/Form.php
index 8ea2d78..504ebbe 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -42,7 +42,7 @@ interface Form {
 	 *
 	 * @return void
 	 */
-	public function set_data( array $data );
+	public function set_data( $data );
 
 	/**
 	 * Use to render the form to string.
@@ -69,6 +69,6 @@ interface Form {
 	/**
 	 * Form if you ever need to have more than one form at once.
 	 */
-	public function get_form_id(): int;
+	public function get_form_id(): string;
 }
 
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index 45dc515..ba13928 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -113,7 +113,9 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
-	 * @param array|ContainerInterface $data Data consistent with Form and ContainerForm interface.
+	 * @param array|ContainerInterface $data Data consistent with Form or ContainerForm interface.
+	 *
+	 * @return void
 	 */
 	public function set_data( $data ) {
 		if ( is_array( $data ) ) {
@@ -208,7 +210,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $fields;
 	}
 
-	public function get_form_id(): int {
+	public function get_form_id(): string {
 		return $this->form_id;
 	}
 
-- 
GitLab


From d466d1ade903b3f3e7684eb68b7fe05a1ca94577 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Fri, 10 Sep 2021 02:24:11 +0200
Subject: [PATCH 20/39] fix: remove return type from NoSerialize - it passes
 any value

---
 src/Serializer/NoSerialize.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index 31a09e1..b29e88b 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ): string {
+	public function serialize( $value ) {
 		return $value;
 	}
 
-- 
GitLab


From c0613204695bc3b80e48ad1794333957ba71c9bb Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Wed, 15 Sep 2021 12:17:59 +0200
Subject: [PATCH 21/39] fix: escaping

---
 templates/input-image.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/input-image.php b/templates/input-image.php
index af9f792..cb9ae95 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -7,7 +7,7 @@
 
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
-<div class="media-input-wrapper" id="<?php echo $media_container_id; ?>">
+<div class="media-input-wrapper" id="<?php echo esc_attr( $media_container_id ); ?>">
 	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
 		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
 		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
-- 
GitLab


From a838b13fbb88ffc546e8151c7d779b846e80d344 Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Wed, 15 Sep 2021 12:54:28 +0200
Subject: [PATCH 22/39] fix: reformat

---
 src/ContainerForm.php    | 3 ++-
 src/Field/BasicField.php | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 1d4cf05..9c7e339 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms;
 
+use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
 
 /**
@@ -11,7 +12,7 @@ use WPDesk\Persistence\PersistentContainer;
  */
 interface ContainerForm {
 	/**
-	 * @param \Psr\Container\ContainerInterface $data
+	 * @param ContainerInterface $data
 	 *
 	 * @return void
 	 */
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 69e460d..9444933 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -124,7 +124,7 @@ abstract class BasicField implements Field {
 	}
 
 	public function get_possible_values() {
-		return isset( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
+		return $this->meta['possible_values'] ?? [];
 	}
 
 	public function get_id(): string {
-- 
GitLab


From fe0eab2e3f4e0a9beeec3d66946673bdcb543837 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 15 Sep 2021 11:43:14 +0200
Subject: [PATCH 23/39] feat: add escaping functions in templates

---
 phpcs.xml.dist                    |  2 +-
 templates/button.php              |  3 +--
 templates/form-end.php            |  6 ++++++
 templates/form-field.php          | 22 ++++++++++++----------
 templates/form-label.php          |  5 +++--
 templates/form-start.php          |  5 +++--
 templates/header.php              |  4 ++--
 templates/input-checkbox.php      | 19 ++++++++++---------
 templates/input-date-picker.php   | 21 +++++++++++----------
 templates/input-hidden.php        | 20 +++++++++++---------
 templates/input-image.php         | 12 ++++++------
 templates/input-number.php        | 21 +++++++++++----------
 templates/input-radio.php         | 20 +++++++++++---------
 templates/input-submit.php        | 14 +++++++-------
 templates/input-text-multiple.php | 12 +++++-------
 templates/input-text.php          | 22 +++++++++++-----------
 templates/input.php               | 10 ++++------
 templates/paragraph.php           |  7 +++----
 templates/product-select.php      |  8 ++++----
 templates/select.php              | 18 ++++++++++--------
 templates/textarea.php            | 13 +++++++------
 templates/wyswig.php              | 13 +++++++------
 22 files changed, 146 insertions(+), 131 deletions(-)

diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 6ef3f27..1b9bf7a 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -31,7 +31,7 @@
 	-->
 
 	<!-- Define plugin text domain for i18n. -->
-	<config name="text_domain" value="shopmagic-for-woocommerce"/>
+	<config name="text_domain" value="wp-forms"/>
 
 	<!-- This value should be aligned with WordPress support version declared in plugin header -->
 	<config name="minimum_supported_wp_version" value="5.0"/>
diff --git a/templates/button.php b/templates/button.php
index c558c6e..fd95750 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -4,7 +4,6 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
 
@@ -16,7 +15,7 @@
 <?php endif; ?>
 
 <?php foreach ( $field->get_attributes( [] ) as $key => $val ) : ?>
-	<?php echo $key . '="' . \esc_attr( $val ) . '"'; ?>
+	<?php echo \esc_attr( $key ) . '="' . \esc_attr( $val ) . '"'; ?>
 <?php endforeach; ?>
 
 	type="<?php echo \esc_attr( $field->get_type() ); ?>"
diff --git a/templates/form-end.php b/templates/form-end.php
index 7484d6e..f2a22fe 100644
--- a/templates/form-end.php
+++ b/templates/form-end.php
@@ -1,3 +1,9 @@
+<?php
+/**
+ * Form ending with hoverable tip snippet in js.
+ */
+
+?>
 </tbody>
 </table>
 </form>
diff --git a/templates/form-field.php b/templates/form-field.php
index 50f5678..0fd07d5 100644
--- a/templates/form-field.php
+++ b/templates/form-field.php
@@ -4,26 +4,28 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 
 <tr valign="top">
 	<?php if ( $field->has_label() ) : ?>
-		<?php echo $renderer->render( 'form-label', [ 'field' => $field ] ); ?>
+		<?php echo wp_kses_post( $renderer->render( 'form-label', [ 'field' => $field ] ) ); ?>
 	<?php endif; ?>
 
 	<td class="forminp">
 		<?php
-		echo $renderer->render(
-			$template_name,
-			[
-				'field'       => $field,
-				'renderer'    => $renderer,
-				'name_prefix' => $name_prefix,
-				'value'       => $value,
-			]
+		echo wp_kses_post(
+			$renderer->render(
+				$template_name,
+				[
+					'field'       => $field,
+					'renderer'    => $renderer,
+					'name_prefix' => $name_prefix,
+					'value'       => $value,
+				]
+			)
 		);
 		?>
 
diff --git a/templates/form-label.php b/templates/form-label.php
index f6268a5..8eeaf28 100644
--- a/templates/form-label.php
+++ b/templates/form-label.php
@@ -4,11 +4,12 @@
  * @var string $name_prefix
  * @var string $value
  */
+
 ?>
 <th class="titledesc" scope="row">
-	<label for="<?php echo esc_attr( $field->get_id() ); ?>"><?php echo esc_html( $field->get_label() ); ?>
+	<label for="<?php echo \esc_attr( $field->get_id() ); ?>"><?php echo \esc_html( $field->get_label() ); ?>
 		<?php if ( $field->has_description_tip() ) : ?>
-			<?php echo wc_help_tip( $field->get_description_tip() ); ?>
+			<?php echo esc_html( wc_help_tip( $field->get_description_tip() ) ); ?>
 		<?php endif ?>
 	</label>
 </th>
diff --git a/templates/form-start.php b/templates/form-start.php
index e3d4bbe..d311794 100644
--- a/templates/form-start.php
+++ b/templates/form-start.php
@@ -2,9 +2,10 @@
 /**
  * @var \WPDesk\Forms\Form\FormWithFields $form
  */
+
 ?>
-<form class="wrap woocommerce" method="<?php echo esc_attr( $form->get_method() ); ?>" action="<?php echo esc_attr( $form->get_action() ); ?>">
-	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js ?>
+<form class="wrap woocommerce" method="<?php echo \esc_attr( $form->get_method() ); ?>" action="<?php echo \esc_attr( $form->get_action() ); ?>">
+	<h2 style="display:none;"></h2><?php // All admin notices will be moved here by WP js. ?>
 
 	<table class="form-table">
 		<tbody>
diff --git a/templates/header.php b/templates/header.php
index 07a9a6e..ec06536 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -10,9 +10,9 @@ $classes     = $field->has_classes() ? 'class="' . esc_attr( $field->get_classes
 ?>
 
 <?php if ( $field->has_label() ) : ?>
-	<h<?php echo $header_size; ?> <?php echo $classes; ?>><?php echo esc_html( $field->get_label() ); ?></h<?php echo $header_size; ?>>
+	<h<?php echo \esc_attr( $header_size ); ?> <?php echo \esc_attr( $classes ); ?>><?php echo \esc_html( $field->get_label() ); ?></h<?php echo \esc_attr( $header_size ); ?>>
 <?php endif; ?>
 
 <?php if ( $field->has_description() ) : ?>
-	<p <?php echo $classes; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+	<p <?php echo \esc_attr( $classes ); ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 <?php endif; ?>
diff --git a/templates/input-checkbox.php b/templates/input-checkbox.php
index d69ecec..8474091 100644
--- a/templates/input-checkbox.php
+++ b/templates/input-checkbox.php
@@ -4,19 +4,20 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
 
 ?>
 
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-date-picker.php b/templates/input-date-picker.php
index 0c5b70c..3caa4c6 100644
--- a/templates/input-date-picker.php
+++ b/templates/input-date-picker.php
@@ -1,19 +1,20 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-hidden.php b/templates/input-hidden.php
index 300944e..6388552 100644
--- a/templates/input-hidden.php
+++ b/templates/input-hidden.php
@@ -4,17 +4,19 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-image.php b/templates/input-image.php
index cb9ae95..313e0e6 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -7,10 +7,10 @@
 
 $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 ?>
-<div class="media-input-wrapper" id="<?php echo esc_attr( $media_container_id ); ?>">
+<div class="media-input-wrapper" id="<?php echo \esc_attr( $media_container_id ); ?>">
 	<input type="hidden" class="image-field-value" value="<?php echo \esc_html( $value ); ?>"
-		   name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
-		   id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
+			name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
+			id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
 	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
             <img src="<?php echo \esc_html( $value ) ?>" alt="" width="100"/>
@@ -28,7 +28,7 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 <script>
 	jQuery( function ( $ ) {
 		var frame,
-			metaBox = $( '#<?php echo esc_attr( $media_container_id ); ?>' ),
+			metaBox = $( '#<?php echo \esc_attr( $media_container_id ); ?>' ),
 			addImgLink = metaBox.find( '.upload-custom-img' ),
 			delImgLink = metaBox.find( '.delete-custom-img' ),
 			imgContainer = metaBox.find( '.custom-img-container' ),
@@ -42,9 +42,9 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 			}
 
 			frame = wp.media( {
-				title: <?php _e( 'Select or Upload Media', 'wp-forms' ); ?>,
+				title: <?php esc_html_e( 'Select or Upload Media', 'wp-forms' ); ?>,
 				button: {
-					text: <?php _e( 'Use this media', 'wp-forms' ); ?>
+					text: <?php esc_html_e( 'Use this media', 'wp-forms' ); ?>
 				},
 				library: {
 					type: ['image']
diff --git a/templates/input-number.php b/templates/input-number.php
index 0c5b70c..3caa4c6 100644
--- a/templates/input-number.php
+++ b/templates/input-number.php
@@ -1,19 +1,20 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-radio.php b/templates/input-radio.php
index 300944e..6388552 100644
--- a/templates/input-radio.php
+++ b/templates/input-radio.php
@@ -4,17 +4,19 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 <?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input-submit.php b/templates/input-submit.php
index 5c11fc8..bae3ce3 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -4,9 +4,9 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
+
 ?>
 
 <tr>
@@ -16,14 +16,14 @@
 				<?php
 				if ( $field->has_classes() ) :
 					?>
-					class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+					class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
 				<?php foreach ( $field->get_attributes( [] ) as $key => $value ) : ?>
-					<?php echo $key; ?>="<?php echo esc_attr( $value ); ?>"
+					<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $value ); ?>"
 				<?php endforeach; ?>
-				type="<?php echo esc_attr( $field->get_type() ); ?>"
-				name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
-				id="<?php echo esc_attr( $field->get_id() ); ?>"
-				value="<?php echo esc_html( $field->get_label() ); ?>"
+				type="<?php echo \esc_attr( $field->get_type() ); ?>"
+				name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
+				id="<?php echo \esc_attr( $field->get_id() ); ?>"
+				value="<?php echo \esc_html( $field->get_label() ); ?>"
 				<?php
 				if ( $field->is_required() ) :
 					?>
diff --git a/templates/input-text-multiple.php b/templates/input-text-multiple.php
index f278729..371013d 100644
--- a/templates/input-text-multiple.php
+++ b/templates/input-text-multiple.php
@@ -4,11 +4,9 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-?>
-<?php
+
 if ( empty( $value ) || is_string( $value ) ) {
 	$input_values[] = '';
 } else {
@@ -17,8 +15,8 @@ if ( empty( $value ) || is_string( $value ) ) {
 ?>
 <div class="clone-element-container">
 <?php foreach ( $input_values as $text_value ) : ?>
-	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
-	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
+	<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
+	<input type="hidden" name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>" value="no"/>
 <?php endif; ?>
 
 	<?php
@@ -41,7 +39,7 @@ if ( empty( $value ) || is_string( $value ) ) {
 
 		<?php
 		foreach ( $field->get_attributes() as $key => $atr_val ) :
-			echo $key . '="' . \esc_attr( $atr_val ) . '"';
+			echo \esc_attr( $key ) . '="' . \esc_attr( $atr_val ) . '"';
 			?>
 		<?php endforeach; ?>
 
@@ -57,7 +55,7 @@ if ( empty( $value ) || is_string( $value ) ) {
 		if ( $field->is_readonly() ) :
 			?>
 			readonly="readonly"<?php endif; ?>
-		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 			value="<?php echo \esc_html( $text_value ); ?>"
 		<?php else : ?>
 			value="yes"
diff --git a/templates/input-text.php b/templates/input-text.php
index 300944e..3caa4c6 100644
--- a/templates/input-text.php
+++ b/templates/input-text.php
@@ -4,17 +4,17 @@
  * @var \WPDesk\View\Renderer\Renderer $renderer
  * @var string $name_prefix
  * @var string $value
- *
  * @var string $template_name Real field template.
  */
-?>
-<?php
-echo $renderer->render(
-	'input',
-	[
-		'field'       => $field,
-		'renderer'    => $renderer,
-		'name_prefix' => $name_prefix,
-		'value'       => $value,
-	]
+
+echo wp_kses_post(
+	$renderer->render(
+		'input',
+		[
+			'field'       => $field,
+			'renderer'    => $renderer,
+			'name_prefix' => $name_prefix,
+			'value'       => $value,
+		]
+	)
 );
diff --git a/templates/input.php b/templates/input.php
index 83448ea..a4844b1 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -1,14 +1,12 @@
 <?php
-
 /**
  * @var \WPDesk\Forms\Field $field
  * @var string $name_prefix
  * @var string $value
  */
-?>
 
-<?php if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
-	<input type="hidden" name="<?php echo $name_prefix . '[' . $field->get_name() . ']'; ?>" value="no"/>
+if ( ! \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
+	<input type="hidden" name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>" value="no"/>
 <?php endif; ?>
 
 <?php
@@ -31,7 +29,7 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 
 	<?php
 	foreach ( $field->get_attributes() as $key => $atr_val ) :
-		echo $key . '="' . \esc_attr( $atr_val ) . '"';
+		echo \esc_attr( $key ) . '="' . \esc_attr( $atr_val ) . '"';
 		?>
 	<?php endforeach; ?>
 
@@ -47,7 +45,7 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 	if ( $field->is_readonly() ) :
 		?>
 		readonly="readonly"<?php endif; ?>
-	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ] ) ) : ?>
+	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 		value="<?php echo \esc_html( $value ); ?>"
 	<?php else : ?>
 		value="yes"
diff --git a/templates/paragraph.php b/templates/paragraph.php
index 9d29015..85fb04c 100644
--- a/templates/paragraph.php
+++ b/templates/paragraph.php
@@ -4,16 +4,15 @@
  * @var string $name_prefix
  * @var string $value
  */
-?>
 
-<?php if ( $field->has_description() ) : ?>
+if ( $field->has_description() ) : ?>
 	<tr>
 		<td style="padding-left:0;" colspan="2">
-			<p 
+			<p
 			<?php
 			if ( $field->has_classes() ) :
 				?>
-				class="<?php echo $field->get_classes(); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
+				class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>><?php echo wp_kses_post( $field->get_description() ); ?></p>
 		</td>
 	</tr>
 <?php endif; ?>
diff --git a/templates/product-select.php b/templates/product-select.php
index bf545ba..57dd47e 100644
--- a/templates/product-select.php
+++ b/templates/product-select.php
@@ -8,15 +8,15 @@
 ?>
 
 <select class="wc-product-search" multiple="multiple" style="width: 50%;"
-		id="<?php echo esc_attr( $field->get_id() ); ?>"
-		name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>][]"
-		data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>"
+		id="<?php echo \esc_attr( $field->get_id() ); ?>"
+		name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>][]"
+		data-placeholder="<?php \esc_attr_e( 'Search for a product&hellip;', 'wp-forms' ); ?>"
 		data-action="woocommerce_json_search_products_and_variations">
 	<?php
 	foreach ( (array) $value as $product_id ) {
 		$product = wc_get_product( $product_id );
 		if ( is_object( $product ) ) {
-			echo '<option value="' . esc_attr( $product_id ) . '"' . selected(
+			echo '<option value="' . \esc_attr( $product_id ) . '"' . selected(
 				true,
 				true,
 				false
diff --git a/templates/select.php b/templates/select.php
index e437efc..625c316 100644
--- a/templates/select.php
+++ b/templates/select.php
@@ -4,16 +4,18 @@
  * @var string $name_prefix
  * @var mixed $value
  */
+
 ?>
+
 <select
-	id="<?php echo esc_attr( $field->get_id() ); ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 	<?php
 	if ( $field->has_classes() ) :
 		?>
-		class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]<?php echo $field->is_multiple() ? '[]' : ''; ?>"
+		class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]<?php echo \esc_attr( $field->is_multiple() ) ? '[]' : ''; ?>"
 	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
-		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
 	<?php
@@ -36,15 +38,15 @@
 	<?php
 	if ( $field->has_placeholder() ) :
 		?>
-		<option value=""><?php echo esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
+		<option value=""><?php echo \esc_html( $field->get_placeholder() ); ?></option><?php endif; ?>
 
 	<?php foreach ( $field->get_possible_values() as $possible_value => $label ) : ?>
 		<option
 			<?php
-			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
+			if ( $possible_value === $value || ( is_array( $value ) && in_array( $possible_value, $value, true ) ) || ( is_numeric( $possible_value ) && is_numeric( $value ) && (int) $possible_value === (int) $value ) ) :
 				?>
 				selected="selected"<?php endif; ?>
-			value="<?php echo esc_attr( $possible_value ); ?>"
-		><?php echo esc_html( $label ); ?></option>
+			value="<?php echo \esc_attr( $possible_value ); ?>"
+		><?php echo \esc_html( $label ); ?></option>
 	<?php endforeach; ?>
 </select>
diff --git a/templates/textarea.php b/templates/textarea.php
index 4d140fa..8cf3846 100644
--- a/templates/textarea.php
+++ b/templates/textarea.php
@@ -4,17 +4,18 @@
  * @var string $name_prefix
  * @var string $value
  */
+
 ?>
 
 <textarea
-	id="<?php echo esc_attr( $field->get_id() ); ?>"
+	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 		<?php
 		if ( $field->has_classes() ) :
 			?>
-			class="<?php echo esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-	name="<?php echo esc_attr( $name_prefix ); ?>[<?php echo esc_attr( $field->get_name() ); ?>]"
+			class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
+	name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
 	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
-		<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $attr_val ); ?>"
+		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
 	<?php
@@ -37,5 +38,5 @@
 	<?php
 	if ( $field->has_placeholder() ) :
 		?>
-		placeholder="<?php echo esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
-><?php echo esc_html( $value ); ?></textarea>
+		placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"<?php endif; ?>
+><?php echo \esc_html( $value ); ?></textarea>
diff --git a/templates/wyswig.php b/templates/wyswig.php
index 6bf06d3..893aec9 100644
--- a/templates/wyswig.php
+++ b/templates/wyswig.php
@@ -4,23 +4,24 @@
  * @var string $name_prefix
  * @var string $value
  */
-?>
-<?php wp_print_styles( 'media-views' ); ?>
+
+wp_print_styles( 'media-views' ); ?>
+
 <script>
 	window.SM_EditorInitialized = true;
 </script>
 
 
 <?php
-$id              = uniqid( 'wyswig_' );
+$editor_id       = uniqid( 'wyswig_' );
 $editor_settings = [
-	'textarea_name' => esc_attr( $name_prefix ) . '[' . esc_attr( $field->get_name() ) . ']',
+	'textarea_name' => \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']',
 ];
 
-wp_editor( wp_kses_post( $value ), $id, $editor_settings );
+wp_editor( wp_kses_post( $value ), $editor_id, $editor_settings );
 ?>
 <script type="text/javascript">
 	(function () {
-		ShopMagic.wyswig.init('<?php echo esc_attr( $id ); ?>');
+		ShopMagic.wyswig.init('<?php echo \esc_attr( $editor_id ); ?>');
 	}());
 </script>
-- 
GitLab


From 87f91d1766ca55d814b3f479a9d697f1f0953ad1 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Wed, 15 Sep 2021 13:21:39 +0200
Subject: [PATCH 24/39] feat: hermetize BasicField methods

---
 src/ContainerForm.php                      |   3 +-
 src/Field.php                              |   7 +-
 src/Field/BasicField.php                   | 151 ++++++++++-----------
 src/Field/ButtonField.php                  |   2 +-
 src/Field/CheckboxField.php                |   5 +-
 src/Field/DatePickerField.php              |   3 -
 src/Field/Header.php                       |   1 -
 src/Field/HiddenField.php                  |   6 +-
 src/Field/ImageInputField.php              |   6 -
 src/Field/InputEmailField.php              |   6 +-
 src/Field/InputNumberField.php             |   6 +-
 src/Field/InputTextField.php               |   6 -
 src/Field/MultipleInputTextField.php       |   1 -
 src/Field/NoOnceField.php                  |   3 +-
 src/Field/ProductSelect.php                |   1 -
 src/Field/TextAreaField.php                |   4 -
 src/Field/Traits/HtmlAttributes.php        |  42 ++++--
 src/Field/WooSelect.php                    |   1 -
 src/Field/WyswigField.php                  |   5 -
 src/FieldsDataReceiver.php                 |   4 +-
 src/Form.php                               |  12 +-
 src/Form/FormWithFields.php                |  12 +-
 src/Sanitizer.php                          |   8 +-
 src/Sanitizer/NoSanitize.php               |   2 +-
 src/Serializer.php                         |   8 +-
 src/Serializer/JsonSerializer.php          |   2 +-
 src/Serializer/NoSerialize.php             |   6 +-
 src/Serializer/ProductSelectSerializer.php |   6 +-
 src/Serializer/SerializeSerializer.php     |   4 +-
 src/Validator/NonceValidator.php           |   4 +-
 30 files changed, 149 insertions(+), 178 deletions(-)

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index 9c7e339..bd5fc82 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -4,6 +4,7 @@ namespace WPDesk\Forms;
 
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
+use Psr\Container\ContainerInterface;
 
 /**
  * Persistent container support for forms.
@@ -16,7 +17,7 @@ interface ContainerForm {
 	 *
 	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Put data from form into a container.
diff --git a/src/Field.php b/src/Field.php
index 42ea129..311d8eb 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -58,19 +58,22 @@ interface Field {
 
 	public function is_attribute_set( string $name ): bool;
 
-	public function get_meta_value( string $name ): string;
+	/** @return mixed */
+	public function get_meta_value( string $name );
 
 	public function is_meta_value_set( string $name ): bool;
 
 	public function get_classes(): string;
 
+	public function get_type(): string;
+
 	public function has_classes(): bool;
 
 	public function is_class_set( string $name ): bool;
 
 	public function has_data(): bool;
 
-	/** @return array<string,int> */
+	/** @return array<string|int> */
 	public function get_data(): array;
 
 	public function add_data( string $data_name, string $data_value ): Field;
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 9444933..2855357 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -22,112 +22,113 @@ abstract class BasicField implements Field {
 
 	const DEFAULT_PRIORITY = 10;
 
-	/** @var array<string,int,bool> */
-	protected $meta;
-
-	/** @var string */
-	protected $default_value;
-
-	public function __construct() {
-		$this->meta['class']    = [];
-		$this->meta['priority'] = self::DEFAULT_PRIORITY;
-	}
-
-	public function get_label(): string {
+	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>, serializer: ?Serializer} */
+	protected $meta = [
+		'priority'          => self::DEFAULT_PRIORITY,
+		'default_value'     => '',
+		'label'             => '',
+		'description'       => '',
+		'description_tip'   => '',
+		'data'              => [],
+		'serializer'        => null,
+	];
+
+	final public function get_label(): string {
 		return $this->meta['label'];
 	}
 
-	public function set_label( string $value ): Field {
+	final public function set_label( string $value ): Field {
 		$this->meta['label'] = $value;
 
 		return $this;
 	}
 
-	public function get_description_tip(): string {
+	final public function get_description_tip(): string {
 		return $this->meta['description_tip'];
 	}
 
-	public function has_description_tip(): bool {
-		return isset( $this->meta['description_tip'] );
+	final public function has_description_tip(): bool {
+		return ! empty( $this->meta['description_tip'] );
 	}
 
+	/** Override method if you need. */
 	public function should_override_form_template(): bool {
-		return $this->attributes['overrite_template'] ?? false;
+		return false;
 	}
 
-	public function get_description(): string {
+	final public function get_description(): string {
 		return $this->meta['description'];
 	}
 
-	public function has_label(): bool {
-		return isset( $this->meta['label'] );
+	final public function has_label(): bool {
+		return ! empty( $this->meta['label'] );
 	}
 
-	public function has_description(): bool {
-		return isset( $this->meta['description'] );
+	final public function has_description(): bool {
+		return ! empty( $this->meta['description'] );
 	}
 
-	public function set_description( string $value ): Field {
+	final public function set_description( string $value ): Field {
 		$this->meta['description'] = $value;
 
 		return $this;
 	}
 
-	public function set_description_tip( string $value ): Field {
+	final public function set_description_tip( string $value ): Field {
 		$this->meta['description_tip'] = $value;
 
 		return $this;
 	}
 
 	public function get_type(): string {
-		return $this->attributes['type'];
+		return 'text';
 	}
 
-	public function set_placeholder( string $value ): Field {
-		$this->meta['placeholder'] = $value;
+	final public function set_placeholder( string $value ): Field {
+		$this->attributes['placeholder'] = $value;
 
 		return $this;
 	}
 
-	public function has_placeholder(): bool {
-		return isset( $this->meta['placeholder'] );
+	final public function has_placeholder(): bool {
+		return ! empty( $this->attributes['placeholder'] );
 	}
 
-	public function get_placeholder(): string {
-		return $this->meta['placeholder'];
+	final public function get_placeholder(): string {
+		return $this->attributes['placeholder'];
 	}
 
-	public function set_name( string $name ): Field {
+	final public function set_name( string $name ): Field {
 		$this->attributes['name'] = $name;
 
 		return $this;
 	}
 
-	public function get_meta_value( string $name ): string {
+	final public function get_meta_value( string $name ) {
 		return $this->meta[ $name ];
 	}
 
-	public function get_classes(): string {
-		return implode( ' ', $this->meta['class'] );
+	final public function get_classes(): string {
+		return implode( ' ', $this->attributes['class'] );
 	}
 
-	public function has_classes(): bool {
-		return ! empty( $this->meta['class'] );
+	final public function has_classes(): bool {
+		return ! empty( $this->attributes['class'] );
 	}
 
-	public function has_data(): bool {
+	final public function has_data(): bool {
 		return ! empty( $this->meta['data'] );
 	}
 
-	public function get_data(): array {
-		return $this->meta['data'] ?: [];
+	final public function get_data(): array {
+		return $this->meta['data'];
 	}
 
-	public function get_possible_values() {
-		return $this->meta['possible_values'] ?? [];
+	final public function get_possible_values() {
+		return ! empty( $this->meta['possible_values'] ) ? $this->meta['possible_values'] : [];
 	}
 
-	public function get_id(): string {
+	final public function get_id(): string {
 		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
@@ -135,50 +136,50 @@ abstract class BasicField implements Field {
 		return $this->attributes['name'];
 	}
 
-	public function is_multiple(): bool {
-		return $this->attributes['multiple'] ?? false;
+	final public function is_multiple(): bool {
+		return $this->attributes['multiple'];
 	}
 
-	public function set_disabled(): Field {
+	final public function set_disabled(): Field {
 		$this->attributes['disabled'] = true;
 
 		return $this;
 	}
 
-	public function is_disabled(): bool {
-		return $this->attributes['disabled'] ?? false;
+	final public function is_disabled(): bool {
+		return $this->attributes['disabled'];
 	}
 
-	public function set_readonly(): Field {
+	final public function set_readonly(): Field {
 		$this->attributes['readonly'] = true;
 
 		return $this;
 	}
 
-	public function is_readonly(): bool {
-		return $this->attributes['readonly'] ?? false;
+	final public function is_readonly(): bool {
+		return $this->attributes['readonly'];
 	}
 
-	public function set_required(): Field {
-		$this->meta['required'] = true;
+	final public function set_required(): Field {
+		$this->attributes['required'] = true;
 
 		return $this;
 	}
 
-	public function add_class( string $class_name ): Field {
-		$this->meta['class'][ $class_name ] = $class_name;
+	final public function add_class( string $class_name ): Field {
+		$this->attributes['class'][ $class_name ] = $class_name;
 
 		return $this;
 	}
 
-	public function unset_class( string $class_name ): Field {
-		unset( $this->meta['class'][ $class_name ] );
+	final public function unset_class( string $class_name ): Field {
+		unset( $this->attributes['class'][ $class_name ] );
 
 		return $this;
 	}
 
-	public function add_data( string $data_name, string $data_value ): Field {
-		if ( ! isset( $this->meta['data'] ) ) {
+	final public function add_data( string $data_name, string $data_value ): Field {
+		if ( empty( $this->meta['data'] ) ) {
 			$this->meta['data'] = [];
 		}
 		$this->meta['data'][ $data_name ] = $data_value;
@@ -186,28 +187,26 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function unset_data( string $data_name ): Field {
+	final public function unset_data( string $data_name ): Field {
 		unset( $this->meta['data'][ $data_name ] );
 
 		return $this;
 	}
 
-	public function is_meta_value_set( string $name ): bool {
-		return isset( $this->meta[ $name ] );
+	final public function is_meta_value_set( string $name ): bool {
+		return ! empty( $this->meta[ $name ] );
 	}
 
-	public function is_class_set( string $name ): bool {
-		return isset( $this->meta['class'][ $name ] );
+	final public function is_class_set( string $name ): bool {
+		return ! empty( $this->attributes['class'][ $name ] );
 	}
 
-	/** @return mixed */
-	public function get_default_value() {
-		return $this->default_value;
+	final public function get_default_value(): string {
+		return $this->meta['default_value'];
 	}
 
-	/** @param mixed $value */
-	public function set_default_value( $value ): Field {
-		$this->default_value = $value;
+	final public function set_default_value( string $value ): Field {
+		$this->meta['default_value'] = $value;
 
 		return $this;
 	}
@@ -221,16 +220,16 @@ abstract class BasicField implements Field {
 		return $chain;
 	}
 
-	public function is_required(): bool {
-		return $this->meta['required'] ?? false;
+	final public function is_required(): bool {
+		return $this->attributes['required'];
 	}
 
 	public function get_sanitizer(): Sanitizer {
 		return new NoSanitize();
 	}
 
-	public function get_serializer(): Serializer {
-		if ( isset( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
+	final public function get_serializer(): Serializer {
+		if ( ! empty( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
 			return $this->meta['serializer'];
 		}
 
@@ -243,7 +242,7 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_priority(): int {
+	final public function get_priority(): int {
 		return $this->meta['priority'];
 	}
 
@@ -252,7 +251,7 @@ abstract class BasicField implements Field {
 	 *
 	 * @see FormWithFields::get_fields()
 	 */
-	public function set_priority( int $priority ): Field {
+	final public function set_priority( int $priority ): Field {
 		$this->meta['priority'] = $priority;
 
 		return $this;
diff --git a/src/Field/ButtonField.php b/src/Field/ButtonField.php
index f0a4023..6d01a1f 100644
--- a/src/Field/ButtonField.php
+++ b/src/Field/ButtonField.php
@@ -3,10 +3,10 @@
 namespace WPDesk\Forms\Field;
 
 class ButtonField extends NoValueField {
-
 	public function get_template_name(): string {
 		return 'button';
 	}
+
 	public function get_type(): string {
 		return 'button';
 	}
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index 507cda0..d55269e 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -8,9 +8,8 @@ class CheckboxField extends BasicField {
 	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
 
-	public function __construct() {
-		parent::__construct();
-		$this->set_attribute( 'type', 'checkbox' );
+	public function get_type(): string {
+		return 'checkbox';
 	}
 
 	public function get_template_name(): string {
diff --git a/src/Field/DatePickerField.php b/src/Field/DatePickerField.php
index 7060d90..7a69247 100644
--- a/src/Field/DatePickerField.php
+++ b/src/Field/DatePickerField.php
@@ -7,11 +7,8 @@ use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class DatePickerField extends BasicField {
 	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
 		$this->add_class( 'date-picker' );
 		$this->set_placeholder( 'YYYY-MM-DD' );
-		$this->set_attribute( 'type', 'text' );
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/Header.php b/src/Field/Header.php
index cebe249..a704f40 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -6,7 +6,6 @@ use WPDesk\Forms\Field;
 
 class Header extends NoValueField {
 	public function __construct() {
-		parent::__construct();
 		$this->meta['header_size'] = '';
 	}
 
diff --git a/src/Field/HiddenField.php b/src/Field/HiddenField.php
index 9c3856c..e48742c 100644
--- a/src/Field/HiddenField.php
+++ b/src/Field/HiddenField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class HiddenField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'hidden' );
+	public function get_type(): string {
+		return 'hidden';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/ImageInputField.php b/src/Field/ImageInputField.php
index 74c8410..1f58ec5 100644
--- a/src/Field/ImageInputField.php
+++ b/src/Field/ImageInputField.php
@@ -4,12 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class ImageInputField extends BasicField {
 
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'text' );
-	}
-
 	public function get_template_name(): string {
 		return 'input-image';
 	}
diff --git a/src/Field/InputEmailField.php b/src/Field/InputEmailField.php
index ee18412..a54ab4a 100644
--- a/src/Field/InputEmailField.php
+++ b/src/Field/InputEmailField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\EmailSanitizer;
 
 class InputEmailField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'email' );
+	public function get_type(): string {
+		return 'email';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/InputNumberField.php b/src/Field/InputNumberField.php
index 9ee7405..380da44 100644
--- a/src/Field/InputNumberField.php
+++ b/src/Field/InputNumberField.php
@@ -6,10 +6,8 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputNumberField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'number' );
+	public function get_type(): string {
+		return 'number';
 	}
 
 	public function get_sanitizer(): Sanitizer {
diff --git a/src/Field/InputTextField.php b/src/Field/InputTextField.php
index 7ca6a96..24b0fa6 100644
--- a/src/Field/InputTextField.php
+++ b/src/Field/InputTextField.php
@@ -6,12 +6,6 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputTextField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-		$this->set_attribute( 'type', 'text' );
-	}
-
 	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
diff --git a/src/Field/MultipleInputTextField.php b/src/Field/MultipleInputTextField.php
index cf976fe..6648e2a 100644
--- a/src/Field/MultipleInputTextField.php
+++ b/src/Field/MultipleInputTextField.php
@@ -3,7 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class MultipleInputTextField extends InputTextField {
-
 	public function get_template_name(): string {
 		return 'input-text-multiple';
 	}
diff --git a/src/Field/NoOnceField.php b/src/Field/NoOnceField.php
index 6419a37..17ac6e0 100644
--- a/src/Field/NoOnceField.php
+++ b/src/Field/NoOnceField.php
@@ -7,8 +7,7 @@ use WPDesk\Forms\Validator\NonceValidator;
 
 class NoOnceField extends BasicField {
 
-	public function __construct( $action_name ) {
-		parent::__construct();
+	public function __construct( string $action_name ) {
 		$this->meta['action'] = $action_name;
 	}
 
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 8960304..2a10e46 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class ProductSelect extends SelectField {
 	public function __construct() {
-		parent::__construct();
 		$this->set_multiple();
 	}
 
diff --git a/src/Field/TextAreaField.php b/src/Field/TextAreaField.php
index 0f83ffe..f22b2bb 100644
--- a/src/Field/TextAreaField.php
+++ b/src/Field/TextAreaField.php
@@ -3,10 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class TextAreaField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-	}
 
 	public function get_template_name(): string {
 		return 'textarea';
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 5ae190a..71eccba 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -9,30 +9,44 @@ namespace WPDesk\Forms\Field\Traits;
  */
 trait HtmlAttributes {
 
-	/** @var string[] */
-	protected $attributes;
+	/** @var array{placeholder: string, name: string, id: string, class: string[], readonly: bool, multiple: bool, disabled: bool, required: bool, method: string, action: string} */
+	protected $attributes = [
+		'placeholder' => '',
+		'name'        => '',
+		'id'          => '',
+		'class'       => [],
+		'action'      => '',
+		'method'      => 'POST',
+		'readonly'    => false,
+		'multiple'    => false,
+		'disabled'    => false,
+		'required'    => false,
+	];
 
 	/**
 	 * Get list of all attributes except given.
 	 *
 	 * @param string[] $except
 	 *
-	 * @return string[]
+	 * @return array<string[]|string|bool>
 	 */
-	public function get_attributes( array $except = [ 'name', 'type' ] ): array {
+	final public function get_attributes( array $except = [ 'name' ] ): array {
 		return array_filter(
 			$this->attributes,
-			static function ( $value, $key ) use ( $except ) {
+			static function ( $key ) use ( $except ) {
 				return ! in_array( $key, $except, true );
 			},
-			ARRAY_FILTER_USE_BOTH
+			ARRAY_FILTER_USE_KEY
 		);
 	}
 
 	/**
+	 * @param string $name
+	 * @param string[]|string|bool $value
+	 *
 	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
 	 */
-	public function set_attribute( string $name, string $value ) {
+	final public function set_attribute( string $name, $value ) {
 		$this->attributes[ $name ] = $value;
 
 		return $this;
@@ -41,17 +55,21 @@ trait HtmlAttributes {
 	/**
 	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
 	 */
-	public function unset_attribute( string $name ) {
+	final public function unset_attribute( string $name ) {
 		unset( $this->attributes[ $name ] );
 
 		return $this;
 	}
 
-	public function is_attribute_set( string $name ): bool {
-		return isset( $this->attributes[ $name ] );
+	final public function is_attribute_set( string $name ): bool {
+		return ! empty( $this->attributes[ $name ] );
 	}
 
-	public function get_attribute( string $name, string $default = null ): string {
-		return $this->attributes[ $name ] ?? $default ?? '';
+	final public function get_attribute( string $name, string $default = null ): string {
+		if ( is_array( $this->attributes[ $name ] ) ) {
+			// Be aware of coercing - if implode returns string(0) '', then return $default value.
+			return implode( ' ', $this->attributes[ $name ] ) ?: $default ?? '';
+		}
+		return (string) $this->attributes[ $name ] ?? $default ?? '';
 	}
 }
diff --git a/src/Field/WooSelect.php b/src/Field/WooSelect.php
index bc59f9c..ec2719c 100644
--- a/src/Field/WooSelect.php
+++ b/src/Field/WooSelect.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms\Field;
 
 class WooSelect extends SelectField {
 	public function __construct() {
-		parent::__construct();
 		$this->set_multiple();
 		$this->add_class( 'wc-enhanced-select' );
 	}
diff --git a/src/Field/WyswigField.php b/src/Field/WyswigField.php
index 06db980..a2f4168 100644
--- a/src/Field/WyswigField.php
+++ b/src/Field/WyswigField.php
@@ -3,11 +3,6 @@
 namespace WPDesk\Forms\Field;
 
 class WyswigField extends BasicField {
-	public function __construct() {
-		parent::__construct();
-		$this->set_default_value( '' );
-	}
-
 	public function get_template_name(): string {
 		return 'wyswig';
 	}
diff --git a/src/FieldsDataReceiver.php b/src/FieldsDataReceiver.php
index 86a1583..e41743d 100644
--- a/src/FieldsDataReceiver.php
+++ b/src/FieldsDataReceiver.php
@@ -2,8 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use Psr\Container\ContainerInterface;
-
 /**
  * Some field owners can receive and process field data.
  * Probably should be used with FieldProvider interface.
@@ -16,5 +14,5 @@ interface FieldsDataReceiver {
 	 *
 	 * @return void
 	 */
-	public function update_fields_data( ContainerInterface $data );
+	public function update_fields_data( \Psr\Container\ContainerInterface $data );
 }
diff --git a/src/Form.php b/src/Form.php
index 504ebbe..5f8725d 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms;
 
+use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
 
 /**
@@ -35,15 +36,6 @@ interface Form {
 	 */
 	public function handle_request( array $request = [] );
 
-	/**
-	 * Data could be saved in some place. Use this method to transmit them to form.
-	 *
-	 * @param array $data Data for form.
-	 *
-	 * @return void
-	 */
-	public function set_data( $data );
-
 	/**
 	 * Use to render the form to string.
 	 *
@@ -54,7 +46,7 @@ interface Form {
 	/**
 	 * Get data from form. Use after handle_request or set_data.
 	 *
-	 * @return array<int,string>
+	 * @return array<int|string>
 	 */
 	public function get_data(): array;
 
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index ba13928..ac0f159 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -7,7 +7,6 @@ use WPDesk\Forms\ContainerForm;
 use WPDesk\Forms\Field;
 use WPDesk\Forms\FieldProvider;
 use WPDesk\Forms\Form;
-use WPDesk\Persistence\Adapter\ArrayContainer;
 use WPDesk\Persistence\ElementNotExistsException;
 use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
@@ -50,11 +49,11 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	}
 
 	public function get_method(): string {
-		return $this->attributes['method'] ?? 'POST';
+		return $this->attributes['method'];
 	}
 
 	public function get_action(): string {
-		return $this->attributes['action'] ?? '';
+		return $this->attributes['action'];
 	}
 
 	public function is_submitted(): bool {
@@ -113,14 +112,9 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	/**
 	 * Data could be saved in some place. Use this method to transmit them to form.
 	 *
-	 * @param array|ContainerInterface $data Data consistent with Form or ContainerForm interface.
-	 *
 	 * @return void
 	 */
-	public function set_data( $data ) {
-		if ( is_array( $data ) ) {
-			$data = new ArrayContainer( $data );
-		}
+	public function set_data( ContainerInterface $data ) {
 		foreach ( $this->fields as $field ) {
 			$data_key = $field->get_name();
 			if ( $data->has( $data_key ) ) {
diff --git a/src/Sanitizer.php b/src/Sanitizer.php
index bc8f207..3f57eac 100644
--- a/src/Sanitizer.php
+++ b/src/Sanitizer.php
@@ -3,6 +3,10 @@
 namespace WPDesk\Forms;
 
 interface Sanitizer {
-	/** @param mixed $value */
-	public function sanitize( $value ): string;
+	/**
+	 * @param mixed $value
+	 *
+	 * @return mixed
+	 */
+	public function sanitize( $value );
 }
diff --git a/src/Sanitizer/NoSanitize.php b/src/Sanitizer/NoSanitize.php
index 21bce01..a3fe4a6 100644
--- a/src/Sanitizer/NoSanitize.php
+++ b/src/Sanitizer/NoSanitize.php
@@ -5,7 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class NoSanitize implements Sanitizer {
-	public function sanitize( $value ): string {
+	public function sanitize( $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer.php b/src/Serializer.php
index 8302325..2096b0f 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -5,15 +5,11 @@ namespace WPDesk\Forms;
 interface Serializer {
 	/**
 	 * @param mixed $value
-	 *
-	 * @return mixed
 	 */
-	public function serialize( $value );
+	public function serialize( $value ): string;
 
 	/**
-	 * @param mixed $value
-	 *
 	 * @return mixed
 	 */
-	public function unserialize( $value );
+	public function unserialize( string $value );
 }
diff --git a/src/Serializer/JsonSerializer.php b/src/Serializer/JsonSerializer.php
index bc8c0e0..9ded064 100644
--- a/src/Serializer/JsonSerializer.php
+++ b/src/Serializer/JsonSerializer.php
@@ -9,7 +9,7 @@ class JsonSerializer implements Serializer {
 		return (string) json_encode( $value );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return json_decode( $value, true );
 	}
 }
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
index b29e88b..371e8e7 100644
--- a/src/Serializer/NoSerialize.php
+++ b/src/Serializer/NoSerialize.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class NoSerialize implements Serializer {
-	public function serialize( $value ) {
-		return $value;
+	public function serialize( $value ): string {
+		return (string) $value;
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer/ProductSelectSerializer.php b/src/Serializer/ProductSelectSerializer.php
index e801d4d..7c4f0e8 100644
--- a/src/Serializer/ProductSelectSerializer.php
+++ b/src/Serializer/ProductSelectSerializer.php
@@ -10,7 +10,7 @@ use WPDesk\Forms\Serializer;
  * @package WPDesk\Forms\Serializer
  */
 class ProductSelectSerializer implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		$products_with_names = [];
 		if ( is_array( $value ) ) {
 			foreach ( $value as $product_id ) {
@@ -22,10 +22,10 @@ class ProductSelectSerializer implements Serializer {
 			}
 		}
 
-		return $products_with_names;
+		return implode( ' ', $products_with_names );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return $value;
 	}
 
diff --git a/src/Serializer/SerializeSerializer.php b/src/Serializer/SerializeSerializer.php
index 79d13f6..dde47cc 100644
--- a/src/Serializer/SerializeSerializer.php
+++ b/src/Serializer/SerializeSerializer.php
@@ -5,11 +5,11 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class SerializeSerializer implements Serializer {
-	public function serialize( $value ) {
+	public function serialize( $value ): string {
 		return serialize( $value );
 	}
 
-	public function unserialize( $value ) {
+	public function unserialize( string $value ) {
 		return unserialize( $value );
 	}
 
diff --git a/src/Validator/NonceValidator.php b/src/Validator/NonceValidator.php
index 8709af6..b887428 100644
--- a/src/Validator/NonceValidator.php
+++ b/src/Validator/NonceValidator.php
@@ -6,14 +6,16 @@ use WPDesk\Forms\Validator;
 
 class NonceValidator implements Validator {
 
+	/** @var string */
 	private $action;
 
+	/** @param string $action */
 	public function __construct( $action ) {
 		$this->action = $action;
 	}
 
 	public function is_valid( $value ): bool {
-		return wp_verify_nonce( $value, $this->action );
+		return (bool) wp_verify_nonce( $value, $this->action );
 	}
 
 	public function get_messages(): array {
-- 
GitLab


From dbac409784528eaf7168c9a84e507505ee25cccd Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Thu, 16 Sep 2021 12:30:40 +0200
Subject: [PATCH 25/39] refactor: remove NoSerialize class, due to false
 serializing process

---
 src/ContainerForm.php                        |  1 -
 src/Field/BasicField.php                     | 69 +++++++++-----------
 src/Field/NoValueField.php                   |  4 +-
 src/Form.php                                 |  1 -
 src/Form/FormWithFields.php                  |  2 -
 src/Persistence/FieldPersistenceStrategy.php | 12 +++-
 src/Serializer/NoSerialize.php               | 16 -----
 7 files changed, 43 insertions(+), 62 deletions(-)
 delete mode 100644 src/Serializer/NoSerialize.php

diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index bd5fc82..d79b57f 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms;
 
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
-use Psr\Container\ContainerInterface;
 
 /**
  * Persistent container support for forms.
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 2855357..8e1a7e0 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -6,7 +6,6 @@ use WPDesk\Forms\Field;
 use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
-use WPDesk\Forms\Serializer\NoSerialize;
 use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\ChainValidator;
 use WPDesk\Forms\Validator\RequiredValidator;
@@ -33,6 +32,35 @@ abstract class BasicField implements Field {
 		'serializer'        => null,
 	];
 
+	public function should_override_form_template(): bool {
+		return false;
+	}
+
+	public function get_type(): string {
+		return 'text';
+	}
+
+	public function get_validator(): Validator {
+		$chain = new ChainValidator();
+		if ( $this->is_required() ) {
+			$chain->attach( new RequiredValidator() );
+		}
+
+		return $chain;
+	}
+
+	public function get_sanitizer(): Sanitizer {
+		return new NoSanitize();
+	}
+
+	public function get_serializer(): Serializer {
+		return null;
+	}
+
+	final public function get_name(): string {
+		return $this->attributes['name'];
+	}
+
 	final public function get_label(): string {
 		return $this->meta['label'];
 	}
@@ -51,11 +79,6 @@ abstract class BasicField implements Field {
 		return ! empty( $this->meta['description_tip'] );
 	}
 
-	/** Override method if you need. */
-	public function should_override_form_template(): bool {
-		return false;
-	}
-
 	final public function get_description(): string {
 		return $this->meta['description'];
 	}
@@ -80,10 +103,6 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_type(): string {
-		return 'text';
-	}
-
 	final public function set_placeholder( string $value ): Field {
 		$this->attributes['placeholder'] = $value;
 
@@ -132,9 +151,6 @@ abstract class BasicField implements Field {
 		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
-	public function get_name(): string {
-		return $this->attributes['name'];
-	}
 
 	final public function is_multiple(): bool {
 		return $this->attributes['multiple'];
@@ -211,35 +227,12 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_validator(): Validator {
-		$chain = new ChainValidator();
-		if ( $this->is_required() ) {
-			$chain->attach( new RequiredValidator() );
-		}
-
-		return $chain;
-	}
-
 	final public function is_required(): bool {
 		return $this->attributes['required'];
 	}
 
-	public function get_sanitizer(): Sanitizer {
-		return new NoSanitize();
-	}
-
-	final public function get_serializer(): Serializer {
-		if ( ! empty( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
-			return $this->meta['serializer'];
-		}
-
-		return new NoSerialize();
-	}
-
-	public function set_serializer( Serializer $serializer ): Field {
-		$this->meta['serializer'] = $serializer;
-
-		return $this;
+	final public function has_serializer(): bool {
+		return ! empty( $this->meta['serializer'] );
 	}
 
 	final public function get_priority(): int {
diff --git a/src/Field/NoValueField.php b/src/Field/NoValueField.php
index 90bbecb..5309170 100644
--- a/src/Field/NoValueField.php
+++ b/src/Field/NoValueField.php
@@ -8,7 +8,7 @@ namespace WPDesk\Forms\Field;
  * @package WPDesk\Forms
  */
 abstract class NoValueField extends BasicField {
-	public function get_name(): string {
-		return '';
+	public function __construct() {
+		$this->set_name( '' );
 	}
 }
diff --git a/src/Form.php b/src/Form.php
index 5f8725d..6fc5c0f 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
 
 /**
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index ac0f159..de48e33 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -94,8 +94,6 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 
 	/**
 	 * Add array to update data.
-	 *
-	 * @param array|ContainerInterface $request new data to update.
 	 */
 	public function handle_request( array $request = [] ) {
 		if ( $this->updated_data === null ) {
diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php
index 02f2d4f..7a70cd5 100644
--- a/src/Persistence/FieldPersistenceStrategy.php
+++ b/src/Persistence/FieldPersistenceStrategy.php
@@ -26,7 +26,11 @@ class FieldPersistenceStrategy {
 	public function persist_fields( FieldProvider $fields_provider, array $data ) {
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
-			$this->persistence->set( $field_key, $field->get_serializer()->serialize( $data[ $field_key ] ) );
+			if ( $field->has_serializer() ) {
+				$this->persistence->set( $field_key, $field->get_serializer()->serialize( $data[ $field_key ] ) );
+			} else {
+				$this->persistence->set( $field_key, $data[ $field_key ] );
+			}
 		}
 	}
 
@@ -38,7 +42,11 @@ class FieldPersistenceStrategy {
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
 			try {
-				$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
+				if ( $field->has_serializer() ) {
+					$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
+				} else {
+					$data[ $field_key ] = $this->persistence->get( $field_key );
+				}
 			} catch ( NotFoundExceptionInterface $not_found ) {
 				// TODO: Logger
 				// LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
deleted file mode 100644
index 371e8e7..0000000
--- a/src/Serializer/NoSerialize.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Serializer;
-
-use WPDesk\Forms\Serializer;
-
-class NoSerialize implements Serializer {
-	public function serialize( $value ): string {
-		return (string) $value;
-	}
-
-	public function unserialize( string $value ) {
-		return $value;
-	}
-
-}
-- 
GitLab


From dad216539349605cf091525539d4534a08fc151b Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Thu, 16 Sep 2021 17:29:58 +0200
Subject: [PATCH 26/39] feat: throw Exception, when accessing non-existing
 Serializer

---
 README.md                                    |  8 ++++----
 changelog.txt                                | 13 +++++++++++++
 src/Field.php                                |  2 ++
 src/Field/BasicField.php                     | 13 ++++++-------
 src/Field/ProductSelect.php                  | 11 +++++++++++
 src/Field/TimepickerField.php                | 11 +++++++++++
 src/Persistence/FieldPersistenceStrategy.php |  8 ++------
 7 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/README.md b/README.md
index 519d15f..c129e94 100644
--- a/README.md
+++ b/README.md
@@ -50,11 +50,11 @@ interface SettingsTab {
 	/**
 	 * Use to set settings from database or defaults.
 	 *
-	 * @param array|ContainerInterface $data Data to render.
+	 * @param ContainerInterface $data Data to render.
 	 *
 	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Use to handle request data from POST.
@@ -102,11 +102,11 @@ abstract class FieldSettingsTab implements SettingsTab {
 		return $this->get_form()->render_form( $renderer );
 	}
 
-	public function set_data( $data ) {
+	public function set_data( ContainerInterface $data ) {
 		$this->get_form()->set_data( $data );
 	}
 
-	public function handle_request( $request ) {
+	public function handle_request( array $request ) {
 		$this->get_form()->handle_request( $request );
 	}
 
diff --git a/changelog.txt b/changelog.txt
index 476dabe..0fba0c8 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,18 @@
 # Changelog
 
+## [3.0.0]
+### Added
+- Added strong typing to all of the interfaces
+- Added fields sorting by priority field
+- Normalized string escaping in all template files
+- Added InputEmailField and EmailSerializer classes
+### Changed
+- All getters and setter in BasicField are now declared final
+- FormWithFields accepts only ContainerInterface in ::set_data() method. Prepare data before passing it
+### Removed
+- Removed deprecated classes
+- Removed NoSerialize class
+
 ## [2.4.7] - 2021-09-20
 ### Fixed
 - Add missing escaping functions in templates
diff --git a/src/Field.php b/src/Field.php
index 311d8eb..08329e7 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -91,5 +91,7 @@ interface Field {
 
 	public function get_serializer(): Serializer;
 
+	public function has_serializer(): bool;
+
 	public function get_priority(): int;
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 8e1a7e0..4c1dc0c 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -21,7 +21,7 @@ abstract class BasicField implements Field {
 
 	const DEFAULT_PRIORITY = 10;
 
-	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>, serializer: ?Serializer} */
+	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>} */
 	protected $meta = [
 		'priority'          => self::DEFAULT_PRIORITY,
 		'default_value'     => '',
@@ -29,7 +29,6 @@ abstract class BasicField implements Field {
 		'description'       => '',
 		'description_tip'   => '',
 		'data'              => [],
-		'serializer'        => null,
 	];
 
 	public function should_override_form_template(): bool {
@@ -53,8 +52,12 @@ abstract class BasicField implements Field {
 		return new NoSanitize();
 	}
 
+	public function has_serializer(): bool {
+		return false;
+	}
+
 	public function get_serializer(): Serializer {
-		return null;
+		throw new \BadMethodCallException('You must define your serializer in a child class.');
 	}
 
 	final public function get_name(): string {
@@ -231,10 +234,6 @@ abstract class BasicField implements Field {
 		return $this->attributes['required'];
 	}
 
-	final public function has_serializer(): bool {
-		return ! empty( $this->meta['serializer'] );
-	}
-
 	final public function get_priority(): int {
 		return $this->meta['priority'];
 	}
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 2a10e46..8d8b5e6 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -2,11 +2,22 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Serializer\ProductSelectSerializer;
+use WPDesk\Forms\Serializer;
+
 class ProductSelect extends SelectField {
 	public function __construct() {
 		$this->set_multiple();
 	}
 
+	public function has_serializer(): bool {
+		return true;
+	}
+
+	public function get_serializer(): Serializer {
+		return new ProductSelectSerializer();
+	}
+
 	public function get_template_name(): string {
 		return 'product-select';
 	}
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index 8468254..c7c1a5d 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -2,7 +2,18 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Serializer;
+use WPDesk\Forms\Serializer\JsonSerializer;
+
 class TimepickerField extends BasicField {
+	public function has_serializer(): bool {
+		return true;
+	}
+
+	public function get_serializer(): Serializer {
+		return new JsonSerializer();
+	}
+
 	public function get_template_name(): string {
 		return 'timepicker';
 	}
diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php
index 7a70cd5..3102f1c 100644
--- a/src/Persistence/FieldPersistenceStrategy.php
+++ b/src/Persistence/FieldPersistenceStrategy.php
@@ -20,9 +20,7 @@ class FieldPersistenceStrategy {
 		$this->persistence = $persistence;
 	}
 
-	/**
-	 * Save fields data.
-	 */
+	/** @return void */
 	public function persist_fields( FieldProvider $fields_provider, array $data ) {
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
@@ -34,9 +32,7 @@ class FieldPersistenceStrategy {
 		}
 	}
 
-	/**
-	 * Load fields data.
-	 */
+	/** @return void */
 	public function load_fields( FieldProvider $fields_provider ): array {
 		$data = [];
 		foreach ( $fields_provider->get_fields() as $field ) {
-- 
GitLab


From 679dcfd9f7ca197004d2f9da0f0183126442f55d Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bartek.jaskulski@wpdesk.net>
Date: Mon, 20 Sep 2021 11:26:37 +0200
Subject: [PATCH 27/39] fix: use appropiate escaping function in url

---
 templates/input-image.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/templates/input-image.php b/templates/input-image.php
index 313e0e6..5111c4c 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -13,15 +13,15 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 			id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
 	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
-            <img src="<?php echo \esc_html( $value ) ?>" alt="" width="100"/>
+            <img src="<?php echo \esc_url( $value ) ?>" alt="" width="100"/>
 		<?php endif; ?>
     </div>
     <p class="hide-if-no-js">
-        <a class="upload-custom-img <?php if ( $value ): ?>hidden<?php endif ?>" href="<?php echo \esc_html( $value ) ?>">
-			<?php _e( 'Set image', 'wp-forms' ) ?>
+        <a class="upload-custom-img <?php if ( $value ): ?>hidden<?php endif ?>" href="<?php echo \esc_url( $value ) ?>">
+			<?php \esc_html_e( 'Set image', 'wp-forms' ) ?>
         </a>
         <a class="delete-custom-img <?php if ( ! $value ): ?>hidden<?php endif ?>" href="#">
-			<?php _e( 'Remove image', 'wp-forms' ) ?>
+			<?php \esc_html_e( 'Remove image', 'wp-forms' ) ?>
         </a>
     </p>
 </div>
-- 
GitLab


From dc8237b4401f844e4b6f234af63d4ee555727c30 Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Tue, 5 Oct 2021 18:48:39 +0200
Subject: [PATCH 28/39] fix: devel merge, reformat

---
 composer.json                              |  2 +-
 src/ContainerForm.php                      |  2 +-
 src/Escaper.php                            |  1 +
 src/Field.php                              |  1 +
 src/Field/BasicField.php                   |  4 +++-
 src/Field/ButtonField.php                  |  1 +
 src/Field/CheckboxField.php                |  1 +
 src/Field/DatePickerField.php              |  1 +
 src/Field/Header.php                       |  2 ++
 src/Field/HiddenField.php                  |  1 +
 src/Field/InputEmailField.php              |  1 +
 src/Field/InputNumberField.php             |  1 +
 src/Field/InputTextField.php               |  1 +
 src/Field/MultipleInputTextField.php       |  1 +
 src/Field/NoValueField.php                 |  1 +
 src/Field/Paragraph.php                    |  1 +
 src/Field/ProductSelect.php                |  1 +
 src/Field/RadioField.php                   |  1 +
 src/Field/SubmitField.php                  |  1 +
 src/Field/TimepickerField.php              |  1 +
 src/Field/Traits/HtmlAttributes.php        |  7 ++++--
 src/Field/WooSelect.php                    |  1 +
 src/Field/WyswigField.php                  |  1 +
 src/FieldProvider.php                      |  1 +
 src/FieldRenderer.php                      |  1 +
 src/FieldsDataReceiver.php                 |  5 +++-
 src/Form.php                               |  2 +-
 src/Sanitizer.php                          |  1 +
 src/Sanitizer/EmailSanitizer.php           |  1 +
 src/Sanitizer/NoSanitize.php               |  1 +
 src/Sanitizer/TextFieldSanitizer.php       |  1 +
 src/Serializer.php                         |  1 +
 src/Serializer/JsonSerializer.php          |  1 +
 src/Serializer/ProductSelectSerializer.php |  1 +
 src/Serializer/SerializeSerializer.php     |  1 +
 src/Validator.php                          |  1 +
 src/Validator/NoValidateValidator.php      |  1 +
 src/Validator/RequiredValidator.php        |  1 +
 templates/button.php                       |  1 +
 templates/form-field.php                   | 10 ++++----
 templates/form-label.php                   |  2 +-
 templates/input-checkbox.php               | 18 +++++++-------
 templates/input-date-picker.php            | 18 +++++++-------
 templates/input-hidden.php                 | 18 +++++++-------
 templates/input-image.php                  | 28 ++++++++++++++--------
 templates/input-number.php                 | 18 +++++++-------
 templates/input-radio.php                  | 18 +++++++-------
 templates/input-text.php                   | 18 +++++++-------
 48 files changed, 120 insertions(+), 84 deletions(-)

diff --git a/composer.json b/composer.json
index 8150bcf..03b48b4 100644
--- a/composer.json
+++ b/composer.json
@@ -20,7 +20,7 @@
 		"ext-curl": "*",
 		"ext-json": "*",
 		"wpdesk/wp-persistence": "^2.0|^3.0",
-		"wpdesk/wp-view": "^1.1"
+		"wpdesk/wp-view": "^2"
 	},
 	"require-dev": {
 		"phpunit/phpunit": "<7",
diff --git a/src/ContainerForm.php b/src/ContainerForm.php
index bd5fc82..e3b6dde 100644
--- a/src/ContainerForm.php
+++ b/src/ContainerForm.php
@@ -4,7 +4,6 @@ namespace WPDesk\Forms;
 
 use Psr\Container\ContainerInterface;
 use WPDesk\Persistence\PersistentContainer;
-use Psr\Container\ContainerInterface;
 
 /**
  * Persistent container support for forms.
@@ -12,6 +11,7 @@ use Psr\Container\ContainerInterface;
  * @package WPDesk\Forms
  */
 interface ContainerForm {
+
 	/**
 	 * @param ContainerInterface $data
 	 *
diff --git a/src/Escaper.php b/src/Escaper.php
index 8c460dd..462295c 100644
--- a/src/Escaper.php
+++ b/src/Escaper.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms;
 
 interface Escaper {
+
 	/** @param mixed $value */
 	public function escape( $value ): string;
 }
diff --git a/src/Field.php b/src/Field.php
index 08329e7..b932f27 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -11,6 +11,7 @@ namespace WPDesk\Forms;
  * @package WPDesk\Forms
  */
 interface Field {
+
 	public function get_name(): string;
 
 	/** @return mixed */
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 4c1dc0c..c1d5270 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Field;
 
+use BadMethodCallException;
 use WPDesk\Forms\Field;
 use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
@@ -17,6 +18,7 @@ use WPDesk\Forms\Validator\RequiredValidator;
  * @package WPDesk\Forms
  */
 abstract class BasicField implements Field {
+
 	use Field\Traits\HtmlAttributes;
 
 	const DEFAULT_PRIORITY = 10;
@@ -57,7 +59,7 @@ abstract class BasicField implements Field {
 	}
 
 	public function get_serializer(): Serializer {
-		throw new \BadMethodCallException('You must define your serializer in a child class.');
+		throw new BadMethodCallException('You must define your serializer in a child class.');
 	}
 
 	final public function get_name(): string {
diff --git a/src/Field/ButtonField.php b/src/Field/ButtonField.php
index 6d01a1f..1a43c3f 100644
--- a/src/Field/ButtonField.php
+++ b/src/Field/ButtonField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class ButtonField extends NoValueField {
+
 	public function get_template_name(): string {
 		return 'button';
 	}
diff --git a/src/Field/CheckboxField.php b/src/Field/CheckboxField.php
index d55269e..1411029 100644
--- a/src/Field/CheckboxField.php
+++ b/src/Field/CheckboxField.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Field;
 use WPDesk\Forms\Field;
 
 class CheckboxField extends BasicField {
+
 	const VALUE_TRUE  = 'yes';
 	const VALUE_FALSE = 'no';
 
diff --git a/src/Field/DatePickerField.php b/src/Field/DatePickerField.php
index 7a69247..2ec2160 100644
--- a/src/Field/DatePickerField.php
+++ b/src/Field/DatePickerField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class DatePickerField extends BasicField {
+
 	public function __construct() {
 		$this->add_class( 'date-picker' );
 		$this->set_placeholder( 'YYYY-MM-DD' );
diff --git a/src/Field/Header.php b/src/Field/Header.php
index a704f40..b588b8f 100644
--- a/src/Field/Header.php
+++ b/src/Field/Header.php
@@ -5,7 +5,9 @@ namespace WPDesk\Forms\Field;
 use WPDesk\Forms\Field;
 
 class Header extends NoValueField {
+
 	public function __construct() {
+		parent::__construct();
 		$this->meta['header_size'] = '';
 	}
 
diff --git a/src/Field/HiddenField.php b/src/Field/HiddenField.php
index e48742c..ff06bdc 100644
--- a/src/Field/HiddenField.php
+++ b/src/Field/HiddenField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class HiddenField extends BasicField {
+
 	public function get_type(): string {
 		return 'hidden';
 	}
diff --git a/src/Field/InputEmailField.php b/src/Field/InputEmailField.php
index a54ab4a..36325f3 100644
--- a/src/Field/InputEmailField.php
+++ b/src/Field/InputEmailField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\EmailSanitizer;
 
 class InputEmailField extends BasicField {
+
 	public function get_type(): string {
 		return 'email';
 	}
diff --git a/src/Field/InputNumberField.php b/src/Field/InputNumberField.php
index 380da44..84aac99 100644
--- a/src/Field/InputNumberField.php
+++ b/src/Field/InputNumberField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputNumberField extends BasicField {
+
 	public function get_type(): string {
 		return 'number';
 	}
diff --git a/src/Field/InputTextField.php b/src/Field/InputTextField.php
index 24b0fa6..92f473d 100644
--- a/src/Field/InputTextField.php
+++ b/src/Field/InputTextField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\TextFieldSanitizer;
 
 class InputTextField extends BasicField {
+
 	public function get_sanitizer(): Sanitizer {
 		return new TextFieldSanitizer();
 	}
diff --git a/src/Field/MultipleInputTextField.php b/src/Field/MultipleInputTextField.php
index 6648e2a..cf976fe 100644
--- a/src/Field/MultipleInputTextField.php
+++ b/src/Field/MultipleInputTextField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class MultipleInputTextField extends InputTextField {
+
 	public function get_template_name(): string {
 		return 'input-text-multiple';
 	}
diff --git a/src/Field/NoValueField.php b/src/Field/NoValueField.php
index 5309170..a84a1a7 100644
--- a/src/Field/NoValueField.php
+++ b/src/Field/NoValueField.php
@@ -8,6 +8,7 @@ namespace WPDesk\Forms\Field;
  * @package WPDesk\Forms
  */
 abstract class NoValueField extends BasicField {
+
 	public function __construct() {
 		$this->set_name( '' );
 	}
diff --git a/src/Field/Paragraph.php b/src/Field/Paragraph.php
index 6e74de3..253eea0 100644
--- a/src/Field/Paragraph.php
+++ b/src/Field/Paragraph.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class Paragraph extends NoValueField {
+
 	public function get_template_name(): string {
 		return 'paragraph';
 	}
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 8d8b5e6..ff14f8e 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Serializer\ProductSelectSerializer;
 use WPDesk\Forms\Serializer;
 
 class ProductSelect extends SelectField {
+
 	public function __construct() {
 		$this->set_multiple();
 	}
diff --git a/src/Field/RadioField.php b/src/Field/RadioField.php
index 3e20d1b..cd8fd51 100644
--- a/src/Field/RadioField.php
+++ b/src/Field/RadioField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class RadioField extends BasicField {
+
 	public function get_template_name(): string {
 		return 'input-radio';
 	}
diff --git a/src/Field/SubmitField.php b/src/Field/SubmitField.php
index bcb00f7..0decb84 100644
--- a/src/Field/SubmitField.php
+++ b/src/Field/SubmitField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class SubmitField extends NoValueField {
+
 	public function get_template_name(): string {
 		return 'input-submit';
 	}
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index c7c1a5d..0d5f0e3 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -6,6 +6,7 @@ use WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer\JsonSerializer;
 
 class TimepickerField extends BasicField {
+
 	public function has_serializer(): bool {
 		return true;
 	}
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 71eccba..4edae3b 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -2,6 +2,9 @@
 
 namespace WPDesk\Forms\Field\Traits;
 
+use WPDesk\Forms\Field;
+use WPDesk\Forms\Form;
+
 /**
  * Implementation of HTML attributes like id, name, action etc.
  *
@@ -44,7 +47,7 @@ trait HtmlAttributes {
 	 * @param string $name
 	 * @param string[]|string|bool $value
 	 *
-	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 * @return Field|Form
 	 */
 	final public function set_attribute( string $name, $value ) {
 		$this->attributes[ $name ] = $value;
@@ -53,7 +56,7 @@ trait HtmlAttributes {
 	}
 
 	/**
-	 * @return \WPDesk\Forms\Field|\WPDesk\Forms\Form
+	 * @return HtmlAttributes
 	 */
 	final public function unset_attribute( string $name ) {
 		unset( $this->attributes[ $name ] );
diff --git a/src/Field/WooSelect.php b/src/Field/WooSelect.php
index ec2719c..be348f9 100644
--- a/src/Field/WooSelect.php
+++ b/src/Field/WooSelect.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class WooSelect extends SelectField {
+
 	public function __construct() {
 		$this->set_multiple();
 		$this->add_class( 'wc-enhanced-select' );
diff --git a/src/Field/WyswigField.php b/src/Field/WyswigField.php
index a2f4168..145908f 100644
--- a/src/Field/WyswigField.php
+++ b/src/Field/WyswigField.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms\Field;
 
 class WyswigField extends BasicField {
+
 	public function get_template_name(): string {
 		return 'wyswig';
 	}
diff --git a/src/FieldProvider.php b/src/FieldProvider.php
index e693d00..d8d281e 100644
--- a/src/FieldProvider.php
+++ b/src/FieldProvider.php
@@ -6,6 +6,7 @@ namespace WPDesk\Forms;
  * FieldProvider is owner of FormFields. These fields can be used to render forms and process values.
  */
 interface FieldProvider {
+
 	/**
 	 * Returns owned fields.
 	 *
diff --git a/src/FieldRenderer.php b/src/FieldRenderer.php
index f60c1b0..3e2191e 100644
--- a/src/FieldRenderer.php
+++ b/src/FieldRenderer.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms;
 
 interface FieldRenderer {
+
 	/** @return string|array String or normalized array */
 	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' );
 }
diff --git a/src/FieldsDataReceiver.php b/src/FieldsDataReceiver.php
index e41743d..961f897 100644
--- a/src/FieldsDataReceiver.php
+++ b/src/FieldsDataReceiver.php
@@ -2,6 +2,8 @@
 
 namespace WPDesk\Forms;
 
+use Psr\Container\ContainerInterface;
+
 /**
  * Some field owners can receive and process field data.
  * Probably should be used with FieldProvider interface.
@@ -9,10 +11,11 @@ namespace WPDesk\Forms;
  * @package WPDesk\Forms
  */
 interface FieldsDataReceiver {
+
 	/**
 	 * Set values corresponding to fields.
 	 *
 	 * @return void
 	 */
-	public function update_fields_data( \Psr\Container\ContainerInterface $data );
+	public function update_fields_data( ContainerInterface $data );
 }
diff --git a/src/Form.php b/src/Form.php
index 5f8725d..b5014ff 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -2,7 +2,6 @@
 
 namespace WPDesk\Forms;
 
-use WPDesk\Persistence\PersistentContainer;
 use WPDesk\View\Renderer\Renderer;
 
 /**
@@ -11,6 +10,7 @@ use WPDesk\View\Renderer\Renderer;
  * @package WPDesk\Forms
  */
 interface Form {
+
 	/**
 	 * For some reason you may want to disable a form. Returns false when disabled.
 	 */
diff --git a/src/Sanitizer.php b/src/Sanitizer.php
index 3f57eac..000d3aa 100644
--- a/src/Sanitizer.php
+++ b/src/Sanitizer.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms;
 
 interface Sanitizer {
+
 	/**
 	 * @param mixed $value
 	 *
diff --git a/src/Sanitizer/EmailSanitizer.php b/src/Sanitizer/EmailSanitizer.php
index 1a51a78..160ef3c 100644
--- a/src/Sanitizer/EmailSanitizer.php
+++ b/src/Sanitizer/EmailSanitizer.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class EmailSanitizer implements Sanitizer {
+
 	public function sanitize( $value ): string {
 		return sanitize_email( $value );
 	}
diff --git a/src/Sanitizer/NoSanitize.php b/src/Sanitizer/NoSanitize.php
index a3fe4a6..2647e66 100644
--- a/src/Sanitizer/NoSanitize.php
+++ b/src/Sanitizer/NoSanitize.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class NoSanitize implements Sanitizer {
+
 	public function sanitize( $value ) {
 		return $value;
 	}
diff --git a/src/Sanitizer/TextFieldSanitizer.php b/src/Sanitizer/TextFieldSanitizer.php
index 325c652..c0df5c3 100644
--- a/src/Sanitizer/TextFieldSanitizer.php
+++ b/src/Sanitizer/TextFieldSanitizer.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer;
 
 class TextFieldSanitizer implements Sanitizer {
+
 	public function sanitize( $value ): string {
 		return sanitize_text_field( $value );
 	}
diff --git a/src/Serializer.php b/src/Serializer.php
index 2096b0f..ad5f888 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms;
 
 interface Serializer {
+
 	/**
 	 * @param mixed $value
 	 */
diff --git a/src/Serializer/JsonSerializer.php b/src/Serializer/JsonSerializer.php
index 9ded064..0048820 100644
--- a/src/Serializer/JsonSerializer.php
+++ b/src/Serializer/JsonSerializer.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class JsonSerializer implements Serializer {
+
 	public function serialize( $value ): string {
 		return (string) json_encode( $value );
 	}
diff --git a/src/Serializer/ProductSelectSerializer.php b/src/Serializer/ProductSelectSerializer.php
index 7c4f0e8..dd034f0 100644
--- a/src/Serializer/ProductSelectSerializer.php
+++ b/src/Serializer/ProductSelectSerializer.php
@@ -10,6 +10,7 @@ use WPDesk\Forms\Serializer;
  * @package WPDesk\Forms\Serializer
  */
 class ProductSelectSerializer implements Serializer {
+
 	public function serialize( $value ): string {
 		$products_with_names = [];
 		if ( is_array( $value ) ) {
diff --git a/src/Serializer/SerializeSerializer.php b/src/Serializer/SerializeSerializer.php
index dde47cc..776bd76 100644
--- a/src/Serializer/SerializeSerializer.php
+++ b/src/Serializer/SerializeSerializer.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Serializer;
 use WPDesk\Forms\Serializer;
 
 class SerializeSerializer implements Serializer {
+
 	public function serialize( $value ): string {
 		return serialize( $value );
 	}
diff --git a/src/Validator.php b/src/Validator.php
index 2281820..9422fdb 100644
--- a/src/Validator.php
+++ b/src/Validator.php
@@ -3,6 +3,7 @@
 namespace WPDesk\Forms;
 
 interface Validator {
+
 	/** @param mixed $value */
 	public function is_valid( $value ): bool;
 
diff --git a/src/Validator/NoValidateValidator.php b/src/Validator/NoValidateValidator.php
index 04cf59c..d3bf32f 100644
--- a/src/Validator/NoValidateValidator.php
+++ b/src/Validator/NoValidateValidator.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class NoValidateValidator implements Validator {
+
 	public function is_valid( $value ): bool {
 		return true;
 	}
diff --git a/src/Validator/RequiredValidator.php b/src/Validator/RequiredValidator.php
index 4e78faf..5d4851a 100644
--- a/src/Validator/RequiredValidator.php
+++ b/src/Validator/RequiredValidator.php
@@ -5,6 +5,7 @@ namespace WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator;
 
 class RequiredValidator implements Validator {
+
 	public function is_valid( $value ): bool {
 		return $value !== null;
 	}
diff --git a/templates/button.php b/templates/button.php
index fd95750..214417d 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -33,3 +33,4 @@
 		readonly="readonly"<?php endif; ?>
 
 ><?php echo \esc_html( $field->get_label() ); ?></button>
+
diff --git a/templates/form-field.php b/templates/form-field.php
index 0fd07d5..09a0fe9 100644
--- a/templates/form-field.php
+++ b/templates/form-field.php
@@ -11,13 +11,12 @@
 
 <tr valign="top">
 	<?php if ( $field->has_label() ) : ?>
-		<?php echo wp_kses_post( $renderer->render( 'form-label', [ 'field' => $field ] ) ); ?>
+		<?php $renderer->output_render( 'form-label', [ 'field' => $field ] ); ?>
 	<?php endif; ?>
 
 	<td class="forminp">
 		<?php
-		echo wp_kses_post(
-			$renderer->render(
+			$renderer->output_render(
 				$template_name,
 				[
 					'field'       => $field,
@@ -25,9 +24,8 @@
 					'name_prefix' => $name_prefix,
 					'value'       => $value,
 				]
-			)
-		);
-		?>
+			);
+			?>
 
 		<?php if ( $field->has_description() ) : ?>
 			<p class="description"><?php echo wp_kses_post( $field->get_description() ); ?></p>
diff --git a/templates/form-label.php b/templates/form-label.php
index 8eeaf28..9d960fe 100644
--- a/templates/form-label.php
+++ b/templates/form-label.php
@@ -9,7 +9,7 @@
 <th class="titledesc" scope="row">
 	<label for="<?php echo \esc_attr( $field->get_id() ); ?>"><?php echo \esc_html( $field->get_label() ); ?>
 		<?php if ( $field->has_description_tip() ) : ?>
-			<?php echo esc_html( wc_help_tip( $field->get_description_tip() ) ); ?>
+			<?php echo wp_kses_post( wc_help_tip( $field->get_description_tip() ) ); ?>
 		<?php endif ?>
 	</label>
 </th>
diff --git a/templates/input-checkbox.php b/templates/input-checkbox.php
index 8474091..55f544f 100644
--- a/templates/input-checkbox.php
+++ b/templates/input-checkbox.php
@@ -10,14 +10,12 @@
 ?>
 
 <?php
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
diff --git a/templates/input-date-picker.php b/templates/input-date-picker.php
index 3caa4c6..51e9715 100644
--- a/templates/input-date-picker.php
+++ b/templates/input-date-picker.php
@@ -7,14 +7,12 @@
  * @var string $template_name Real field template.
  */
 
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
diff --git a/templates/input-hidden.php b/templates/input-hidden.php
index 6388552..7668c7f 100644
--- a/templates/input-hidden.php
+++ b/templates/input-hidden.php
@@ -9,14 +9,12 @@
 
 ?>
 <?php
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
diff --git a/templates/input-image.php b/templates/input-image.php
index 5111c4c..ce099e4 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -13,17 +13,25 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 			id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
 	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
-            <img src="<?php echo \esc_url( $value ) ?>" alt="" width="100"/>
+			<img src="<?php echo \esc_url( $value ); ?>" alt="" width="100"/>
 		<?php endif; ?>
-    </div>
-    <p class="hide-if-no-js">
-        <a class="upload-custom-img <?php if ( $value ): ?>hidden<?php endif ?>" href="<?php echo \esc_url( $value ) ?>">
-			<?php \esc_html_e( 'Set image', 'wp-forms' ) ?>
-        </a>
-        <a class="delete-custom-img <?php if ( ! $value ): ?>hidden<?php endif ?>" href="#">
-			<?php \esc_html_e( 'Remove image', 'wp-forms' ) ?>
-        </a>
-    </p>
+	</div>
+	<p class="hide-if-no-js">
+		<a class="upload-custom-img 
+		<?php
+		if ( $value ) :
+			?>
+			hidden<?php endif ?>" href="<?php echo \esc_url( $value ); ?>">
+			<?php \esc_html_e( 'Set image', 'wp-forms' ); ?>
+		</a>
+		<a class="delete-custom-img 
+		<?php
+		if ( ! $value ) :
+			?>
+			hidden<?php endif ?>" href="#">
+			<?php \esc_html_e( 'Remove image', 'wp-forms' ); ?>
+		</a>
+	</p>
 </div>
 <script>
 	jQuery( function ( $ ) {
diff --git a/templates/input-number.php b/templates/input-number.php
index 3caa4c6..51e9715 100644
--- a/templates/input-number.php
+++ b/templates/input-number.php
@@ -7,14 +7,12 @@
  * @var string $template_name Real field template.
  */
 
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
diff --git a/templates/input-radio.php b/templates/input-radio.php
index 6388552..7668c7f 100644
--- a/templates/input-radio.php
+++ b/templates/input-radio.php
@@ -9,14 +9,12 @@
 
 ?>
 <?php
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
diff --git a/templates/input-text.php b/templates/input-text.php
index 3caa4c6..51e9715 100644
--- a/templates/input-text.php
+++ b/templates/input-text.php
@@ -7,14 +7,12 @@
  * @var string $template_name Real field template.
  */
 
-echo wp_kses_post(
-	$renderer->render(
-		'input',
-		[
-			'field'       => $field,
-			'renderer'    => $renderer,
-			'name_prefix' => $name_prefix,
-			'value'       => $value,
-		]
-	)
+$renderer->output_render(
+	'input',
+	[
+		'field'       => $field,
+		'renderer'    => $renderer,
+		'name_prefix' => $name_prefix,
+		'value'       => $value,
+	]
 );
-- 
GitLab


From 08b0068a3aeb313aa6896215002aa42993afa940 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Wed, 6 Oct 2021 10:40:11 +0200
Subject: [PATCH 29/39] fix: prevent all empty attributes from being written to
 templates

---
 src/Field/Traits/HtmlAttributes.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 4edae3b..e0fc3ba 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -33,13 +33,13 @@ trait HtmlAttributes {
 	 *
 	 * @return array<string[]|string|bool>
 	 */
-	final public function get_attributes( array $except = [ 'name' ] ): array {
+	final public function get_attributes( array $except = [ 'name', 'method', 'action' ] ): array {
 		return array_filter(
 			$this->attributes,
-			static function ( $key ) use ( $except ) {
-				return ! in_array( $key, $except, true );
+			static function ( $attribute, $key ) use ( $except ) {
+				return ! in_array( $key, $except, true ) && ! empty( $attribute );
 			},
-			ARRAY_FILTER_USE_KEY
+			ARRAY_FILTER_USE_BOTH
 		);
 	}
 
-- 
GitLab


From a32c016e5bb012771fb0ef5d7fcfd207b96162d1 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Wed, 6 Oct 2021 10:52:28 +0200
Subject: [PATCH 30/39] fix: remove classes from basic attributes iteration

---
 src/Field/Traits/HtmlAttributes.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index e0fc3ba..980d54c 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -33,7 +33,7 @@ trait HtmlAttributes {
 	 *
 	 * @return array<string[]|string|bool>
 	 */
-	final public function get_attributes( array $except = [ 'name', 'method', 'action' ] ): array {
+	final public function get_attributes( array $except = [ 'name', 'class', 'method', 'action' ] ): array {
 		return array_filter(
 			$this->attributes,
 			static function ( $attribute, $key ) use ( $except ) {
-- 
GitLab


From 4194136993983cdb5504534df5637cba2d53ecaa Mon Sep 17 00:00:00 2001
From: potreb <potreb@gmail.com>
Date: Wed, 6 Oct 2021 12:21:10 +0200
Subject: [PATCH 31/39] fix: html attributes, templates fix

---
 src/Field/BasicField.php                | 29 ++++++++++++-------------
 src/Field/SelectField.php               |  2 +-
 src/Field/Traits/HtmlAttributes.php     | 26 +++++++---------------
 src/Form/FormWithFields.php             | 15 ++++++++-----
 src/Renderer/JsonNormalizedRenderer.php | 28 +++++++++---------------
 templates/button.php                    | 23 +++++---------------
 templates/input-submit.php              | 12 ----------
 templates/input-text-multiple.php       | 12 ----------
 templates/input.php                     | 16 --------------
 templates/select.php                    | 17 ---------------
 templates/textarea.php                  | 17 ---------------
 11 files changed, 48 insertions(+), 149 deletions(-)

diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index c1d5270..53149c1 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -25,12 +25,12 @@ abstract class BasicField implements Field {
 
 	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>} */
 	protected $meta = [
-		'priority'          => self::DEFAULT_PRIORITY,
-		'default_value'     => '',
-		'label'             => '',
-		'description'       => '',
-		'description_tip'   => '',
-		'data'              => [],
+		'priority'        => self::DEFAULT_PRIORITY,
+		'default_value'   => '',
+		'label'           => '',
+		'description'     => '',
+		'description_tip' => '',
+		'data'            => [],
 	];
 
 	public function should_override_form_template(): bool {
@@ -59,7 +59,7 @@ abstract class BasicField implements Field {
 	}
 
 	public function get_serializer(): Serializer {
-		throw new BadMethodCallException('You must define your serializer in a child class.');
+		throw new BadMethodCallException( 'You must define your serializer in a child class.' );
 	}
 
 	final public function get_name(): string {
@@ -156,33 +156,32 @@ abstract class BasicField implements Field {
 		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
-
 	final public function is_multiple(): bool {
-		return $this->attributes['multiple'];
+		return isset( $this->attributes['multiple'] );
 	}
 
 	final public function set_disabled(): Field {
-		$this->attributes['disabled'] = true;
+		$this->attributes['disabled'] = 'disabled';
 
 		return $this;
 	}
 
 	final public function is_disabled(): bool {
-		return $this->attributes['disabled'];
+		return $this->attributes['disabled'] ?? false;
 	}
 
 	final public function set_readonly(): Field {
-		$this->attributes['readonly'] = true;
+		$this->attributes['readonly'] = 'readonly';
 
 		return $this;
 	}
 
 	final public function is_readonly(): bool {
-		return $this->attributes['readonly'];
+		return $this->attributes['readonly'] ?? false;
 	}
 
 	final public function set_required(): Field {
-		$this->attributes['required'] = true;
+		$this->attributes['required'] = 'required';
 
 		return $this;
 	}
@@ -233,7 +232,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function is_required(): bool {
-		return $this->attributes['required'];
+		return isset( $this->attributes['required'] );
 	}
 
 	final public function get_priority(): int {
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index ee0264c..2162753 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -18,7 +18,7 @@ class SelectField extends BasicField {
 	}
 
 	public function set_multiple(): Field {
-		$this->attributes['multiple'] = true;
+		$this->attributes['multiple'] = 'multiple';
 
 		return $this;
 	}
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index 980d54c..ba01363 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -12,19 +12,8 @@ use WPDesk\Forms\Form;
  */
 trait HtmlAttributes {
 
-	/** @var array{placeholder: string, name: string, id: string, class: string[], readonly: bool, multiple: bool, disabled: bool, required: bool, method: string, action: string} */
-	protected $attributes = [
-		'placeholder' => '',
-		'name'        => '',
-		'id'          => '',
-		'class'       => [],
-		'action'      => '',
-		'method'      => 'POST',
-		'readonly'    => false,
-		'multiple'    => false,
-		'disabled'    => false,
-		'required'    => false,
-	];
+	/** @var array{placeholder: string, name: string, id: string, class: string[]} */
+	protected $attributes = [];
 
 	/**
 	 * Get list of all attributes except given.
@@ -33,18 +22,18 @@ trait HtmlAttributes {
 	 *
 	 * @return array<string[]|string|bool>
 	 */
-	final public function get_attributes( array $except = [ 'name', 'class', 'method', 'action' ] ): array {
+	final public function get_attributes( array $except = [ 'name', 'class' ] ): array {
 		return array_filter(
 			$this->attributes,
-			static function ( $attribute, $key ) use ( $except ) {
-				return ! in_array( $key, $except, true ) && ! empty( $attribute );
+			static function ( $key ) use ( $except ) {
+				return ! in_array( $key, $except, true );
 			},
-			ARRAY_FILTER_USE_BOTH
+			ARRAY_FILTER_USE_KEY
 		);
 	}
 
 	/**
-	 * @param string $name
+	 * @param string               $name
 	 * @param string[]|string|bool $value
 	 *
 	 * @return Field|Form
@@ -73,6 +62,7 @@ trait HtmlAttributes {
 			// Be aware of coercing - if implode returns string(0) '', then return $default value.
 			return implode( ' ', $this->attributes[ $name ] ) ?: $default ?? '';
 		}
+
 		return (string) $this->attributes[ $name ] ?? $default ?? '';
 	}
 }
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index de48e33..c3c965d 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -26,12 +26,14 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	/**
 	 * FormWithFields constructor.
 	 *
-	 * @param Field[]  $fields
-	 * @param string $form_id
+	 * @param Field[] $fields
+	 * @param string  $form_id
 	 */
 	public function __construct( array $fields, string $form_id = 'form' ) {
 		$this->fields  = $fields;
 		$this->form_id = $form_id;
+		$this->set_action( '' );
+		$this->set_method( 'POST' );
 	}
 
 	/** Set Form action attribute. */
@@ -41,6 +43,10 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $this;
 	}
 
+	public function get_action(): string {
+		return $this->attributes['action'];
+	}
+
 	/** Set Form method attribute ie. GET/POST. */
 	public function set_method( string $method ): self {
 		$this->attributes['method'] = $method;
@@ -52,9 +58,6 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 		return $this->attributes['method'];
 	}
 
-	public function get_action(): string {
-		return $this->attributes['action'];
-	}
 
 	public function is_submitted(): bool {
 		return null !== $this->updated_data;
@@ -146,7 +149,7 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	}
 
 	public function render_form( Renderer $renderer ): string {
-		$content  = $renderer->render(
+		$content = $renderer->render(
 			'form-start',
 			[
 				'form'   => $this,
diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 82021cb..008168a 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -13,28 +13,23 @@ use WPDesk\Forms\FieldRenderer;
 class JsonNormalizedRenderer implements FieldRenderer {
 	/**
 	 * @param FieldProvider $provider
-	 * @param array $fields_data
-	 * @param string $name_prefix
+	 * @param array         $fields_data
+	 * @param string        $name_prefix
 	 *
 	 * @return array Normalized fields with data.
 	 */
 	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' ): array {
 		$rendered_fields = [];
 		foreach ( $provider->get_fields() as $field ) {
-			$rendered = [
-				'name'     => $field->get_name(),
-				'template' => $field->get_template_name(),
-				'multiple' => $field->is_multiple(),
-				'disabled' => $field->is_disabled(),
-				'readonly' => $field->is_readonly(),
-				'required' => $field->is_required(),
-				'prefix'   => $name_prefix,
-				'value '   => $fields_data[ $field->get_name() ] ?? $field->get_default_value(),
-			];
+			$rendered = [];
+			foreach ( $field->get_attributes() as $key => $attribute ) {
+				$rendered[ $key ] = $attribute;
+			}
+			$rendered['name']     = $field->get_name();
+			$rendered['template'] = $field->get_template_name();
+			$rendered['prefix']   = $name_prefix;
+			$rendered['value']    = $fields_data[ $field->get_name() ] ?? $field->get_default_value();
 
-			if ( $field->has_classes() ) {
-				$rendered['class'] = $field->get_classes();
-			}
 			if ( $field->has_description() ) {
 				$rendered['description'] = $field->get_description();
 			}
@@ -44,9 +39,6 @@ class JsonNormalizedRenderer implements FieldRenderer {
 			if ( $field->has_label() ) {
 				$rendered['label'] = $field->get_label();
 			}
-			if ( $field->has_placeholder() ) {
-				$rendered['placeholder'] = $field->get_placeholder();
-			}
 			$options = $field->get_possible_values();
 			if ( $options ) {
 				$rendered['options'] = $options;
diff --git a/templates/button.php b/templates/button.php
index 214417d..3068ae6 100644
--- a/templates/button.php
+++ b/templates/button.php
@@ -10,27 +10,16 @@
 ?>
 
 <button
-<?php if ( $field->has_classes() ) : ?>
-	class="<?php echo \esc_attr( $field->get_classes() ); ?>"
-<?php endif; ?>
-
-<?php foreach ( $field->get_attributes( [] ) as $key => $val ) : ?>
-	<?php echo \esc_attr( $key ) . '="' . \esc_attr( $val ) . '"'; ?>
-<?php endforeach; ?>
-
 	type="<?php echo \esc_attr( $field->get_type() ); ?>"
 	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
 	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 	value="<?php echo \esc_html( $value ); ?>"
-
-	<?php
-	if ( $field->is_disabled() ) :
-		?>
-		disabled="disabled"<?php endif; ?>
-	<?php
-	if ( $field->is_readonly() ) :
-		?>
-		readonly="readonly"<?php endif; ?>
+	<?php if ( $field->has_classes() ) : ?>
+		class="<?php echo \esc_attr( $field->get_classes() ); ?>"
+	<?php endif; ?>
+	<?php foreach ( $field->get_attributes() as $key => $val ) : ?>
+		<?php echo \esc_attr( $key ) . '="' . \esc_attr( $val ) . '"'; ?>
+	<?php endforeach; ?>
 
 ><?php echo \esc_html( $field->get_label() ); ?></button>
 
diff --git a/templates/input-submit.php b/templates/input-submit.php
index bae3ce3..65453d6 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -24,18 +24,6 @@
 				name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
 				id="<?php echo \esc_attr( $field->get_id() ); ?>"
 				value="<?php echo \esc_html( $field->get_label() ); ?>"
-				<?php
-				if ( $field->is_required() ) :
-					?>
-					required="required"<?php endif; ?>
-				<?php
-				if ( $field->is_disabled() ) :
-					?>
-					disabled="disabled"<?php endif; ?>
-				<?php
-				if ( $field->is_readonly() ) :
-					?>
-					readonly="readonly"<?php endif; ?>
 			/>
 		</p>
 	</td>
diff --git a/templates/input-text-multiple.php b/templates/input-text-multiple.php
index 371013d..05e7d29 100644
--- a/templates/input-text-multiple.php
+++ b/templates/input-text-multiple.php
@@ -43,18 +43,6 @@ if ( empty( $value ) || is_string( $value ) ) {
 			?>
 		<?php endforeach; ?>
 
-		<?php
-		if ( $field->is_required() ) :
-			?>
-			required="required"<?php endif; ?>
-		<?php
-		if ( $field->is_disabled() ) :
-			?>
-			disabled="disabled"<?php endif; ?>
-		<?php
-		if ( $field->is_readonly() ) :
-			?>
-			readonly="readonly"<?php endif; ?>
 		<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 			value="<?php echo \esc_html( $text_value ); ?>"
 		<?php else : ?>
diff --git a/templates/input.php b/templates/input.php
index a4844b1..6fb3c01 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -23,28 +23,12 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 		class="<?php echo \esc_attr( $field->get_classes() ); ?>"
 	<?php endif; ?>
 
-	<?php if ( $field->get_type() === 'text' && $field->has_placeholder() ) : ?>
-		placeholder="<?php echo \esc_html( $field->get_placeholder() ); ?>"
-	<?php endif; ?>
-
 	<?php
 	foreach ( $field->get_attributes() as $key => $atr_val ) :
 		echo \esc_attr( $key ) . '="' . \esc_attr( $atr_val ) . '"';
 		?>
 	<?php endforeach; ?>
 
-	<?php
-	if ( $field->is_required() ) :
-		?>
-		required="required"<?php endif; ?>
-	<?php
-	if ( $field->is_disabled() ) :
-		?>
-		disabled="disabled"<?php endif; ?>
-	<?php
-	if ( $field->is_readonly() ) :
-		?>
-		readonly="readonly"<?php endif; ?>
 	<?php if ( \in_array( $field->get_type(), [ 'number', 'text', 'hidden' ], true ) ) : ?>
 		value="<?php echo \esc_html( $value ); ?>"
 	<?php else : ?>
diff --git a/templates/select.php b/templates/select.php
index 625c316..edb7e06 100644
--- a/templates/select.php
+++ b/templates/select.php
@@ -17,23 +17,6 @@
 	<?php foreach ( $field->get_attributes() as $key => $attr_val ) : ?>
 		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
-
-	<?php
-	if ( $field->is_required() ) :
-		?>
-		required="required"<?php endif; ?>
-	<?php
-	if ( $field->is_disabled() ) :
-		?>
-		disabled="disabled"<?php endif; ?>
-	<?php
-	if ( $field->is_readonly() ) :
-		?>
-		readonly="readonly"<?php endif; ?>
-	<?php
-	if ( $field->is_multiple() ) :
-		?>
-		multiple="multiple"<?php endif; ?>
 >
 	<?php
 	if ( $field->has_placeholder() ) :
diff --git a/templates/textarea.php b/templates/textarea.php
index 8cf3846..218f860 100644
--- a/templates/textarea.php
+++ b/templates/textarea.php
@@ -18,23 +18,6 @@
 		<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $attr_val ); ?>"
 	<?php endforeach; ?>
 
-	<?php
-	if ( $field->is_required() ) :
-		?>
-		required="required"<?php endif; ?>
-	<?php
-	if ( $field->is_disabled() ) :
-		?>
-		disabled="disabled"<?php endif; ?>
-	<?php
-	if ( $field->is_readonly() ) :
-		?>
-		readonly="readonly"<?php endif; ?>
-	<?php
-	if ( $field->is_multiple() ) :
-		?>
-		multiple="multiple"<?php endif; ?>
-
 	<?php
 	if ( $field->has_placeholder() ) :
 		?>
-- 
GitLab


From 8266e545eebfa26ecfe99a0b60e1f960fa24533f Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Fri, 22 Oct 2021 14:06:08 +0200
Subject: [PATCH 32/39] fix: allow TextFieldSanitizer process array values

---
 changelog.txt                        | 5 +++++
 src/Sanitizer/TextFieldSanitizer.php | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/changelog.txt b/changelog.txt
index b2f9dcf..6894cf9 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,9 @@
 # Changelog
+
+## [2.4.11]
+### Changed
+- Allow TextFieldSanitizer to process array values
+
 ## [2.4.10] - 2021-10-01
 ### Changed
 - Render form data without using echo
diff --git a/src/Sanitizer/TextFieldSanitizer.php b/src/Sanitizer/TextFieldSanitizer.php
index 0a1bbcb..743c205 100644
--- a/src/Sanitizer/TextFieldSanitizer.php
+++ b/src/Sanitizer/TextFieldSanitizer.php
@@ -6,6 +6,9 @@ use WPDesk\Forms\Sanitizer;
 
 class TextFieldSanitizer implements Sanitizer {
 	public function sanitize( $value ) {
+		if ( is_array( $value ) ) {
+			return array_map('sanitize_text_field', $value);
+		}
 		return sanitize_text_field( $value );
 	}
 
-- 
GitLab


From be343b5640e420ee46ec3526b139c6127466ecd3 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Fri, 8 Apr 2022 12:48:54 +0200
Subject: [PATCH 33/39] fix: add nullables for all attributes for safer usage
 in templates

---
 src/Field/BasicField.php            | 20 +++++++++-----------
 src/Field/Traits/HtmlAttributes.php |  2 +-
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 53149c1..67aa662 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -14,8 +14,6 @@ use WPDesk\Forms\Validator\RequiredValidator;
 /**
  * Base class for fields. Is responsible for settings all required field values and provides standard implementation for
  * the field interface.
- *
- * @package WPDesk\Forms
  */
 abstract class BasicField implements Field {
 
@@ -63,11 +61,11 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_name(): string {
-		return $this->attributes['name'];
+		return $this->attributes['name'] ?? '';
 	}
 
 	final public function get_label(): string {
-		return $this->meta['label'];
+		return $this->meta['label'] ?? '';
 	}
 
 	final public function set_label( string $value ): Field {
@@ -77,7 +75,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_description_tip(): string {
-		return $this->meta['description_tip'];
+		return $this->meta['description_tip'] ?? '';
 	}
 
 	final public function has_description_tip(): bool {
@@ -85,7 +83,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_description(): string {
-		return $this->meta['description'];
+		return $this->meta['description'] ?? '';
 	}
 
 	final public function has_label(): bool {
@@ -119,7 +117,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_placeholder(): string {
-		return $this->attributes['placeholder'];
+		return $this->attributes['placeholder'] ?? '';
 	}
 
 	final public function set_name( string $name ): Field {
@@ -129,11 +127,11 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_meta_value( string $name ) {
-		return $this->meta[ $name ];
+		return $this->meta[ $name ] ?? '';
 	}
 
 	final public function get_classes(): string {
-		return implode( ' ', $this->attributes['class'] );
+		return implode( ' ', $this->attributes['class'] ?? [] );
 	}
 
 	final public function has_classes(): bool {
@@ -145,7 +143,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_data(): array {
-		return $this->meta['data'];
+		return $this->meta['data'] ?? [];
 	}
 
 	final public function get_possible_values() {
@@ -222,7 +220,7 @@ abstract class BasicField implements Field {
 	}
 
 	final public function get_default_value(): string {
-		return $this->meta['default_value'];
+		return $this->meta['default_value'] ?? '';
 	}
 
 	final public function set_default_value( string $value ): Field {
diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php
index ba01363..aac835d 100644
--- a/src/Field/Traits/HtmlAttributes.php
+++ b/src/Field/Traits/HtmlAttributes.php
@@ -63,6 +63,6 @@ trait HtmlAttributes {
 			return implode( ' ', $this->attributes[ $name ] ) ?: $default ?? '';
 		}
 
-		return (string) $this->attributes[ $name ] ?? $default ?? '';
+		return (string) ( $this->attributes[ $name ] ?? $default ?? '' );
 	}
 }
-- 
GitLab


From 88cafd1b75eee37cdc5b324ad13b8d844ff801bb Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Fri, 8 Apr 2022 14:39:26 +0200
Subject: [PATCH 34/39] fix: return empty data if no fields added to form

---
 src/Form/FormWithFields.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index c3c965d..8d4961d 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -180,6 +180,10 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 	}
 
 	public function get_data(): array {
+		if ( empty( $this->get_fields() ) ) {
+			return [];
+		}
+
 		$data = $this->updated_data;
 
 		foreach ( $this->get_fields() as $field ) {
-- 
GitLab


From f879cad8ce9d10a978cd31a1084d071e529370d7 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Tue, 12 Apr 2022 15:25:28 +0200
Subject: [PATCH 35/39] fix: use classes separately in templates

---
 templates/input-submit.php | 10 ++++------
 templates/input.php        |  1 -
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/templates/input-submit.php b/templates/input-submit.php
index 65453d6..176d6d7 100644
--- a/templates/input-submit.php
+++ b/templates/input-submit.php
@@ -13,16 +13,14 @@
 	<td style="padding-left:0;">
 		<p class="submit">
 			<input
-				<?php
-				if ( $field->has_classes() ) :
-					?>
-					class="<?php echo \esc_attr( $field->get_classes() ); ?>"<?php endif; ?>
-				<?php foreach ( $field->get_attributes( [] ) as $key => $value ) : ?>
+				<?php if ( $field->has_classes() ) : ?>
+					class="<?php echo \esc_attr( $field->get_classes() ); ?>"
+				<?php endif; ?>
+				<?php foreach ( $field->get_attributes() as $key => $value ) : ?>
 					<?php echo \esc_attr( $key ); ?>="<?php echo \esc_attr( $value ); ?>"
 				<?php endforeach; ?>
 				type="<?php echo \esc_attr( $field->get_type() ); ?>"
 				name="<?php echo \esc_attr( $name_prefix ); ?>[<?php echo \esc_attr( $field->get_name() ); ?>]"
-				id="<?php echo \esc_attr( $field->get_id() ); ?>"
 				value="<?php echo \esc_html( $field->get_label() ); ?>"
 			/>
 		</p>
diff --git a/templates/input.php b/templates/input.php
index 6fb3c01..4b8eb6a 100644
--- a/templates/input.php
+++ b/templates/input.php
@@ -17,7 +17,6 @@ if ( $field->get_type() === 'checkbox' && $field->has_sublabel() ) :
 <input
 	type="<?php echo \esc_attr( $field->get_type() ); ?>"
 	name="<?php echo \esc_attr( $name_prefix ) . '[' . \esc_attr( $field->get_name() ) . ']'; ?>"
-	id="<?php echo \esc_attr( $field->get_id() ); ?>"
 
 	<?php if ( $field->has_classes() ) : ?>
 		class="<?php echo \esc_attr( $field->get_classes() ); ?>"
-- 
GitLab


From 5c6ca1f87efa092fc3fb919916d1cc58c825d881 Mon Sep 17 00:00:00 2001
From: Piotr Po <potreb@gmail.com>
Date: Tue, 7 Jun 2022 20:40:52 +0200
Subject: [PATCH 36/39] fix: radio field

---
 src/Field/RadioField.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/Field/RadioField.php b/src/Field/RadioField.php
index cd8fd51..73c5f70 100644
--- a/src/Field/RadioField.php
+++ b/src/Field/RadioField.php
@@ -4,6 +4,10 @@ namespace WPDesk\Forms\Field;
 
 class RadioField extends BasicField {
 
+	public function get_type(): string {
+		return 'radio';
+	}
+
 	public function get_template_name(): string {
 		return 'input-radio';
 	}
-- 
GitLab


From 3997f29021fb92c8844bd8bf852a4b5b19b8c546 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Tue, 19 Jul 2022 03:20:26 +0200
Subject: [PATCH 37/39] feat: add possibility to manipulate field type

---
 src/Field/BasicField.php      | 9 ++++++++-
 src/Field/SelectField.php     | 4 ++++
 src/Field/TextAreaField.php   | 4 ++++
 src/Field/TimepickerField.php | 4 ++++
 4 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 67aa662..3e34ff9 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -29,6 +29,7 @@ abstract class BasicField implements Field {
 		'description'     => '',
 		'description_tip' => '',
 		'data'            => [],
+		'type'            => 'text',
 	];
 
 	public function should_override_form_template(): bool {
@@ -36,7 +37,13 @@ abstract class BasicField implements Field {
 	}
 
 	public function get_type(): string {
-		return 'text';
+		return $this->meta['type'];
+	}
+
+	public function set_type( string $type ): Field {
+		$this->meta['type'] = $type;
+
+		return $this;
 	}
 
 	public function get_validator(): Validator {
diff --git a/src/Field/SelectField.php b/src/Field/SelectField.php
index 2162753..04d290c 100644
--- a/src/Field/SelectField.php
+++ b/src/Field/SelectField.php
@@ -6,6 +6,10 @@ use WPDesk\Forms\Field;
 
 class SelectField extends BasicField {
 
+	public function get_type(): string {
+		return 'select';
+	}
+
 	public function get_template_name(): string {
 		return 'select';
 	}
diff --git a/src/Field/TextAreaField.php b/src/Field/TextAreaField.php
index f22b2bb..81ed137 100644
--- a/src/Field/TextAreaField.php
+++ b/src/Field/TextAreaField.php
@@ -4,6 +4,10 @@ namespace WPDesk\Forms\Field;
 
 class TextAreaField extends BasicField {
 
+	public function get_type(): string {
+		return 'textarea';
+	}
+
 	public function get_template_name(): string {
 		return 'textarea';
 	}
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index 0d5f0e3..f1bf91a 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -7,6 +7,10 @@ use WPDesk\Forms\Serializer\JsonSerializer;
 
 class TimepickerField extends BasicField {
 
+	public function get_type(): string {
+		return 'time';
+	}
+
 	public function has_serializer(): bool {
 		return true;
 	}
-- 
GitLab


From d18dd7fc3f69a8e8935ae37b3cc61f642f04ebcf Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Tue, 19 Jul 2022 03:20:43 +0200
Subject: [PATCH 38/39] feat: sort fields in JsonRenderer

---
 src/Renderer/JsonNormalizedRenderer.php | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/Renderer/JsonNormalizedRenderer.php b/src/Renderer/JsonNormalizedRenderer.php
index 008168a..da9e1f8 100644
--- a/src/Renderer/JsonNormalizedRenderer.php
+++ b/src/Renderer/JsonNormalizedRenderer.php
@@ -2,6 +2,7 @@
 
 namespace WPDesk\Forms\Renderer;
 
+use WPDesk\Forms\Field;
 use WPDesk\Forms\FieldProvider;
 use WPDesk\Forms\FieldRenderer;
 
@@ -20,7 +21,14 @@ class JsonNormalizedRenderer implements FieldRenderer {
 	 */
 	public function render_fields( FieldProvider $provider, array $fields_data, string $name_prefix = '' ): array {
 		$rendered_fields = [];
-		foreach ( $provider->get_fields() as $field ) {
+		$fields          = $provider->get_fields();
+		usort(
+			$fields,
+			static function ( Field $a, Field $b ) {
+				return $a->get_priority() <=> $b->get_priority();
+			}
+		);
+		foreach ( $fields as $field ) {
 			$rendered = [];
 			foreach ( $field->get_attributes() as $key => $attribute ) {
 				$rendered[ $key ] = $attribute;
-- 
GitLab


From aef962c80bbdec2ba14569ce0fbbf55c9e2ce988 Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Tue, 19 Jul 2022 03:39:55 +0200
Subject: [PATCH 39/39] chore: update changelog

---
 changelog.txt | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/changelog.txt b/changelog.txt
index 94bd676..d940f97 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,18 @@
 # Changelog
 
+## [3.0.0] - 2022-07-19
+### Added
+- Added strong typing to all the interfaces
+- Added fields sorting by priority field
+- Normalized string escaping in all template files
+- Added InputEmailField and EmailSerializer classes
+### Changed
+- All getters and setter in BasicField are now declared final
+- FormWithFields accepts only ContainerInterface in ::set_data() method. Prepare data before passing it
+### Removed
+- Removed deprecated classes
+- Removed NoSerialize class
+
 ## [2.4.12] - 2021-12-22
 ### Fixed
 - Fixed image input JS
@@ -20,19 +33,6 @@
 ### Fixed
 - Add escaping functions to all templates
 
-## [3.0.0]
-### Added
-- Added strong typing to all of the interfaces
-- Added fields sorting by priority field
-- Normalized string escaping in all template files
-- Added InputEmailField and EmailSerializer classes
-### Changed
-- All getters and setter in BasicField are now declared final
-- FormWithFields accepts only ContainerInterface in ::set_data() method. Prepare data before passing it
-### Removed
-- Removed deprecated classes
-- Removed NoSerialize class
-
 ## [2.4.7] - 2021-09-20
 ### Fixed
 - Add missing escaping functions in templates
-- 
GitLab