diff --git a/app/bootstrap.php b/app/bootstrap.php
index ec60a1708dacc3d2238960e5b1c9e7c0da05cc92..c8e676cb69cffd5cf32de8f12f9f83987cc6619a 100644
--- a/app/bootstrap.php
+++ b/app/bootstrap.php
@@ -11,14 +11,14 @@ error_reporting(E_ALL);
 #ini_set('display_errors', 1);
 
 /* PHP version validation */
-if (!defined('PHP_VERSION_ID') || !(PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 50700 || PHP_VERSION_ID === 70002 || PHP_VERSION_ID === 70004 || PHP_VERSION_ID >= 70006)) {
+if (!defined('PHP_VERSION_ID') || !(PHP_VERSION_ID >= 50605 && PHP_VERSION_ID < 50700 || PHP_VERSION_ID === 70002 || PHP_VERSION_ID === 70004 || PHP_VERSION_ID >= 70006)) {
     if (PHP_SAPI == 'cli') {
-        echo 'Magento supports PHP 5.6, 7.0.2, 7.0.4, and 7.0.6 or later. ' .
+        echo 'Magento supports PHP 5.6.5, 7.0.2, 7.0.4, and 7.0.6 or later. ' .
             'Please read http://devdocs.magento.com/guides/v1.0/install-gde/system-requirements.html';
     } else {
         echo <<<HTML
 <div style="font:12px/1.35em arial, helvetica, sans-serif;">
-    <p>Magento supports PHP 5.6, 7.0.2, 7.0.4, and 7.0.6 or later. Please read
+    <p>Magento supports PHP 5.6.5, 7.0.2, 7.0.4, and 7.0.6 or later. Please read
     <a target="_blank" href="http://devdocs.magento.com/guides/v1.0/install-gde/system-requirements.html">
     Magento System Requirements</a>.
 </div>
@@ -35,6 +35,17 @@ $umaskFile = BP . '/magento_umask';
 $mask = file_exists($umaskFile) ? octdec(file_get_contents($umaskFile)) : 002;
 umask($mask);
 
+if (empty($_SERVER['ENABLE_IIS_REWRITES']) || ($_SERVER['ENABLE_IIS_REWRITES'] != 1)) {
+    /*
+     * Unset headers used by IIS URL rewrites.
+     */
+    unset($_SERVER['HTTP_X_REWRITE_URL']);
+    unset($_SERVER['HTTP_X_ORIGINAL_URL']);
+    unset($_SERVER['IIS_WasUrlRewritten']);
+    unset($_SERVER['UNENCODED_URL']);
+    unset($_SERVER['ORIG_PATH_INFO']);
+}
+
 if (!empty($_SERVER['MAGE_PROFILER'])
     && isset($_SERVER['HTTP_ACCEPT'])
     && strpos($_SERVER['HTTP_ACCEPT'], 'text/html') !== false
diff --git a/app/code/Magento/AdminNotification/composer.json b/app/code/Magento/AdminNotification/composer.json
index 527268df36b41efe5078528138342a03fa33745d..09d8ce41bbb03607a2f8cd16831454c8565a5204 100644
--- a/app/code/Magento/AdminNotification/composer.json
+++ b/app/code/Magento/AdminNotification/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-admin-notification",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-media-storage": "100.2.*",
diff --git a/app/code/Magento/AdvancedPricingImportExport/composer.json b/app/code/Magento/AdvancedPricingImportExport/composer.json
index 65ea7524dffff5bb778aaf5ec7658302072cfaf9..2fc465fa3c3dfd7a51abdd713f0c5c6dfd6843c6 100644
--- a/app/code/Magento/AdvancedPricingImportExport/composer.json
+++ b/app/code/Magento/AdvancedPricingImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-advanced-pricing-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-inventory": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/Authorization/composer.json b/app/code/Magento/Authorization/composer.json
index 0ca367d4854dfe5c35811d15aee4d718c0a4edb7..af88e8376dc756cb9e1f6180848df41e6fd8b5f3 100644
--- a/app/code/Magento/Authorization/composer.json
+++ b/app/code/Magento/Authorization/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-authorization",
     "description": "Authorization module provides access to Magento ACL functionality.",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/Authorizenet/composer.json b/app/code/Magento/Authorizenet/composer.json
index 0c9e9641b6076850310edd75a2a4ea5ed3ccd094..b93cb6688f56d826a8d981518612897aae6f1ac8 100644
--- a/app/code/Magento/Authorizenet/composer.json
+++ b/app/code/Magento/Authorizenet/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-authorizenet",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-sales": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-quote": "100.2.*",
diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json
index 7d428636a1f45e23d81879c99baaeef6744518fc..5cfe6955b46bb99f6dd8c76cd58e3ba9bb6f28ad 100644
--- a/app/code/Magento/Backend/composer.json
+++ b/app/code/Magento/Backend/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-backend",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-directory": "100.2.*",
         "magento/module-developer": "100.2.*",
diff --git a/app/code/Magento/Backup/composer.json b/app/code/Magento/Backup/composer.json
index 21ed6f1780a41348c5bb26556c14fcaa02c08770..ee05d6726db4c3bea7460893242d546a511fe0cc 100644
--- a/app/code/Magento/Backup/composer.json
+++ b/app/code/Magento/Backup/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-backup",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-cron": "100.2.*",
diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json
index 3b77e208837a4a4341baabbae615b7e35b266500..91cacf6add2b891dc4ad759cb6b1e9a6990cb397 100644
--- a/app/code/Magento/Braintree/composer.json
+++ b/app/code/Magento/Braintree/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-braintree",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/magento-composer-installer": "*",
         "magento/module-config": "100.2.*",
diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js
index 184260c39e954d1c5a1fd6d45b34f09fcab9daa7..075a1fdaf1fc118f42832fa438762715420a585a 100644
--- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js
+++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js
@@ -98,7 +98,6 @@ define([
             quote.totals.subscribe(function () {
                 if (self.grandTotalAmount !== quote.totals()['base_grand_total']) {
                     self.grandTotalAmount = quote.totals()['base_grand_total'];
-                    self.reInitPayPal();
                 }
             });
 
diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
index 50a3caaf68b3bd39ce1458e4883b4c1dd35c0525..538c80d9b1cf27af4ba14c911b0d0a6913c403c7 100644
--- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
+++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
@@ -268,15 +268,12 @@ class BundlePanel extends AbstractModifier
             'arguments' => [
                 'data' => [
                     'config' => [
-                        'componentType' => 'dynamicRows',
+                        'componentType' => Container::NAME,
+                        'component' => 'Magento_Bundle/js/components/bundle-dynamic-rows',
                         'template' => 'ui/dynamic-rows/templates/collapsible',
-                        'label' => '',
                         'additionalClasses' => 'admin__field-wide',
-                        'collapsibleHeader' => true,
-                        'columnsHeader' => false,
-                        'deleteProperty' => false,
-                        'addButton' => false,
                         'dataScope' => 'data.bundle_options',
+                        'bundleSelectionsName' => 'product_bundle_container.bundle_selections'
                     ],
                 ],
             ],
@@ -318,14 +315,11 @@ class BundlePanel extends AbstractModifier
                                     'arguments' => [
                                         'data' => [
                                             'config' => [
-                                                'componentType' => DynamicRows::NAME,
-                                                'label' => '',
+                                                'componentType' => Container::NAME,
+                                                'component' => 'Magento_Bundle/js/components/bundle-dynamic-rows-grid',
                                                 'sortOrder' => 50,
                                                 'additionalClasses' => 'admin__field-wide',
-                                                'component' => 'Magento_Ui/js/dynamic-rows/dynamic-rows-grid',
                                                 'template' => 'ui/dynamic-rows/templates/default',
-                                                'columnsHeader' => false,
-                                                'columnsHeaderAfterRender' => true,
                                                 'provider' => 'product_form.product_form_data_source',
                                                 'dataProvider' => '${ $.dataScope }' . '.bundle_button_proxy',
                                                 'identificationDRProperty' => 'product_id',
@@ -343,8 +337,7 @@ class BundlePanel extends AbstractModifier
                                                     'selection_qty' => '',
                                                 ],
                                                 'links' => ['insertData' => '${ $.provider }:${ $.dataProvider }'],
-                                                'source' => 'product',
-                                                'addButton' => false,
+                                                'source' => 'product'
                                             ],
                                         ],
                                     ],
@@ -561,7 +554,7 @@ class BundlePanel extends AbstractModifier
                         'componentType' => Container::NAME,
                         'isTemplate' => true,
                         'component' => 'Magento_Ui/js/dynamic-rows/record',
-                        'is_collection' => true,
+                        'is_collection' => true
                     ],
                 ],
             ],
diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json
index ab587044476db47c0a824cfdb130988f22591971..24756bdf950a7a42431e31cbc08090ca0141eb27 100644
--- a/app/code/Magento/Bundle/composer.json
+++ b/app/code/Magento/Bundle/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-bundle",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-tax": "100.2.*",
diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows-grid.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows-grid.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9a924e1cffe696688fed502bc715347c8afb8d2
--- /dev/null
+++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows-grid.js
@@ -0,0 +1,59 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+    'underscore',
+    'Magento_Ui/js/dynamic-rows/dynamic-rows-grid'
+], function (_, dynamicRowsGrid) {
+    'use strict';
+
+    return dynamicRowsGrid.extend({
+        defaults: {
+            label: '',
+            columnsHeader: false,
+            columnsHeaderAfterRender: true,
+            addButton: false
+        },
+
+        /**
+         * Initialize elements from grid
+         *
+         * @param {Array} data
+         *
+         * @returns {Object} Chainable.
+         */
+        initElements: function (data) {
+            var newData = this.getNewData(data),
+                recordIndex;
+
+            this.parsePagesData(data);
+
+            if (newData.length) {
+                if (this.insertData().length) {
+                    recordIndex = data.length - newData.length - 1;
+
+                    _.each(newData, function (newRecord) {
+                        this.processingAddChild(newRecord, ++recordIndex, newRecord[this.identificationProperty]);
+                    }, this);
+                }
+            }
+
+            return this;
+        },
+
+        /**
+         * Mapping value from grid
+         *
+         * @param {Array} data
+         */
+        mappingValue: function (data) {
+            if (_.isEmpty(data)) {
+                return;
+            }
+
+            this._super();
+        }
+    });
+});
diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows.js
new file mode 100644
index 0000000000000000000000000000000000000000..b36d8003a399fb4af88d3e3cfab34559e2e80bea
--- /dev/null
+++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-dynamic-rows.js
@@ -0,0 +1,98 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+    'underscore',
+    'mageUtils',
+    'uiRegistry',
+    'Magento_Ui/js/dynamic-rows/dynamic-rows'
+], function (_, utils, registry, dynamicRows) {
+    'use strict';
+
+    return dynamicRows.extend({
+        defaults: {
+            label: '',
+            collapsibleHeader: true,
+            columnsHeader: false,
+            deleteProperty: false,
+            addButton: false
+        },
+
+        /**
+         * Set new data to dataSource,
+         * delete element
+         *
+         * @param {Array} data - record data
+         */
+        _updateData: function (data) {
+            var elems = _.clone(this.elems()),
+                path,
+                dataArr,
+                optionBaseData;
+
+            dataArr = this.recordData.splice(this.startIndex, this.recordData().length - this.startIndex);
+            dataArr.splice(0, this.pageSize);
+            elems = _.sortBy(this.elems(), function (elem) {
+                return ~~elem.index;
+            });
+
+            data.concat(dataArr).forEach(function (rec, idx) {
+                if (elems[idx]) {
+                    elems[idx].recordId = rec[this.identificationProperty];
+                }
+
+                if (!rec.position) {
+                    rec.position = this.maxPosition;
+                    this.setMaxPosition();
+                }
+
+                path = this.dataScope + '.' + this.index + '.' + (this.startIndex + idx);
+                optionBaseData = _.pick(rec, function (value) {
+                    return !_.isObject(value);
+                });
+                this.source.set(path, optionBaseData);
+                this.source.set(path + '.bundle_button_proxy', []);
+                this.source.set(path + '.bundle_selections', []);
+                this.removeBundleItemsFromOption(idx);
+                _.each(rec['bundle_selections'], function (obj, index) {
+                    this.source.set(path + '.bundle_button_proxy' + '.' + index, rec['bundle_button_proxy'][index]);
+                    this.source.set(path + '.bundle_selections' + '.' + index, obj);
+                }, this);
+            }, this);
+
+            this.elems(elems);
+        },
+
+        /**
+         *  Removes nested dynamic-rows-grid rendered records from option
+         *
+         * @param {Number|String} index - element index
+         */
+        removeBundleItemsFromOption: function (index) {
+            var bundleSelections = registry.get(this.name + '.' + index + '.' + this.bundleSelectionsName),
+                bundleSelectionsLength = (bundleSelections.elems() || []).length,
+                i;
+
+            if (bundleSelectionsLength) {
+                for (i = 0; i < bundleSelectionsLength; i++) {
+                    bundleSelections.elems()[0].destroy();
+                }
+            }
+        },
+
+        /**
+        * {@inheritdoc}
+        */
+        processingAddChild: function (ctx, index, prop) {
+            var recordIds = _.map(this.recordData(), function (rec) {
+                return parseInt(rec['record_id'], 10);
+            }),
+            maxRecordId = _.max(recordIds);
+
+            prop = maxRecordId > -1 ? maxRecordId + 1 : prop;
+            this._super(ctx, index, prop);
+        }
+    });
+});
diff --git a/app/code/Magento/BundleImportExport/composer.json b/app/code/Magento/BundleImportExport/composer.json
index 3d7900d98287c1eba32a5badd2d5b2fdc1857f25..2f5e3afdbff86ded9c88161ebea832c29b37f229 100644
--- a/app/code/Magento/BundleImportExport/composer.json
+++ b/app/code/Magento/BundleImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-bundle-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-import-export": "100.2.*",
         "magento/module-catalog-import-export": "100.2.*",
diff --git a/app/code/Magento/CacheInvalidate/composer.json b/app/code/Magento/CacheInvalidate/composer.json
index cafccadb41ad869ff87ee8eb154c747f569a4c79..c886e069b66e37d3b0c7a12af377a250cfc75192 100644
--- a/app/code/Magento/CacheInvalidate/composer.json
+++ b/app/code/Magento/CacheInvalidate/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-cache-invalidate",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-page-cache": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json
index 9d0ce3db92aa402a7c247fed21185953c4707342..45ecd32464e9cc3f647264420961d6848b0445e9 100644
--- a/app/code/Magento/Captcha/composer.json
+++ b/app/code/Magento/Captcha/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-captcha",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-customer": "100.2.*",
         "magento/module-checkout": "100.2.*",
diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php
index 9e9f18e0113717ad6853ea5d4512661a897e926c..c913c82de1acdecbf3328c37fe7529dfbab193ba 100644
--- a/app/code/Magento/Catalog/Model/Product.php
+++ b/app/code/Magento/Catalog/Model/Product.php
@@ -22,7 +22,6 @@ use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryExtensionFactory;
  * @method Product setHasError(bool $value)
  * @method \Magento\Catalog\Model\ResourceModel\Product getResource()
  * @method null|bool getHasError()
- * @method Product setAssociatedProductIds(array $productIds)
  * @method array getAssociatedProductIds()
  * @method Product setNewVariationsAttributeSetId(int $value)
  * @method int getNewVariationsAttributeSetId()
@@ -2614,4 +2613,16 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
         }
         return $this->mediaGalleryProcessor;
     }
+
+    /**
+     * Set the associated products
+     *
+     * @param array $productIds
+     * @return $this
+     */
+    public function setAssociatedProductIds(array $productIds)
+    {
+        $this->getExtensionAttributes()->setConfigurableProductLinks($productIds);
+        return $this;
+    }
 }
diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php
index 4385c8add37aef25dc52a888d2ff839b49e734db..27796e1cda2a167848c2a3b8fb0d096f40c172d6 100644
--- a/app/code/Magento/Catalog/Model/ProductRepository.php
+++ b/app/code/Magento/Catalog/Model/ProductRepository.php
@@ -640,6 +640,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
 
         $collection->load();
 
+        $collection->addCategoryIds();
         $searchResult = $this->searchResultsFactory->create();
         $searchResult->setSearchCriteria($searchCriteria);
         $searchResult->setItems($collection->getItems());
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/AbstractEav.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/AbstractEav.php
index d9612f18c9111df4634e18cb8b9abf523643f2e5..432bc696ef7cecd822b5168e7da70a9ed1cd4fc5 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/AbstractEav.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/AbstractEav.php
@@ -197,7 +197,7 @@ abstract class AbstractEav extends \Magento\Catalog\Model\ResourceModel\Product\
         )->joinLeft(
             ['e' => $this->getTable('catalog_product_entity')],
             'e.' . $linkField .' = l.parent_id',
-            ['e.entity_id as parent_id']
+            []
         )->join(
             ['cs' => $this->getTable('store')],
             '',
@@ -205,9 +205,17 @@ abstract class AbstractEav extends \Magento\Catalog\Model\ResourceModel\Product\
         )->join(
             ['i' => $idxTable],
             'l.child_id = i.entity_id AND cs.store_id = i.store_id',
-            ['attribute_id', 'store_id', 'value']
+            []
         )->group(
-            ['parent_id', 'i.attribute_id', 'i.store_id', 'i.value']
+            ['parent_id', 'i.attribute_id', 'i.store_id', 'i.value', 'l.child_id']
+        )->columns(
+            [
+                'parent_id' => 'e.entity_id',
+                'attribute_id' => 'i.attribute_id',
+                'store_id' => 'i.store_id',
+                'value' => 'i.value',
+                'source_id' => 'l.child_id'
+            ]
         );
         if ($parentIds !== null) {
             $select->where('e.entity_id IN(?)', $parentIds);
@@ -222,7 +230,7 @@ abstract class AbstractEav extends \Magento\Catalog\Model\ResourceModel\Product\
                 'select' => $select,
                 'entity_field' => new \Zend_Db_Expr('l.parent_id'),
                 'website_field' => new \Zend_Db_Expr('cs.website_id'),
-                'store_field' => new \Zend_Db_Expr('cs.store_id')
+                'store_field' => new \Zend_Db_Expr('cs.store_id'),
             ]
         );
 
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Decimal.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Decimal.php
index e8d9889e68d59384e74cfb3fc0491a2edb8f3edb..a45d4f13a1a9a811fffb6269bf94575675c60d80 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Decimal.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Decimal.php
@@ -85,6 +85,7 @@ class Decimal extends AbstractEav
                 'pdd.attribute_id',
                 'cs.store_id',
                 'value' => $productValueExpression,
+                'source_id' => 'cpe.entity_id',
             ]
         );
 
@@ -116,7 +117,7 @@ class Decimal extends AbstractEav
                 'select' => $select,
                 'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
                 'website_field' => new \Zend_Db_Expr('cs.website_id'),
-                'store_field' => new \Zend_Db_Expr('cs.store_id')
+                'store_field' => new \Zend_Db_Expr('cs.store_id'),
             ]
         );
 
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
index c4eda1c987192acb5dd7e5ce003fe8b9cff0bdc6..1d37c57aa8b251bc73edf6e4a06aed1789cdc476 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
@@ -178,6 +178,7 @@ class Source extends AbstractEav
                 'pid.attribute_id',
                 'pid.store_id',
                 'value' => $ifNullSql,
+                'pid.entity_id',
             ]
         )->where(
             'pid.attribute_id IN(?)',
@@ -200,7 +201,7 @@ class Source extends AbstractEav
                 'select' => $select,
                 'entity_field' => new \Zend_Db_Expr('pid.entity_id'),
                 'website_field' => new \Zend_Db_Expr('pid.website_id'),
-                'store_field' => new \Zend_Db_Expr('pid.store_id')
+                'store_field' => new \Zend_Db_Expr('pid.store_id'),
             ]
         );
         $query = $select->insertFromSelect($idxTable);
@@ -221,11 +222,7 @@ class Source extends AbstractEav
         $connection = $this->getConnection();
 
         // prepare multiselect attributes
-        if ($attributeId === null) {
-            $attrIds = $this->_getIndexableAttributes(true);
-        } else {
-            $attrIds = [$attributeId];
-        }
+        $attrIds = $attributeId === null ? $this->_getIndexableAttributes(true) : [$attributeId];
 
         if (!$attrIds) {
             return $this;
@@ -247,20 +244,20 @@ class Source extends AbstractEav
         $productValueExpression = $connection->getCheckSql('pvs.value_id > 0', 'pvs.value', 'pvd.value');
         $select = $connection->select()->from(
             ['pvd' => $this->getTable('catalog_product_entity_varchar')],
-            [$productIdField, 'attribute_id']
+            []
         )->join(
             ['cs' => $this->getTable('store')],
             '',
-            ['store_id']
+            []
         )->joinLeft(
             ['pvs' => $this->getTable('catalog_product_entity_varchar')],
             "pvs.{$productIdField} = pvd.{$productIdField} AND pvs.attribute_id = pvd.attribute_id"
             . ' AND pvs.store_id=cs.store_id',
-            ['value' => $productValueExpression]
+            []
         )->joinLeft(
             ['cpe' => $this->getTable('catalog_product_entity')],
             "cpe.{$productIdField} = pvd.{$productIdField}",
-            ['entity_id']
+            []
         )->where(
             'pvd.store_id=?',
             $connection->getIfNullSql('pvs.store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID)
@@ -272,6 +269,14 @@ class Source extends AbstractEav
             $attrIds
         )->where(
             'cpe.entity_id IS NOT NULL'
+        )->columns(
+            [
+                'entity_id' => 'cpe.entity_id',
+                'attribute_id' => 'attribute_id',
+                'store_id' => 'cs.store_id',
+                'value' => $productValueExpression,
+                'source_id' => 'cpe.entity_id',
+            ]
         );
 
         $statusCond = $connection->quoteInto('=?', ProductStatus::STATUS_ENABLED);
@@ -289,30 +294,11 @@ class Source extends AbstractEav
                 'select' => $select,
                 'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
                 'website_field' => new \Zend_Db_Expr('cs.website_id'),
-                'store_field' => new \Zend_Db_Expr('cs.store_id')
+                'store_field' => new \Zend_Db_Expr('cs.store_id'),
             ]
         );
 
-        $i = 0;
-        $data = [];
-        $query = $select->query();
-        while ($row = $query->fetch()) {
-            $values = explode(',', $row['value']);
-            foreach ($values as $valueId) {
-                if (isset($options[$row['attribute_id']][$valueId])) {
-                    $data[] = [$row['entity_id'], $row['attribute_id'], $row['store_id'], $valueId];
-                    $i++;
-                    if ($i % 10000 == 0) {
-                        $this->_saveIndexData($data);
-                        $data = [];
-                    }
-                }
-            }
-        }
-
-        $this->_saveIndexData($data);
-        unset($options);
-        unset($data);
+        $this->saveDataFromSelect($select, $options);
 
         return $this;
     }
@@ -331,7 +317,7 @@ class Source extends AbstractEav
         $connection = $this->getConnection();
         $connection->insertArray(
             $this->getIdxTable(),
-            ['entity_id', 'attribute_id', 'store_id', 'value'],
+            ['entity_id', 'attribute_id', 'store_id', 'value', 'source_id'],
             $data
         );
         return $this;
@@ -348,4 +334,31 @@ class Source extends AbstractEav
     {
         return $this->tableStrategy->getTableName('catalog_product_index_eav');
     }
+
+    /**
+     * @param \Magento\Framework\DB\Select $select
+     * @param array $options
+     * @return void
+     */
+    private function saveDataFromSelect(\Magento\Framework\DB\Select $select, array $options)
+    {
+        $i = 0;
+        $data = [];
+        $query = $select->query();
+        while ($row = $query->fetch()) {
+            $values = explode(',', $row['value']);
+            foreach ($values as $valueId) {
+                if (isset($options[$row['attribute_id']][$valueId])) {
+                    $data[] = [$row['entity_id'], $row['attribute_id'], $row['store_id'], $valueId, $row['source_id']];
+                    $i++;
+                    if ($i % 10000 == 0) {
+                        $this->_saveIndexData($data);
+                        $data = [];
+                    }
+                }
+            }
+        }
+
+        $this->_saveIndexData($data);
+    }
 }
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
index 289445ae2daf07c4132f6d69372c84fcfb36a066..2b979ff79fe5c498215b6b144e71897b9ca2c913 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
@@ -368,7 +368,7 @@ class DefaultPrice extends AbstractIndexer implements PriceInterface
                 'select' => $select,
                 'entity_field' => new \Zend_Db_Expr('e.entity_id'),
                 'website_field' => new \Zend_Db_Expr('cw.website_id'),
-                'store_field' => new \Zend_Db_Expr('cs.store_id')
+                'store_field' => new \Zend_Db_Expr('cs.store_id'),
             ]
         );
 
diff --git a/app/code/Magento/Catalog/Setup/InstallSchema.php b/app/code/Magento/Catalog/Setup/InstallSchema.php
index 171e96efe9b0a1e714e1331fc2ed95a175cd58fb..a2ba6aa283f6516021f0baffaafd6e6470c060f0 100644
--- a/app/code/Magento/Catalog/Setup/InstallSchema.php
+++ b/app/code/Magento/Catalog/Setup/InstallSchema.php
@@ -18,6 +18,7 @@ class InstallSchema implements InstallSchemaInterface
     /**
      * {@inheritdoc}
      * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     * @throws \Zend_Db_Exception
      */
     public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
     {
@@ -2429,7 +2430,6 @@ class InstallSchema implements InstallSchemaInterface
                 'option_id',
                 $installer->getTable('catalog_product_option'),
                 'option_id',
-                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE,
                 \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
             )
             ->setComment(
diff --git a/app/code/Magento/Catalog/Setup/UpgradeSchema.php b/app/code/Magento/Catalog/Setup/UpgradeSchema.php
index cbcce1d427bb6c91fa000bff0b4a069ab02d034f..7fc2ef7d219ba917aa59c9887749a9024bda49ce 100755
--- a/app/code/Magento/Catalog/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Catalog/Setup/UpgradeSchema.php
@@ -61,9 +61,56 @@ class UpgradeSchema implements UpgradeSchemaInterface
             }
         }
 
+        if (version_compare($context->getVersion(), '2.1.2', '<')) {
+            $this->addSourceEntityIdToProductEavIndex($setup);
+        }
+
         $setup->endSetup();
     }
 
+    /**
+     * Add the column 'source_id' to the Product EAV index tables.
+     * It allows to identify which entity was used to create value in the index.
+     * It is useful to identify original entity in a composite products.
+     *
+     * @param SchemaSetupInterface $setup
+     * @return void
+     */
+    private function addSourceEntityIdToProductEavIndex(SchemaSetupInterface $setup)
+    {
+        $tables = [
+            'catalog_product_index_eav',
+            'catalog_product_index_eav_idx',
+            'catalog_product_index_eav_tmp',
+            'catalog_product_index_eav_decimal',
+            'catalog_product_index_eav_decimal_idx',
+            'catalog_product_index_eav_decimal_tmp',
+        ];
+        $connection = $setup->getConnection();
+        foreach ($tables as $tableName) {
+            $tableName = $setup->getTable($tableName);
+            $connection->addColumn(
+                $tableName,
+                'source_id',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+                    'unsigned' => true,
+                    'nullable' => false,
+                    'default' => 0,
+                    'comment' => 'Original entity Id for attribute value',
+                ]
+            );
+            $connection->dropIndex($tableName, $connection->getPrimaryKeyName($tableName));
+            $primaryKeyFields = ['entity_id', 'attribute_id', 'store_id', 'value', 'source_id'];
+            $setup->getConnection()->addIndex(
+                $tableName,
+                $connection->getIndexName($tableName, $primaryKeyFields),
+                $primaryKeyFields,
+                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_PRIMARY
+            );
+        }
+    }
+
     /**
      * @param SchemaSetupInterface $setup
      * @return void
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
index e91bb469eb112d4de70cba92bff5b93ca069ca58..8c08d0c63bc5e93c7ab690f6441eaa02281b3255 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
@@ -715,6 +715,7 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase
             ->method('process')
             ->with($searchCriteriaMock, $collectionMock);
         $collectionMock->expects($this->once())->method('load');
+        $collectionMock->expects($this->once())->method('addCategoryIds');
         $collectionMock->expects($this->once())->method('getItems')->willReturn([$itemsMock]);
         $collectionMock->expects($this->once())->method('getSize')->willReturn(128);
         $searchResultsMock = $this->getMock(
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
index 0fbba264f7e93383f07434a7fe2ebf4586d54516..886c7a070adf93b68ec54f45813ba80911029e44 100755
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
@@ -315,17 +315,6 @@ class General extends AbstractModifier
             $importsConfig = [
                 'mask' => $this->locator->getStore()->getConfig('catalog/fields_masks/' . $listener),
                 'component' => 'Magento_Catalog/js/components/import-handler',
-                'imports' => [
-                    'handleNameChanges' => '${$.provider}:data.product.name',
-                    'handleDescriptionChanges' => '${$.provider}:data.product.description',
-                    'handleSkuChanges' => '${$.provider}:data.product.sku',
-                    'handleColorChanges' => '${$.provider}:data.product.color',
-                    'handleCountryChanges' => '${$.provider}:data.product.country_of_manufacture',
-                    'handleGenderChanges' => '${$.provider}:data.product.gender',
-                    'handleMaterialChanges' => '${$.provider}:data.product.material',
-                    'handleShortDescriptionChanges' => '${$.provider}:data.product.short_description',
-                    'handleSizeChanges' => '${$.provider}:data.product.size'
-                ],
                 'allowImport' => !$this->locator->getProduct()->getId(),
             ];
 
diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json
index 64157f6bc8af74e82975668e43a62ef583227908..8c77dd77f98b74a53ee1124a16c473d843d21d60 100644
--- a/app/code/Magento/Catalog/composer.json
+++ b/app/code/Magento/Catalog/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-eav": "100.2.*",
         "magento/module-cms": "101.1.*",
diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml
index c629bf6a180ccc0ec42e51a67352f6eaa673dd86..0c9e6bb356fe14101d467a04aa91b23fb6873f09 100644
--- a/app/code/Magento/Catalog/etc/module.xml
+++ b/app/code/Magento/Catalog/etc/module.xml
@@ -6,7 +6,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="Magento_Catalog" setup_version="2.1.1">
+    <module name="Magento_Catalog" setup_version="2.1.2">
         <sequence>
             <module name="Magento_Eav"/>
             <module name="Magento_Cms"/>
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js
index e67bde152475f62769d6eaff73548893f98ed7d0..a0aec918ccda24f1ae05486bc5d9ec59522f0ca7 100644
--- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js
+++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js
@@ -4,148 +4,78 @@
  */
 
 define([
+    'Magento_Ui/js/form/element/abstract',
     'underscore',
-    'Magento_Ui/js/form/element/textarea'
-], function (_, Textarea) {
+    'uiRegistry'
+], function (Abstract, _, registry) {
     'use strict';
 
-    return Textarea.extend({
+    return Abstract.extend({
         defaults: {
             allowImport: true,
             autoImportIfEmpty: false,
-            values: {
-                'name': '',
-                'description': '',
-                'sku': '',
-                'color': '',
-                'country_of_manufacture': '',
-                'gender': '',
-                'material': '',
-                'short_description': '',
-                'size': ''
-            },
-            valueUpdate: 'input',
-            mask: ''
+            values: {},
+            mask: '',
+            queryTemplate: 'ns = ${ $.ns }, index = '
         },
 
-        /**
-         * Handle name value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleNameChanges: function (newValue) {
-            this.values.name = newValue;
-            this.updateValue();
-        },
-
-        /**
-         * Handle description value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleDescriptionChanges: function (newValue) {
-            this.values.description = newValue;
-            this.updateValue();
-        },
+        /** @inheritdoc */
+        initialize: function () {
+            this._super();
 
-        /**
-         * Handle sku value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleSkuChanges: function (newValue) {
-            if (this.code !== 'sku') {
-                this.values.sku = newValue;
-                this.updateValue();
+            if (this.allowImport) {
+                this.setHandlers();
             }
         },
 
         /**
-         * Handle color value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleColorChanges: function (newValue) {
-            this.values.color = newValue;
-            this.updateValue();
-        },
-
-        /**
-         * Handle country value changes, if it's allowed
-         *
-         * @param {String} newValue
+         * Split mask placeholder and attach events to placeholder fields.
          */
-        handleCountryChanges: function (newValue) {
-            this.values.country = newValue;
-            this.updateValue();
-        },
+        setHandlers: function () {
+            var str = this.mask || '',
+                placeholders;
 
-        /**
-         * Handle gender value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleGenderChanges: function (newValue) {
-            this.values.gender = newValue;
-            this.updateValue();
-        },
+            placeholders = str.match(/{{(.*?)}}/g); // Get placeholders
 
-        /**
-         * Handle material value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleMaterialChanges: function (newValue) {
-            this.values.material = newValue;
-            this.updateValue();
-        },
+            _.each(placeholders, function (placeholder) {
+                placeholder = placeholder.replace(/[{{}}]/g, ''); // Remove curly braces
 
-        /**
-         * Handle short description value changes, if it's allowed
-         *
-         * @param {String} newValue
-         */
-        handleShortDescriptionChanges: function (newValue) {
-            this.values['short_description'] = newValue;
-            this.updateValue();
+                registry.get(this.queryTemplate + placeholder, function (component) {
+                    this.values[placeholder] = component.getPreview();
+                    component.on('value', this.updateValue.bind(this, placeholder, component));
+                    component.valueUpdate = 'keyup';
+                }.bind(this));
+            }, this);
         },
 
         /**
-         * Handle size value changes, if it's allowed
+         * Update field with mask value, if it's allowed.
          *
-         * @param {String} newValue
+         * @param {Object} placeholder
+         * @param {Object} component
          */
-        handleSizeChanges: function (newValue) {
-            this.values.size = newValue;
-            this.updateValue();
-        },
+        updateValue: function (placeholder, component) {
+            var string = this.mask || '',
+                nonEmptyValueFlag = false;
 
-        /**
-         * Update field value, if it's allowed
-         */
-        updateValue: function () {
-            var str = this.mask || '',
-                nonEmptyValueFlag = false,
-                tmpElement;
+            if (placeholder) {
+                this.values[placeholder] = component.getPreview() || '';
+            }
 
             if (!this.allowImport) {
                 return;
             }
 
-            if (str) {
-                _.each(this.values, function (propertyValue, propertyName) {
-                    str = str.replace('{{' + propertyName + '}}', propertyValue);
-                    nonEmptyValueFlag = nonEmptyValueFlag || !!propertyValue;
-                });
-            }
-
-            // strip tags
-            tmpElement = document.createElement('div');
-            tmpElement.innerHTML = str;
-            str =  tmpElement.textContent || tmpElement.innerText || '';
+            _.each(this.values, function (propertyValue, propertyName) {
+                string = string.replace('{{' + propertyName + '}}', propertyValue);
+                nonEmptyValueFlag = nonEmptyValueFlag || !!propertyValue;
+            });
 
             if (nonEmptyValueFlag) {
-                this.value(str);
+                string = string.replace(/(<([^>]+)>)/ig, ''); // Remove html tags
+                this.value(string);
+            } else {
+                this.value('');
             }
         },
 
@@ -169,13 +99,20 @@ define([
          *  and disallow/allow import value
          */
         userChanges: function () {
+
+            /**
+             *  As userChanges is called before updateValue,
+             *  we forced to get value from component by reference
+             */
+            var actualValue = arguments[1].currentTarget.value;
+
             this._super();
 
-            if (this.value() === '') {
+            if (actualValue === '') {
                 this.allowImport = true;
 
                 if (this.autoImportIfEmpty) {
-                    this.updateValue();
+                    this.updateValue(null, null);
                 }
             } else {
                 this.allowImport = false;
diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view.xml
index 4c8ae8eaae9524fe75f74ba5f0dd45ef045c2954..298cdcc29e953a74625a3834edab6b9a5eb47631 100644
--- a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view.xml
+++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view.xml
@@ -28,53 +28,6 @@
                     </block>
                     <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml">
                         <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/>
-                        <!-- The following code shows how to set your own pager increments -->
-                        <!--
-                            <action method="setDefaultListPerPage">
-                            <argument name="limit" xsi:type="string">4</argument>
-                        </action>
-                        <action method="setDefaultGridPerPage">
-                            <argument name="limit" xsi:type="string">3</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">list</argument>
-                            <argument name="limit" xsi:type="string">2</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">list</argument>
-                            <argument name="limit" xsi:type="string">4</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">list</argument>
-                            <argument name="limit" xsi:type="string">6</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">list</argument>
-                            <argument name="limit" xsi:type="string">8</argument>
-                        </action>
-                        <action method="addPagerLimit" translate="label">
-                            <argument name="mode" xsi:type="string">list</argument>
-                            <argument name="limit" xsi:type="string">all</argument>
-                            <argument name="label" xsi:type="string">All</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">grid</argument>
-                            <argument name="limit" xsi:type="string">3</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">grid</argument>
-                            <argument name="limit" xsi:type="string">6</argument>
-                        </action>
-                        <action method="addPagerLimit">
-                            <argument name="mode" xsi:type="string">grid</argument>
-                            <argument name="limit" xsi:type="string">9</argument>
-                        </action>
-                        <action method="addPagerLimit" translate="label">
-                            <argument name="mode" xsi:type="string">grid</argument>
-                            <argument name="limit" xsi:type="string">all</argument>
-                            <argument name="label" xsi:type="string">All</argument>
-                        </action>
-                        -->
                     </block>
                     <action method="setToolbarBlockName">
                         <argument name="name" xsi:type="string">product_list_toolbar</argument>
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
index afb2e86b6248a79523405c78acd1cf27953b90c2..54208dcdba534139c96e8fd975e0757f9ecb11e1 100644
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
@@ -2304,7 +2304,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
 
         $sku = $rowData[self::COL_SKU];
 
-        if (isset($this->_oldSku[$sku])) {
+        if (isset($this->_oldSku[$sku]) && Import::BEHAVIOR_REPLACE !== $this->getBehavior()) {
             // can we get all necessary data from existent DB product?
             // check for supported type of existing product
             if (isset($this->_productTypeModels[$this->_oldSku[$sku]['type_id']])) {
@@ -2356,7 +2356,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
             $rowAttributesValid = $productTypeValidator->isRowValid(
                 $rowData,
                 $rowNum,
-                !isset($this->_oldSku[$sku])
+                !(isset($this->_oldSku[$sku]) && Import::BEHAVIOR_REPLACE !== $this->getBehavior())
             );
             if (!$rowAttributesValid && self::SCOPE_DEFAULT == $rowScope) {
                 // mark SCOPE_DEFAULT row as invalid for future child rows if product not in DB already
diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json
index 7dbd7f4bc5e656ff09712549886e97a95fa3f4f1..8ed5f43692df51482038e1d1f7d4b91f05fd8c23 100644
--- a/app/code/Magento/CatalogImportExport/composer.json
+++ b/app/code/Magento/CatalogImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-url-rewrite": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json
index 254d8d2db4bf9db35b338507cdd744d1aaf0e152..684f616ecd6fcfca7088c257afec000fba6a4b1d 100644
--- a/app/code/Magento/CatalogInventory/composer.json
+++ b/app/code/Magento/CatalogInventory/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-inventory",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json
index 71eb5b49db1fc68eadb064968796cfdaf1081d60..004ab82a028d3aba288b71a234dead24d63a4755 100644
--- a/app/code/Magento/CatalogRule/composer.json
+++ b/app/code/Magento/CatalogRule/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-rule",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-rule": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/CatalogRuleConfigurable/composer.json b/app/code/Magento/CatalogRuleConfigurable/composer.json
index cc51269e2d9720e380612cf56c712ff2459bbe35..b930380f7bb025ea409be398c013c12773cb2f20 100644
--- a/app/code/Magento/CatalogRuleConfigurable/composer.json
+++ b/app/code/Magento/CatalogRuleConfigurable/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-rule-configurable",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-configurable-product": "100.2.*",
         "magento/framework": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Aggregation/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Aggregation/DataProvider.php
index 9b75e6e6e0c325819d09f543cc445ae61eb7fb84..ddf86951068acc3c95017e54e489faf92e4b28cc 100644
--- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Aggregation/DataProvider.php
+++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Aggregation/DataProvider.php
@@ -6,6 +6,7 @@
 namespace Magento\CatalogSearch\Model\Adapter\Mysql\Aggregation;
 
 use Magento\Catalog\Model\Product;
+use Magento\CatalogInventory\Model\Stock;
 use Magento\Customer\Model\Session;
 use Magento\Eav\Model\Config;
 use Magento\Framework\App\ResourceConnection;
@@ -79,7 +80,13 @@ class DataProvider implements DataProviderInterface
 
         $select = $this->getSelect();
 
-        if ($attribute->getAttributeCode() == 'price') {
+        $select->joinInner(
+            ['entities' => $entityIdsTable->getName()],
+            'main_table.entity_id  = entities.entity_id',
+            []
+        );
+
+        if ($attribute->getAttributeCode() === 'price') {
             /** @var \Magento\Store\Model\Store $store */
             $store = $this->scopeResolver->getScope($currentScope);
             if (!$store instanceof \Magento\Store\Model\Store) {
@@ -94,19 +101,24 @@ class DataProvider implements DataProviderInterface
             $currentScopeId = $this->scopeResolver->getScope($currentScope)
                 ->getId();
             $table = $this->resource->getTableName(
-                'catalog_product_index_eav' . ($attribute->getBackendType() == 'decimal' ? '_decimal' : '')
+                'catalog_product_index_eav' . ($attribute->getBackendType() === 'decimal' ? '_decimal' : '')
             );
-            $select->from(['main_table' => $table], ['value'])
+            $subSelect = $select;
+            $subSelect->from(['main_table' => $table], ['main_table.value'])
+                ->joinLeft(
+                    ['stock_index' => $this->resource->getTableName('cataloginventory_stock_status')],
+                    'main_table.source_id = stock_index.product_id',
+                    []
+                )
                 ->where('main_table.attribute_id = ?', $attribute->getAttributeId())
-                ->where('main_table.store_id = ? ', $currentScopeId);
+                ->where('main_table.store_id = ? ', $currentScopeId)
+                ->where('stock_index.stock_status = ?', Stock::STOCK_IN_STOCK)
+                ->group(['main_table.entity_id', 'main_table.value']);
+            $parentSelect = $this->getSelect();
+            $parentSelect->from(['main_table' => $subSelect], ['main_table.value']);
+            $select = $parentSelect;
         }
 
-        $select->joinInner(
-            ['entities' => $entityIdsTable->getName()],
-            'main_table.entity_id  = entities.entity_id',
-            []
-        );
-
         return $select;
     }
 
diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/AliasResolver.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/AliasResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..7099ce2502b19e21de48ae570e2dc063be6162d1
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/AliasResolver.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Adapter\Mysql\Filter;
+
+
+use Magento\CatalogSearch\Model\Search\RequestGenerator;
+
+/**
+ * Purpose of class is to resolve table alias for Search Request filter
+ */
+class AliasResolver
+{
+    /**
+     * The suffix for stock status filter that may be added to the query beside the filter query
+     * Used when showing of Out of Stock products is disabled.
+     */
+    const STOCK_FILTER_SUFFIX = '_stock';
+
+    /**
+     * @param \Magento\Framework\Search\Request\FilterInterface $filter
+     * @return string alias of the filter in database
+     */
+    public function getAlias(\Magento\Framework\Search\Request\FilterInterface $filter)
+    {
+        $alias = null;
+        $field = $filter->getField();
+        switch ($field) {
+            case 'price':
+                $alias = 'price_index';
+                break;
+            case 'category_ids':
+                $alias = 'category_ids_index';
+                break;
+            default:
+                $alias = $field . RequestGenerator::FILTER_SUFFIX;
+                break;
+        }
+        return $alias;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php
index 05205f04f8b99cd903f345f8c1f7dc04384e7aee..fb579c1dce29c7da26b35288ff61040363f4f510 100644
--- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php
+++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php
@@ -8,8 +8,11 @@ namespace Magento\CatalogSearch\Model\Adapter\Mysql\Filter;
 use Magento\Catalog\Api\Data\ProductInterface;
 use Magento\Catalog\Model\Product;
 use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
+use Magento\CatalogInventory\Model\Stock;
 use Magento\CatalogSearch\Model\Search\TableMapper;
 use Magento\Eav\Model\Config;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\App\ResourceConnection;
 use Magento\Framework\App\ScopeResolverInterface;
 use Magento\Framework\DB\Adapter\AdapterInterface;
@@ -17,6 +20,7 @@ use Magento\Framework\EntityManager\MetadataPool;
 use Magento\Framework\Search\Adapter\Mysql\ConditionManager;
 use Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface;
 use Magento\Framework\Search\Request\FilterInterface;
+use Magento\Store\Model\ScopeInterface;
 use Magento\Store\Model\Store;
 
 /**
@@ -60,9 +64,14 @@ class Preprocessor implements PreprocessorInterface
     private $metadataPool;
 
     /**
-     * @var TableMapper
+     * @var ScopeConfigInterface
      */
-    private $tableMapper;
+    private $scopeConfig;
+
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
 
     /**
      * @param ConditionManager $conditionManager
@@ -71,6 +80,9 @@ class Preprocessor implements PreprocessorInterface
      * @param ResourceConnection $resource
      * @param TableMapper $tableMapper
      * @param string $attributePrefix
+     * @param ScopeConfigInterface $scopeConfig
+     * @param AliasResolver $aliasResolver
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(
         ConditionManager $conditionManager,
@@ -78,7 +90,9 @@ class Preprocessor implements PreprocessorInterface
         Config $config,
         ResourceConnection $resource,
         TableMapper $tableMapper,
-        $attributePrefix
+        $attributePrefix,
+        ScopeConfigInterface $scopeConfig = null,
+        AliasResolver $aliasResolver = null
     ) {
         $this->conditionManager = $conditionManager;
         $this->scopeResolver = $scopeResolver;
@@ -86,7 +100,16 @@ class Preprocessor implements PreprocessorInterface
         $this->resource = $resource;
         $this->connection = $resource->getConnection();
         $this->attributePrefix = $attributePrefix;
-        $this->tableMapper = $tableMapper;
+
+        if (null === $scopeConfig) {
+            $scopeConfig = ObjectManager::getInstance()->get(ScopeConfigInterface::class);
+        }
+        if (null === $aliasResolver) {
+            $aliasResolver = ObjectManager::getInstance()->get(AliasResolver::class);
+        }
+
+        $this->scopeConfig = $scopeConfig;
+        $this->aliasResolver = $aliasResolver;
     }
 
     /**
@@ -117,7 +140,7 @@ class Preprocessor implements PreprocessorInterface
         } elseif ($filter->getField() === 'category_ids') {
             return 'category_ids_index.category_id = ' . (int) $filter->getValue();
         } elseif ($attribute->isStatic()) {
-            $alias = $this->tableMapper->getMappingAlias($filter);
+            $alias = $this->aliasResolver->getAlias($filter);
             $resultQuery = str_replace(
                 $this->connection->quoteIdentifier($attribute->getAttributeCode()),
                 $this->connection->quoteIdentifier($alias . '.' . $attribute->getAttributeCode()),
@@ -208,7 +231,7 @@ class Preprocessor implements PreprocessorInterface
      */
     private function processTermSelect(FilterInterface $filter, $isNegation)
     {
-        $alias = $this->tableMapper->getMappingAlias($filter);
+        $alias = $this->aliasResolver->getAlias($filter);
         if (is_array($filter->getValue())) {
             $value = sprintf(
                 '%s IN (%s)',
@@ -224,9 +247,31 @@ class Preprocessor implements PreprocessorInterface
             $value
         );
 
+        if ($this->isAddStockFilter()) {
+            $resultQuery = sprintf(
+                '%1$s AND %2$s%3$s.stock_status = %4$s',
+                $resultQuery,
+                $alias,
+                AliasResolver::STOCK_FILTER_SUFFIX,
+                Stock::STOCK_IN_STOCK
+            );
+        }
+
         return $resultQuery;
     }
 
+    /**
+     * @return bool
+     */
+    private function isAddStockFilter()
+    {
+        $isShowOutOfStock = $this->scopeConfig->isSetFlag(
+            'cataloginventory/options/show_out_of_stock',
+            ScopeInterface::SCOPE_STORE
+        );
+        return false === $isShowOutOfStock;
+    }
+
     /**
      * Get product metadata pool
      *
diff --git a/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/ExclusionStrategy.php b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/ExclusionStrategy.php
new file mode 100644
index 0000000000000000000000000000000000000000..8626b2ea15b077fc42380afaba82b245e7387937
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/ExclusionStrategy.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Search\FilterMapper;
+
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+
+/**
+ * Strategy which processes exclusions from general rules
+ */
+class ExclusionStrategy implements FilterStrategyInterface
+{
+    /**
+     * @var \Magento\Framework\App\ResourceConnection
+     */
+    private $resourceConnection;
+
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    private $storeManager;
+
+    /**
+     * @param \Magento\Framework\App\ResourceConnection $resourceConnection
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param AliasResolver $aliasResolver
+     */
+    public function __construct(
+        \Magento\Framework\App\ResourceConnection $resourceConnection,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        AliasResolver $aliasResolver
+    ) {
+        $this->resourceConnection = $resourceConnection;
+        $this->storeManager = $storeManager;
+        $this->aliasResolver = $aliasResolver;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function apply(
+        \Magento\Framework\Search\Request\FilterInterface $filter,
+        \Magento\Framework\DB\Select $select
+    ) {
+        $isApplied = false;
+        $field = $filter->getField();
+        if ('price' === $field) {
+            $alias = $this->aliasResolver->getAlias($filter);
+            $tableName = $this->resourceConnection->getTableName('catalog_product_index_price');
+            $select->joinInner(
+                [
+                    $alias => $tableName
+                ],
+                $this->resourceConnection->getConnection()->quoteInto(
+                    'search_index.entity_id = price_index.entity_id AND price_index.website_id = ?',
+                    $this->storeManager->getWebsite()->getId()
+                ),
+                []
+            );
+            $isApplied = true;
+        } elseif ('category_ids' === $field) {
+            $alias = $this->aliasResolver->getAlias($filter);
+            $tableName = $this->resourceConnection->getTableName('catalog_category_product_index');
+            $select->joinInner(
+                [
+                    $alias => $tableName
+                ],
+                'search_index.entity_id = category_ids_index.product_id',
+                []
+            );
+            $isApplied = true;
+        }
+        return $isApplied;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterContext.php b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterContext.php
new file mode 100644
index 0000000000000000000000000000000000000000..d244e3d5f754893fb671a3b6c81565eb5c920ff7
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterContext.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Search\FilterMapper;
+
+
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+use Magento\Eav\Model\Config as EavConfig;
+use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+
+/**
+ * FilterContext represents a Context of the Strategy pattern
+ * Its responsibility is to choose appropriate strategy to apply passed filter to the Select
+ */
+class FilterContext implements FilterStrategyInterface
+{
+    /**
+     * @var ExclusionStrategy
+     */
+    private $exclusionStrategy;
+
+    /**
+     * @var EavConfig
+     */
+    private $eavConfig;
+
+    /**
+     * @var TermDropdownStrategy
+     */
+    private $termDropdownStrategy;
+
+    /**
+     * @var StaticAttributeStrategy
+     */
+    private $staticAttributeStrategy;
+
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
+
+    /**
+     * @param EavConfig $eavConfig
+     * @param AliasResolver $aliasResolver
+     * @param ExclusionStrategy $exclusionStrategy
+     * @param TermDropdownStrategy $termDropdownStrategy
+     * @param StaticAttributeStrategy $staticAttributeStrategy
+     */
+    public function __construct(
+        EavConfig $eavConfig,
+        AliasResolver $aliasResolver,
+        ExclusionStrategy $exclusionStrategy,
+        TermDropdownStrategy $termDropdownStrategy,
+        StaticAttributeStrategy $staticAttributeStrategy
+    ) {
+        $this->eavConfig = $eavConfig;
+        $this->aliasResolver = $aliasResolver;
+        $this->exclusionStrategy = $exclusionStrategy;
+        $this->termDropdownStrategy = $termDropdownStrategy;
+        $this->staticAttributeStrategy = $staticAttributeStrategy;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function apply(
+        \Magento\Framework\Search\Request\FilterInterface $filter,
+        \Magento\Framework\DB\Select $select
+    ) {
+        $isApplied = $this->exclusionStrategy->apply($filter, $select);
+
+        if (!$isApplied) {
+            $attribute = $this->getAttributeByCode($filter->getField());
+            if ($attribute) {
+                if ($filter->getType() === \Magento\Framework\Search\Request\FilterInterface::TYPE_TERM
+                    && in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true)
+                ) {
+                    $isApplied = $this->termDropdownStrategy->apply($filter, $select);
+                } elseif ($attribute->getBackendType() === AbstractAttribute::TYPE_STATIC) {
+                    $isApplied = $this->staticAttributeStrategy->apply($filter, $select);
+                }
+            }
+        }
+
+        return $isApplied;
+    }
+
+    /**
+     * @param string $field
+     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    private function getAttributeByCode($field)
+    {
+        return $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field);
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterStrategyInterface.php b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterStrategyInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf17f7d5132efbf8246af0de674d7c789551aa3e
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/FilterStrategyInterface.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Search\FilterMapper;
+
+/**
+ * FilterStrategyInterface provides the interface to work with strategies
+ */
+interface FilterStrategyInterface
+{
+    /**
+     * @param \Magento\Framework\Search\Request\FilterInterface $filter
+     * @param \Magento\Framework\DB\Select $select
+     * @return bool is filter was applied
+     */
+    public function apply(
+        \Magento\Framework\Search\Request\FilterInterface $filter,
+        \Magento\Framework\DB\Select $select
+    );
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/StaticAttributeStrategy.php b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/StaticAttributeStrategy.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb9d61b5a7f4c352d23096050a5acd292dc80d54
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/StaticAttributeStrategy.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Search\FilterMapper;
+
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+use Magento\Eav\Model\Config as EavConfig;
+
+/**
+ * This strategy handles static attributes
+ */
+class StaticAttributeStrategy implements FilterStrategyInterface
+{
+    /**
+     * @var \Magento\Framework\App\ResourceConnection
+     */
+    private $resourceConnection;
+
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
+
+    /**
+     * @var EavConfig
+     */
+    private $eavConfig;
+
+    /**
+     * @param \Magento\Framework\App\ResourceConnection $resourceConnection
+     * @param EavConfig $eavConfig
+     * @param AliasResolver $aliasResolver
+     */
+    public function __construct(
+        \Magento\Framework\App\ResourceConnection $resourceConnection,
+        EavConfig $eavConfig,
+        AliasResolver $aliasResolver
+    ) {
+        $this->resourceConnection = $resourceConnection;
+        $this->eavConfig = $eavConfig;
+        $this->aliasResolver = $aliasResolver;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function apply(
+        \Magento\Framework\Search\Request\FilterInterface $filter,
+        \Magento\Framework\DB\Select $select
+    ) {
+        $attribute = $this->getAttributeByCode($filter->getField());
+        $alias = $this->aliasResolver->getAlias($filter);
+        $select->joinInner(
+            [$alias => $attribute->getBackendTable()],
+            'search_index.entity_id = '
+            . $this->resourceConnection->getConnection()->quoteIdentifier("$alias.entity_id"),
+            []
+        );
+        return true;
+    }
+
+    /**
+     * @param string $field
+     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    private function getAttributeByCode($field)
+    {
+        return $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field);
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/TermDropdownStrategy.php b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/TermDropdownStrategy.php
new file mode 100644
index 0000000000000000000000000000000000000000..76828fe28f4348c8b90c9f1bf695906242c77222
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Search/FilterMapper/TermDropdownStrategy.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Search\FilterMapper;
+
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+use Magento\Eav\Model\Config as EavConfig;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Store\Model\ScopeInterface;
+use Magento\Store\Model\StoreManagerInterface;
+
+/**
+ * This strategy handles attributes which comply with two criteria:
+ *   - The filter for dropdown or multi-select attribute
+ *   - The filter is Term filter
+ *
+ */
+class TermDropdownStrategy implements FilterStrategyInterface
+{
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
+
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
+
+    /**
+     * @var EavConfig
+     */
+    private $eavConfig;
+
+    /**
+     * @var ResourceConnection
+     */
+    private $resourceConnection;
+
+    /**
+     * @var ScopeConfigInterface
+     */
+    private $scopeConfig;
+
+    /**
+     * @param StoreManagerInterface $storeManager
+     * @param ResourceConnection $resourceConnection
+     * @param EavConfig $eavConfig
+     * @param ScopeConfigInterface $scopeConfig
+     * @param AliasResolver $aliasResolver
+     */
+    public function __construct(
+        StoreManagerInterface $storeManager,
+        ResourceConnection $resourceConnection,
+        EavConfig $eavConfig,
+        ScopeConfigInterface $scopeConfig,
+        AliasResolver $aliasResolver
+    ) {
+        $this->storeManager = $storeManager;
+        $this->resourceConnection = $resourceConnection;
+        $this->eavConfig = $eavConfig;
+        $this->scopeConfig = $scopeConfig;
+        $this->aliasResolver = $aliasResolver;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function apply(
+        \Magento\Framework\Search\Request\FilterInterface $filter,
+        \Magento\Framework\DB\Select $select
+    ) {
+        $alias = $this->aliasResolver->getAlias($filter);
+        $attribute = $this->getAttributeByCode($filter->getField());
+        $joinCondition = sprintf(
+            'search_index.entity_id = %1$s.entity_id AND %1$s.attribute_id = %2$d AND %1$s.store_id = %3$d',
+            $alias,
+            $attribute->getId(),
+            $this->storeManager->getWebsite()->getId()
+        );
+        $select->joinLeft(
+            [$alias => $this->resourceConnection->getTableName('catalog_product_index_eav')],
+            $joinCondition,
+            []
+        );
+        if ($this->isAddStockFilter()) {
+            $stockAlias = $alias . AliasResolver::STOCK_FILTER_SUFFIX;
+            $select->joinLeft(
+                [
+                    $stockAlias => $this->resourceConnection->getTableName('cataloginventory_stock_status'),
+                ],
+                sprintf('%2$s.product_id = %1$s.source_id', $alias, $stockAlias),
+                []
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * @param string $field
+     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    private function getAttributeByCode($field)
+    {
+        return $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field);
+    }
+
+    /**
+     * @return bool
+     */
+    private function isAddStockFilter()
+    {
+        $isShowOutOfStock = $this->scopeConfig->isSetFlag(
+            'cataloginventory/options/show_out_of_stock',
+            ScopeInterface::SCOPE_STORE
+        );
+
+        return false === $isShowOutOfStock;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
index 1d30bb4a14d23a94d79a2faa5bc20823df220d8d..0e96e4de700259c9dc48c8f876983e2642316a86 100644
--- a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
+++ b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
@@ -99,6 +99,7 @@ class IndexBuilder implements IndexBuilderInterface
      *
      * @param RequestInterface $request
      * @return Select
+     * @throws \LogicException
      */
     public function build(RequestInterface $request)
     {
@@ -132,7 +133,7 @@ class IndexBuilder implements IndexBuilderInterface
                 ),
                 []
             );
-            $select->where('stock_index.stock_status = ?', Stock::DEFAULT_STOCK_ID);
+            $select->where('stock_index.stock_status = ?', Stock::STOCK_IN_STOCK);
         }
 
         return $select;
diff --git a/app/code/Magento/CatalogSearch/Model/Search/TableMapper.php b/app/code/Magento/CatalogSearch/Model/Search/TableMapper.php
index ca7298e1beaac560ee66427f2b9d57db7ce21508..ac726192856a5fa555eae6757cd83b16930565ee 100644
--- a/app/code/Magento/CatalogSearch/Model/Search/TableMapper.php
+++ b/app/code/Magento/CatalogSearch/Model/Search/TableMapper.php
@@ -6,10 +6,11 @@
 
 namespace Magento\CatalogSearch\Model\Search;
 
-use Magento\Catalog\Model\Product;
 use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+use Magento\CatalogSearch\Model\Search\FilterMapper\FilterStrategyInterface;
 use Magento\Eav\Model\Config as EavConfig;
-use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Framework\App\Config\ScopeConfigInterface;
 use Magento\Framework\App\ObjectManager;
 use Magento\Framework\App\ResourceConnection as AppResource;
 use Magento\Framework\DB\Select;
@@ -21,12 +22,15 @@ use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
 /**
+ * Responsibility of the TableMapper is to collect all filters from the search query
+ * and pass them one by one for processing in the FilterContext,
+ * which will apply them to the Select
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class TableMapper
 {
     /**
-     * @var Resource
+     * @var AppResource
      */
     private $resource;
 
@@ -40,22 +44,59 @@ class TableMapper
      */
     private $eavConfig;
 
+    /**
+     * @var ScopeConfigInterface
+     */
+    private $scopeConfig;
+
+    /**
+     * @var FilterStrategyInterface
+     */
+    private $filterStrategy;
+
+    /**
+     * @var AliasResolver
+     */
+    private $aliasResolver;
+
     /**
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @param AppResource $resource
      * @param StoreManagerInterface $storeManager
      * @param CollectionFactory $attributeCollectionFactory
      * @param EavConfig $eavConfig
+     * @param ScopeConfigInterface $scopeConfig
+     * @param FilterStrategyInterface $filterStrategy
+     * @param AliasResolver $aliasResolver
      */
     public function __construct(
         AppResource $resource,
         StoreManagerInterface $storeManager,
         CollectionFactory $attributeCollectionFactory,
-        EavConfig $eavConfig = null
+        EavConfig $eavConfig = null,
+        ScopeConfigInterface $scopeConfig = null,
+        FilterStrategyInterface $filterStrategy = null,
+        AliasResolver $aliasResolver = null
     ) {
         $this->resource = $resource;
         $this->storeManager = $storeManager;
-        $this->eavConfig = $eavConfig !== null ? $eavConfig : ObjectManager::getInstance()->get(EavConfig::class);
+
+        if (null === $eavConfig) {
+            $eavConfig = ObjectManager::getInstance()->get(EavConfig::class);
+        }
+        if (null === $scopeConfig) {
+            $scopeConfig = ObjectManager::getInstance()->get(ScopeConfigInterface::class);
+        }
+        if (null === $filterStrategy) {
+            $filterStrategy = ObjectManager::getInstance()->get(FilterStrategyInterface::class);
+        }
+        if (null === $aliasResolver) {
+            $aliasResolver = ObjectManager::getInstance()->get(AliasResolver::class);
+        }
+        $this->eavConfig = $eavConfig;
+        $this->scopeConfig = $scopeConfig;
+        $this->filterStrategy = $filterStrategy;
+        $this->aliasResolver = $aliasResolver;
     }
 
     /**
@@ -66,111 +107,53 @@ class TableMapper
      */
     public function addTables(Select $select, RequestInterface $request)
     {
-        $mappedTables = [];
-        $filters = $this->getFilters($request->getQuery());
+        $appliedFilters = [];
+        $filters = $this->getFiltersFromQuery($request->getQuery());
         foreach ($filters as $filter) {
-            list($alias, $table, $mapOn, $mappedFields, $joinType) = $this->getMappingData($filter);
-            if (!array_key_exists($alias, $mappedTables)) {
-                switch ($joinType) {
-                    case \Magento\Framework\DB\Select::INNER_JOIN:
-                        $select->joinInner(
-                            [$alias => $table],
-                            $mapOn,
-                            $mappedFields
-                        );
-                        break;
-                    case \Magento\Framework\DB\Select::LEFT_JOIN:
-                        $select->joinLeft(
-                            [$alias => $table],
-                            $mapOn,
-                            $mappedFields
-                        );
-                        break;
-                    default:
-                        throw new \LogicException(__('Unsupported join type: %1', $joinType));
+            $alias = $this->aliasResolver->getAlias($filter);
+            if (!array_key_exists($alias, $appliedFilters)) {
+                $isApplied = $this->filterStrategy->apply($filter, $select);
+                if ($isApplied) {
+                    $appliedFilters[$alias] = true;
                 }
-                $mappedTables[$alias] = $table;
             }
         }
         return $select;
     }
 
     /**
+     * This method is deprecated.
+     * Please use \Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver::getAlias() instead.
+     *
+     * @deprecated
+     * @see AliasResolver::getAlias()
+     *
      * @param FilterInterface $filter
      * @return string
      */
     public function getMappingAlias(FilterInterface $filter)
     {
-        list($alias) = $this->getMappingData($filter);
-        return $alias;
-    }
-
-    /**
-     * Returns mapping data for field in format: [
-     *  'table_alias',
-     *  'table',
-     *  'join_condition',
-     *  ['fields'],
-     *  'joinType'
-     * ]
-     * @param FilterInterface $filter
-     * @return array
-     */
-    private function getMappingData(FilterInterface $filter)
-    {
-        $alias = null;
-        $table = null;
-        $mapOn = null;
-        $mappedFields = null;
-        $field = $filter->getField();
-        $joinType = \Magento\Framework\DB\Select::INNER_JOIN;
-        $fieldToTableMap = $this->getFieldToTableMap($field);
-        if ($fieldToTableMap) {
-            list($alias, $table, $mapOn, $mappedFields) = $fieldToTableMap;
-            $table = $this->resource->getTableName($table);
-        } elseif ($attribute = $this->getAttributeByCode($field)) {
-            if ($filter->getType() === FilterInterface::TYPE_TERM
-                && in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true)
-            ) {
-                $joinType = \Magento\Framework\DB\Select::LEFT_JOIN;
-                $table = $this->resource->getTableName('catalog_product_index_eav');
-                $alias = $field . RequestGenerator::FILTER_SUFFIX;
-                $mapOn = sprintf(
-                    'search_index.entity_id = %1$s.entity_id AND %1$s.attribute_id = %2$d AND %1$s.store_id = %3$d',
-                    $alias,
-                    $attribute->getId(),
-                    $this->getStoreId()
-                );
-                $mappedFields = [];
-            } elseif ($attribute->getBackendType() === AbstractAttribute::TYPE_STATIC) {
-                $table = $attribute->getBackendTable();
-                $alias = $field . RequestGenerator::FILTER_SUFFIX;
-                $mapOn = 'search_index.entity_id = ' . $alias . '.entity_id';
-                $mappedFields = null;
-            }
-        }
-
-        return [$alias, $table, $mapOn, $mappedFields, $joinType];
+        return $this->aliasResolver->getAlias($filter);
     }
 
     /**
      * @param RequestQueryInterface $query
      * @return FilterInterface[]
      */
-    private function getFilters($query)
+    private function getFiltersFromQuery(RequestQueryInterface $query)
     {
         $filters = [];
         switch ($query->getType()) {
             case RequestQueryInterface::TYPE_BOOL:
                 /** @var \Magento\Framework\Search\Request\Query\BoolExpression $query */
                 foreach ($query->getMust() as $subQuery) {
-                    $filters = array_merge($filters, $this->getFilters($subQuery));
+                    $filters = array_merge($filters, $this->getFiltersFromQuery($subQuery));
                 }
                 foreach ($query->getShould() as $subQuery) {
-                    $filters = array_merge($filters, $this->getFilters($subQuery));
+                    $filters = array_merge($filters, $this->getFiltersFromQuery($subQuery));
                 }
                 foreach ($query->getMustNot() as $subQuery) {
-                    $filters = array_merge($filters, $this->getFilters($subQuery));
+                    $filters = array_merge($filters, $this->getFiltersFromQuery($subQuery));
                 }
                 break;
             case RequestQueryInterface::TYPE_FILTER:
@@ -219,57 +202,4 @@ class TableMapper
         }
         return $filters;
     }
-
-    /**
-     * @return int
-     */
-    private function getWebsiteId()
-    {
-        return $this->storeManager->getWebsite()->getId();
-    }
-
-    /**
-     * @return int
-     */
-    private function getStoreId()
-    {
-        return $this->storeManager->getStore()->getId();
-    }
-
-    /**
-     * @param string $field
-     * @return array|null
-     */
-    private function getFieldToTableMap($field)
-    {
-        $fieldToTableMap = [
-            'price' => [
-                'price_index',
-                'catalog_product_index_price',
-                $this->resource->getConnection()->quoteInto(
-                    'search_index.entity_id = price_index.entity_id AND price_index.website_id = ?',
-                    $this->getWebsiteId()
-                ),
-                []
-            ],
-            'category_ids' => [
-                'category_ids_index',
-                'catalog_category_product_index',
-                'search_index.entity_id = category_ids_index.product_id',
-                []
-            ]
-        ];
-        return array_key_exists($field, $fieldToTableMap) ? $fieldToTableMap[$field] : null;
-    }
-
-    /**
-     * @param string $field
-     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
-     * @throws \Magento\Framework\Exception\LocalizedException
-     */
-    private function getAttributeByCode($field)
-    {
-        $attribute = $this->eavConfig->getAttribute(Product::ENTITY, $field);
-        return $attribute;
-    }
 }
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/AliasResolverTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/AliasResolverTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab01d2553a3edcebde8a564a8ca8b8bb8cf2c7dd
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/AliasResolverTest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Unit\Model\Adapter\Mysql\Filter;
+
+use Magento\CatalogSearch\Model\Search\RequestGenerator;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+class AliasResolverTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver
+     */
+    private $aliasResolver;
+
+    /**
+     * @inheritDoc
+     */
+    protected function setUp()
+    {
+        $objectManagerHelper = new ObjectManagerHelper($this);
+        $this->aliasResolver = $objectManagerHelper->getObject(
+            \Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver::class,
+            []
+        );
+    }
+
+    /**
+     * @param string $field
+     * @param string $expectedAlias
+     * @dataProvider aliasDataProvider
+     */
+    public function testGetFilterAlias($field, $expectedAlias)
+    {
+        $filter = $this->getMockBuilder(\Magento\Framework\Search\Request\Filter\Term::class)
+            ->setMethods(['getField'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $filter->expects($this->once())
+            ->method('getField')
+            ->willReturn($field);
+        $this->assertSame($expectedAlias, $this->aliasResolver->getAlias($filter));
+    }
+
+    /**
+     * @return array
+     */
+    public function aliasDataProvider()
+    {
+        return [
+            'general' => [
+                'field' => 'general',
+                'alias' => 'general' . RequestGenerator::FILTER_SUFFIX,
+            ],
+            'price' => [
+                'field' => 'price',
+                'alias' => 'price_index',
+            ],
+            'category_ids' => [
+                'field' => 'category_ids',
+                'alias' => 'category_ids_index',
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php
index 0949bf6469be92611fbefa4c45962d8255570892..2cd6935586bd816bcc8c1e444b242c3b3f7a1472 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php
@@ -6,6 +6,7 @@
 
 namespace Magento\CatalogSearch\Test\Unit\Model\Adapter\Mysql\Filter;
 
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
 use Magento\Framework\DB\Select;
 use Magento\Framework\EntityManager\EntityMetadata;
 use Magento\Framework\Search\Request\FilterInterface;
@@ -18,9 +19,9 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject;
 class PreprocessorTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\CatalogSearch\Model\Search\TableMapper|\PHPUnit_Framework_MockObject_MockObject
+     * @var AliasResolver|\PHPUnit_Framework_MockObject_MockObject
      */
-    private $tableMapper;
+    private $aliasResolver;
 
     /**
      * @var \Magento\Framework\DB\Adapter\AdapterInterface|MockObject
@@ -141,7 +142,7 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase
                 )
             );
 
-        $this->tableMapper = $this->getMockBuilder(\Magento\CatalogSearch\Model\Search\TableMapper::class)
+        $this->aliasResolver = $this->getMockBuilder(AliasResolver::class)
             ->disableOriginalConstructor()
             ->getMock();
         $this->metadataPoolMock = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class)
@@ -164,7 +165,7 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase
                 'resource' => $resource,
                 'attributePrefix' => 'attr_',
                 'metadataPool' => $this->metadataPoolMock,
-                'tableMapper' => $this->tableMapper,
+                'aliasResolver' => $this->aliasResolver,
             ]
         );
     }
@@ -234,7 +235,7 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase
 
         $this->attribute->method('getAttributeCode')
             ->willReturn('static_attribute');
-        $this->tableMapper->expects($this->once())->method('getMappingAlias')
+        $this->aliasResolver->expects($this->once())->method('getAlias')
             ->willReturn('attr_table_alias');
         $this->filter->expects($this->exactly(3))
             ->method('getField')
@@ -272,7 +273,7 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase
             ->method('getFrontendInput')
             ->willReturn($frontendInput);
 
-        $this->tableMapper->expects($this->once())->method('getMappingAlias')
+        $this->aliasResolver->expects($this->once())->method('getAlias')
             ->willReturn('termAttrAlias');
 
         $this->filter->expects($this->exactly(3))
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/FilterMapper/FilterContextTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/FilterMapper/FilterContextTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9f133b763889bafb4843f7f9f868a3995a842eed
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/FilterMapper/FilterContextTest.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Unit\Model\Search\FilterMapper;
+
+use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
+use Magento\CatalogSearch\Model\Search\FilterMapper\ExclusionStrategy;
+use Magento\CatalogSearch\Model\Search\FilterMapper\FilterContext;
+use Magento\CatalogSearch\Model\Search\FilterMapper\StaticAttributeStrategy;
+use Magento\CatalogSearch\Model\Search\FilterMapper\TermDropdownStrategy;
+use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Framework\Search\Request\FilterInterface;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class FilterContextTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var FilterContext|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $filterContext;
+
+    /**
+     * @var AliasResolver|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $aliasResolver;
+
+    /**
+     * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $eavConfig;
+
+    /**
+     * @var ExclusionStrategy|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $exclusionStrategy;
+
+    /**
+     * @var TermDropdownStrategy|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $termDropdownStrategy;
+
+    /**
+     * @var StaticAttributeStrategy|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $staticAttributeStrategy;
+
+    /**
+     * @var \Magento\Framework\DB\Select
+     */
+    private $select;
+
+    /**
+     * @inheritDoc
+     */
+    protected function setUp()
+    {
+        $this->eavConfig = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getAttribute'])
+            ->getMock();
+        $this->aliasResolver = $this->getMockBuilder(
+            AliasResolver::class
+        )
+            ->disableOriginalConstructor()
+            ->setMethods(['getAlias'])
+            ->getMock();
+        $this->exclusionStrategy = $this->getMockBuilder(ExclusionStrategy::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['apply'])
+            ->getMock();
+        $this->termDropdownStrategy = $this->getMockBuilder(TermDropdownStrategy::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['apply'])
+            ->getMock();
+        $this->staticAttributeStrategy = $this->getMockBuilder(StaticAttributeStrategy::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['apply'])
+            ->getMock();
+        $this->select = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
+            ->disableOriginalConstructor()
+            ->setMethods([])
+            ->getMock();
+        $objectManager = new ObjectManager($this);
+        $this->filterContext = $objectManager->getObject(
+            FilterContext::class,
+            [
+                'eavConfig' => $this->eavConfig,
+                'aliasResolver' => $this->aliasResolver,
+                'exclusionStrategy' => $this->exclusionStrategy,
+                'termDropdownStrategy' => $this->termDropdownStrategy,
+                'staticAttributeStrategy' => $this->staticAttributeStrategy,
+            ]
+        );
+    }
+
+    public function testApplyOnExclusionFilter()
+    {
+        $filter = $this->createFilterMock();
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(true);
+        $this->eavConfig->expects($this->never())->method('getAttribute');
+        $this->assertTrue($this->filterContext->apply($filter, $this->select));
+    }
+
+    public function testApplyFilterWithoutAttribute()
+    {
+        $filter = $this->createFilterMock('some_field');
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(false);
+        $this->eavConfig->expects($this->once())
+            ->method('getAttribute')
+            ->with(\Magento\Catalog\Model\Product::ENTITY, 'some_field')
+            ->willReturn(null);
+        $this->assertFalse($this->filterContext->apply($filter, $this->select));
+    }
+
+    public function testApplyOnTermFilterBySelect()
+    {
+        $filter = $this->createFilterMock('select_field', FilterInterface::TYPE_TERM);
+        $attribute = $this->createAttributeMock('select');
+        $this->eavConfig->expects($this->once())
+            ->method('getAttribute')
+            ->with(\Magento\Catalog\Model\Product::ENTITY, 'select_field')
+            ->willReturn($attribute);
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(false);
+        $this->termDropdownStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(true);
+        $this->assertTrue($this->filterContext->apply($filter, $this->select));
+    }
+
+    public function testApplyOnTermFilterByMultiSelect()
+    {
+        $filter = $this->createFilterMock('multiselect_field', FilterInterface::TYPE_TERM);
+        $attribute = $this->createAttributeMock('multiselect');
+        $this->eavConfig->expects($this->once())
+            ->method('getAttribute')
+            ->with(\Magento\Catalog\Model\Product::ENTITY, 'multiselect_field')
+            ->willReturn($attribute);
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(false);
+        $this->termDropdownStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(true);
+        $this->assertTrue($this->filterContext->apply($filter, $this->select));
+    }
+
+    public function testApplyOnTermFilterByStaticAttribute()
+    {
+        $filter = $this->createFilterMock('multiselect_field', FilterInterface::TYPE_TERM);
+        $attribute = $this->createAttributeMock('text', AbstractAttribute::TYPE_STATIC);
+        $this->eavConfig->expects($this->once())
+            ->method('getAttribute')
+            ->with(\Magento\Catalog\Model\Product::ENTITY, 'multiselect_field')
+            ->willReturn($attribute);
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(false);
+        $this->staticAttributeStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(true);
+        $this->assertTrue($this->filterContext->apply($filter, $this->select));
+    }
+
+    public function testApplyOnTermFilterByUnknownAttributeType()
+    {
+        $filter = $this->createFilterMock('multiselect_field', FilterInterface::TYPE_TERM);
+        $attribute = $this->createAttributeMock('text', 'text');
+        $this->eavConfig->expects($this->once())
+            ->method('getAttribute')
+            ->with(\Magento\Catalog\Model\Product::ENTITY, 'multiselect_field')
+            ->willReturn($attribute);
+        $this->exclusionStrategy->expects($this->once())
+            ->method('apply')
+            ->with($filter, $this->select)
+            ->willReturn(false);
+        $this->assertFalse($this->filterContext->apply($filter, $this->select));
+    }
+
+    /**
+     * @param string $field
+     * @param string $type
+     * @return FilterInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private function createFilterMock($field = null, $type = null)
+    {
+        $filter = $this->getMockBuilder(FilterInterface::class)
+            ->setMethods(['getField', 'getType'])
+            ->getMockForAbstractClass();
+        $filter->expects($this->any())
+            ->method('getField')
+            ->willReturn($field);
+        $filter->expects($this->any())
+            ->method('getType')
+            ->willReturn($type);
+
+        return $filter;
+    }
+
+    /**
+     * @param string|null $frontendInput
+     * @param string|null $backendType
+     * @return Attribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private function createAttributeMock($frontendInput = null, $backendType = null)
+    {
+        $attribute = $this->getMockBuilder(Attribute::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getFrontendInput', 'getBackendType'])
+            ->getMock();
+        $attribute->expects($this->any())
+            ->method('getFrontendInput')
+            ->willReturn($frontendInput);
+        $attribute->expects($this->any())
+            ->method('getBackendType')
+            ->willReturn($backendType);
+        return $attribute;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/TableMapperTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/TableMapperTest.php
index dd9a556146ab3e40e4e1182f44c959c8260d9c8d..dad4ad8095f5af27fa3ce7cd48b1803c706d80a6 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/TableMapperTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/TableMapperTest.php
@@ -6,6 +6,9 @@
 
 namespace Magento\CatalogSearch\Test\Unit\Model\Search;
 
+use Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection;
+use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
+use Magento\CatalogSearch\Model\Adapter\Mysql\Filter\AliasResolver;
 use Magento\Framework\Search\Request\FilterInterface;
 use Magento\Framework\Search\Request\QueryInterface;
 use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
@@ -16,8 +19,10 @@ use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
  */
 class TableMapperTest extends \PHPUnit_Framework_TestCase
 {
-    const WEBSITE_ID = 4512;
-    const STORE_ID = 2514;
+    /**
+     * @var AliasResolver|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $aliasResolver;
 
     /**
      * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
@@ -25,7 +30,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
     private $eavConfig;
 
     /**
-     * @var \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection|\PHPUnit_Framework_MockObject_MockObject
+     * @var Collection|\PHPUnit_Framework_MockObject_MockObject
      */
     private $attributeCollection;
 
@@ -59,11 +64,6 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
      */
     private $resource;
 
-    /**
-     * @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $store;
-
     /**
      * @var \Magento\CatalogSearch\Model\Search\TableMapper
      */
@@ -76,65 +76,49 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->connection->expects($this->any())
-            ->method('quoteInto')
-            ->willReturnCallback(
-                function ($query, $expression) {
-                    return str_replace('?', $expression, $query);
-                }
-            );
+        $this->connection->expects($this->never())->method('quoteInto');
 
         $this->resource = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->resource->method('getTableName')
-            ->willReturnCallback(
-                function ($table) {
-                    return 'prefix_' . $table;
-                }
-            );
-        $this->resource->expects($this->any())
-            ->method('getConnection')
-            ->willReturn($this->connection);
+        $this->resource->expects($this->never())->method('getTableName');
+        $this->resource->expects($this->never())->method('getConnection');
 
         $this->website = $this->getMockBuilder(\Magento\Store\Api\Data\WebsiteInterface::class)
             ->disableOriginalConstructor()
             ->getMockForAbstractClass();
-        $this->website->expects($this->any())
-            ->method('getId')
-            ->willReturn(self::WEBSITE_ID);
-        $this->store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
-            ->disableOriginalConstructor()
-            ->getMockForAbstractClass();
-        $this->store->expects($this->any())
-            ->method('getId')
-            ->willReturn(self::STORE_ID);
+        $this->website->expects($this->never())->method('getId');
+
         $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->storeManager->expects($this->any())
-            ->method('getWebsite')
-            ->willReturn($this->website);
-        $this->storeManager->expects($this->any())
-            ->method('getStore')
-            ->willReturn($this->store);
-        $this->attributeCollection = $this->getMockBuilder(
-            \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection::class
-        )
+        $this->storeManager->expects($this->never())->method('getWebsite');
+        $this->storeManager->expects($this->never())->method('getStore');
+
+        $this->attributeCollection = $this->getMockBuilder(Collection::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $attributeCollectionFactory = $this->getMockBuilder(
-            \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory::class
-        )
+        $attributeCollectionFactory = $this->getMockBuilder(CollectionFactory::class)
             ->setMethods(['create'])
             ->disableOriginalConstructor()
             ->getMock();
         $attributeCollectionFactory->expects($this->never())
             ->method('create');
+
         $this->eavConfig = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
             ->setMethods(['getAttribute'])
             ->disableOriginalConstructor()
             ->getMock();
+
+        $this->aliasResolver = $this->getMockBuilder(AliasResolver::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->aliasResolver->expects($this->any())
+            ->method('getAlias')
+            ->willReturnCallback(function (FilterInterface $filter) {
+                return $filter->getField() . '_alias';
+            });
+
         $this->target = $objectManager->getObject(
             \Magento\CatalogSearch\Model\Search\TableMapper::class,
             [
@@ -142,6 +126,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
                 'storeManager' => $this->storeManager,
                 'attributeCollectionFactory' => $attributeCollectionFactory,
                 'eavConfig' => $this->eavConfig,
+                'aliasResolver' => $this->aliasResolver,
             ]
         );
 
@@ -160,14 +145,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->once())
-            ->method('joinInner')
-            ->with(
-                ['price_index' => 'prefix_catalog_product_index_price'],
-                'search_index.entity_id = price_index.entity_id AND price_index.website_id = ' . self::WEBSITE_ID,
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
@@ -176,18 +154,10 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
     {
         $priceFilter = $this->createRangeFilter('static');
         $query = $this->createFilterQuery($priceFilter);
-        $this->createAttributeMock('static', 'static', 'backend_table', 0, 'select');
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->once())
-            ->method('joinInner')
-            ->with(
-                ['static_filter' => 'backend_table'],
-                'search_index.entity_id = static_filter.entity_id',
-                null
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
@@ -199,46 +169,25 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->once())
-            ->method('joinInner')
-            ->with(
-                ['category_ids_index' => 'prefix_catalog_category_product_index'],
-                'search_index.entity_id = category_ids_index.product_id',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
 
     public function testAddTermFilter()
     {
-        $this->createAttributeMock('color', null, null, 132, 'select', 0);
         $categoryIdsFilter = $this->createTermFilter('color');
         $query = $this->createFilterQuery($categoryIdsFilter);
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->once())
-            ->method('joinLeft')
-            ->with(
-                ['color_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = color_filter.entity_id'
-                . ' AND color_filter.attribute_id = 132'
-                . ' AND color_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
 
     public function testAddBoolQueryWithTermFiltersInside()
     {
-        $this->createAttributeMock('must1', null, null, 101, 'select', 0);
-        $this->createAttributeMock('should1', null, null, 102, 'select', 1);
-        $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2);
-
         $query = $this->createBoolQuery(
             [
                 $this->createFilterQuery($this->createTermFilter('must1')),
@@ -253,45 +202,13 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->at(0))
-            ->method('joinLeft')
-            ->with(
-                ['must1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = must1_filter.entity_id'
-                . ' AND must1_filter.attribute_id = 101'
-                . ' AND must1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(1))
-            ->method('joinLeft')
-            ->with(
-                ['should1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = should1_filter.entity_id'
-                . ' AND should1_filter.attribute_id = 102'
-                . ' AND should1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(2))
-            ->method('joinLeft')
-            ->with(
-                ['mustNot1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = mustNot1_filter.entity_id'
-                . ' AND mustNot1_filter.attribute_id = 103'
-                . ' AND mustNot1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
 
     public function testAddBoolQueryWithTermAndPriceFiltersInside()
     {
-        $this->createAttributeMock('must1', null, null, 101, 'select', 0);
-        $this->createAttributeMock('should1', null, null, 102, 'select', 1);
-        $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2);
         $query = $this->createBoolQuery(
             [
                 $this->createFilterQuery($this->createTermFilter('must1')),
@@ -307,53 +224,13 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->at(0))
-            ->method('joinLeft')
-            ->with(
-                ['must1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = must1_filter.entity_id'
-                . ' AND must1_filter.attribute_id = 101'
-                . ' AND must1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(1))
-            ->method('joinInner')
-            ->with(
-                ['price_index' => 'prefix_catalog_product_index_price'],
-                'search_index.entity_id = price_index.entity_id AND price_index.website_id = ' . self::WEBSITE_ID,
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(2))
-            ->method('joinLeft')
-            ->with(
-                ['should1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = should1_filter.entity_id'
-                . ' AND should1_filter.attribute_id = 102'
-                . ' AND should1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(3))
-            ->method('joinLeft')
-            ->with(
-                ['mustNot1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = mustNot1_filter.entity_id'
-                . ' AND mustNot1_filter.attribute_id = 103'
-                . ' AND mustNot1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
 
     public function testAddBoolFilterWithTermFiltersInside()
     {
-        $this->createAttributeMock('must1', null, null, 101, 'select', 0);
-        $this->createAttributeMock('should1', null, null, 102, 'select', 1);
-        $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2);
         $query = $this->createFilterQuery(
             $this->createBoolFilter(
                 [
@@ -370,45 +247,13 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->at(0))
-            ->method('joinLeft')
-            ->with(
-                ['must1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = must1_filter.entity_id'
-                . ' AND must1_filter.attribute_id = 101'
-                . ' AND must1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(1))
-            ->method('joinLeft')
-            ->with(
-                ['should1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = should1_filter.entity_id'
-                . ' AND should1_filter.attribute_id = 102'
-                . ' AND should1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(2))
-            ->method('joinLeft')
-            ->with(
-                ['mustNot1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = mustNot1_filter.entity_id'
-                . ' AND mustNot1_filter.attribute_id = 103'
-                . ' AND mustNot1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
 
     public function testAddBoolFilterWithBoolFiltersInside()
     {
-        $this->createAttributeMock('must1', null, null, 101, 'select', 0);
-        $this->createAttributeMock('should1', null, null, 102, 'select', 1);
-        $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2);
         $query = $this->createFilterQuery(
             $this->createBoolFilter(
                 [
@@ -425,36 +270,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
         $this->request->expects($this->once())
             ->method('getQuery')
             ->willReturn($query);
-        $this->select->expects($this->at(0))
-            ->method('joinLeft')
-            ->with(
-                ['must1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = must1_filter.entity_id'
-                . ' AND must1_filter.attribute_id = 101'
-                . ' AND must1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(1))
-            ->method('joinLeft')
-            ->with(
-                ['should1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = should1_filter.entity_id'
-                . ' AND should1_filter.attribute_id = 102'
-                . ' AND should1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
-        $this->select->expects($this->at(2))
-            ->method('joinLeft')
-            ->with(
-                ['mustNot1_filter' => 'prefix_catalog_product_index_eav'],
-                'search_index.entity_id = mustNot1_filter.entity_id'
-                . ' AND mustNot1_filter.attribute_id = 103'
-                . ' AND mustNot1_filter.store_id = 2514',
-                []
-            )
-            ->willReturnSelf();
+
         $select = $this->target->addTables($this->select, $this->request);
         $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select');
     }
@@ -472,6 +288,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             ->willReturn(QueryInterface::TYPE_FILTER);
         $query->method('getReference')
             ->willReturn($filter);
+
         return $query;
     }
 
@@ -495,6 +312,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             ->willReturn($should);
         $query->method('getMustNot')
             ->willReturn($mustNot);
+
         return $query;
     }
 
@@ -518,6 +336,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             ->willReturn($should);
         $query->method('getMustNot')
             ->willReturn($mustNot);
+
         return $query;
     }
 
@@ -532,6 +351,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             FilterInterface::TYPE_RANGE,
             $field
         );
+
         return $filter;
     }
 
@@ -546,6 +366,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             FilterInterface::TYPE_TERM,
             $field
         );
+
         return $filter;
     }
 
@@ -564,40 +385,7 @@ class TableMapperTest extends \PHPUnit_Framework_TestCase
             ->willReturn($type);
         $filter->method('getField')
             ->willReturn($field);
-        return $filter;
-    }
 
-    /**
-     * @param string $code
-     * @param string $backendType
-     * @param string $backendTable
-     * @param int $attributeId
-     * @param string $frontendInput
-     * @param int $positionInCollection
-     */
-    private function createAttributeMock(
-        $code,
-        $backendType = null,
-        $backendTable = null,
-        $attributeId = 120,
-        $frontendInput = 'select',
-        $positionInCollection = 0
-    ) {
-        $attribute = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
-            ->setMethods(['getBackendType', 'getBackendTable', 'getId', 'getFrontendInput'])
-            ->disableOriginalConstructor()
-            ->getMock();
-        $attribute->method('getId')
-            ->willReturn($attributeId);
-        $attribute->method('getBackendType')
-            ->willReturn($backendType);
-        $attribute->method('getBackendTable')
-            ->willReturn($backendTable);
-        $attribute->method('getFrontendInput')
-            ->willReturn($frontendInput);
-        $this->eavConfig->expects($this->at($positionInCollection))
-            ->method('getAttribute')
-            ->with(\Magento\Catalog\Model\Product::ENTITY, $code)
-            ->willReturn($attribute);
+        return $filter;
     }
 }
diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json
index 49756420bd2308cd1f8326f474395b6209c7450c..313cc99881a318799c15488fa742151e26db18ec 100644
--- a/app/code/Magento/CatalogSearch/composer.json
+++ b/app/code/Magento/CatalogSearch/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-search",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-search": "100.2.*",
diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml
index f62b4e47767a25230c5c2ad8372f99acc6bda2eb..7e9451f9b83e7ada30455509b8fd686a0c251705 100644
--- a/app/code/Magento/CatalogSearch/etc/di.xml
+++ b/app/code/Magento/CatalogSearch/etc/di.xml
@@ -11,6 +11,7 @@
     <preference for="Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Filter\Preprocessor" />
     <preference for="Magento\Framework\Search\Dynamic\DataProviderInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Dynamic\DataProvider" />
     <preference for="Magento\Framework\Search\Adapter\OptionsInterface" type="Magento\CatalogSearch\Model\Adapter\Options" />
+    <preference for="Magento\CatalogSearch\Model\Search\FilterMapper\FilterStrategyInterface" type="Magento\CatalogSearch\Model\Search\FilterMapper\FilterContext"/>
     <type name="Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory">
         <arguments>
             <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\ResourceModel\EngineInterface::CONFIG_ENGINE_PATH</argument>
diff --git a/app/code/Magento/CatalogUrlRewrite/composer.json b/app/code/Magento/CatalogUrlRewrite/composer.json
index 8fd54cbc8ee8319f625cd6320954a0c821bf9a52..a5f66cd09dda49086434a4dc73b073fe7f0ee9c3 100644
--- a/app/code/Magento/CatalogUrlRewrite/composer.json
+++ b/app/code/Magento/CatalogUrlRewrite/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-url-rewrite",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-import-export": "100.2.*",
diff --git a/app/code/Magento/CatalogWidget/composer.json b/app/code/Magento/CatalogWidget/composer.json
index 330f46176286c70822a32762dccfed157a2ce358..198e54db32d888dfc32eafd33f5c6b3ca45da870 100644
--- a/app/code/Magento/CatalogWidget/composer.json
+++ b/app/code/Magento/CatalogWidget/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-catalog-widget",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-widget": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Checkout/Controller/Cart/Add.php b/app/code/Magento/Checkout/Controller/Cart/Add.php
index fddfa63b5983e5f508f5211c19f8980d56aafc34..bfbf0008bf5892067aaa7b0ba53ca1bbb7632339 100644
--- a/app/code/Magento/Checkout/Controller/Cart/Add.php
+++ b/app/code/Magento/Checkout/Controller/Cart/Add.php
@@ -84,6 +84,7 @@ class Add extends \Magento\Checkout\Controller\Cart
         }
 
         $params = $this->getRequest()->getParams();
+
         try {
             if (isset($params['qty'])) {
                 $filter = new \Zend_Filter_LocalizedToNormalized(
diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php
index 4ce23c9c7f7090980d48f4c3bb231d4214a7e893..236c716f572d91e4bd4b88366414480567ccabc0 100644
--- a/app/code/Magento/Checkout/Model/Cart.php
+++ b/app/code/Magento/Checkout/Model/Cart.php
@@ -91,6 +91,11 @@ class Cart extends DataObject implements CartInterface
      */
     protected $productRepository;
 
+    /**
+     * @var \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
+     */
+    private $requestInfoFilter;
+
     /**
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -315,6 +320,7 @@ class Cart extends DataObject implements CartInterface
      *
      * @param   \Magento\Framework\DataObject|int|array $requestInfo
      * @return  \Magento\Framework\DataObject
+     * @throws \Magento\Framework\Exception\LocalizedException
      */
     protected function _getProductRequest($requestInfo)
     {
@@ -322,11 +328,14 @@ class Cart extends DataObject implements CartInterface
             $request = $requestInfo;
         } elseif (is_numeric($requestInfo)) {
             $request = new \Magento\Framework\DataObject(['qty' => $requestInfo]);
-        } else {
+        } elseif (is_array($requestInfo)) {
             $request = new \Magento\Framework\DataObject($requestInfo);
+        } else {
+            throw new \Magento\Framework\Exception\LocalizedException(
+                __('We found an invalid request for adding product to quote.')
+            );
         }
-
-        !$request->hasFormKey() ?: $request->unsFormKey();
+        $this->getRequestInfoFilter()->filter($request);
 
         return $request;
     }
@@ -722,4 +731,19 @@ class Cart extends DataObject implements CartInterface
         $this->_checkoutSession->setLastAddedProductId($productId);
         return $result;
     }
+
+    /**
+     * Getter for RequestInfoFilter
+     *
+     * @deprecated
+     * @return \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
+     */
+    private function getRequestInfoFilter()
+    {
+        if ($this->requestInfoFilter === null) {
+            $this->requestInfoFilter = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\Checkout\Model\Cart\RequestInfoFilterInterface::class);
+        }
+        return $this->requestInfoFilter;
+    }
 }
diff --git a/app/code/Magento/Checkout/Model/Cart/RequestInfoFilter.php b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..10f3b81386b8febcee8f2b49ee4acd6242d1e5e8
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilter.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ *
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model\Cart;
+
+/**
+ * Class RequestInfoFilter used for filtering data from a request
+ */
+class RequestInfoFilter implements RequestInfoFilterInterface
+{
+    /**
+     * @var array $params
+     */
+    private $filterList;
+
+    /**
+     * @param array $filterList
+     */
+    public function __construct(
+        array $filterList = []
+    ) {
+        $this->filterList = $filterList;
+    }
+
+    /**
+     * Filters the data with values from filterList
+     *
+     * @param \Magento\Framework\DataObject $params
+     * @return $this
+     */
+    public function filter(\Magento\Framework\DataObject $params)
+    {
+        foreach ($this->filterList as $filterKey) {
+            /** @var string $filterKey */
+            if ($params->hasData($filterKey)) {
+                $params->unsetData($filterKey);
+            }
+        }
+        return $this;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterComposite.php b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterComposite.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ef24c0a5f28a198be28cbb4fc0ba212ebbd9097
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterComposite.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ *
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model\Cart;
+
+/**
+ * Class RequestInfoFilterComposite
+ */
+class RequestInfoFilterComposite implements RequestInfoFilterInterface
+{
+    /**
+     * @var RequestInfoFilter[] $params
+     */
+    private $filters = [];
+
+    /**
+     * @param RequestInfoFilter[] $filters
+     */
+    public function __construct(
+        $filters = []
+    ) {
+        $this->filters = $filters;
+    }
+
+    /**
+     * Loops through all leafs of the composite and calls filter method
+     *
+     * @param \Magento\Framework\DataObject $params
+     * @return $this
+     */
+    public function filter(\Magento\Framework\DataObject $params)
+    {
+        foreach ($this->filters as $filter) {
+            $filter->filter($params);
+        }
+        return $this;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterInterface.php b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bd268f6c896e149bf042ccdbaaa85e411ec6153
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/Cart/RequestInfoFilterInterface.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ *
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model\Cart;
+
+/**
+ * Interface RequestInfoFilterInterface used by composite and leafs to implement filtering
+ */
+interface RequestInfoFilterInterface
+{
+    /**
+     * Filters the data object by an array of parameters
+     *
+     * @param \Magento\Framework\DataObject $params
+     * @return RequestInfoFilterInterface
+     */
+    public function filter(\Magento\Framework\DataObject $params);
+}
diff --git a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php
index b07e90384c1647b51d59405022bb63a0b8e108d3..f2ad294d06cbe45d0b5d77ebe8658d546d27efd3 100644
--- a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php
+++ b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php
@@ -9,6 +9,9 @@ namespace Magento\Checkout\Model;
 use Magento\Quote\Api\CartRepositoryInterface;
 use Magento\Framework\Exception\CouldNotSaveException;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPaymentInformationManagementInterface
 {
 
@@ -42,6 +45,11 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa
      */
     protected $cartRepository;
 
+    /**
+     * @var \Psr\Log\LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param \Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement
      * @param \Magento\Quote\Api\GuestPaymentMethodManagementInterface $paymentMethodManagement
@@ -79,7 +87,13 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa
         $this->savePaymentInformation($cartId, $email, $paymentMethod, $billingAddress);
         try {
             $orderId = $this->cartManagement->placeOrder($cartId);
+        } catch (\Magento\Framework\Exception\LocalizedException $e) {
+            throw new CouldNotSaveException(
+                __($e->getMessage()),
+                $e
+            );
         } catch (\Exception $e) {
+            $this->getLogger()->critical($e);
             throw new CouldNotSaveException(
                 __('An error occurred on the server. Please try to place the order again.'),
                 $e
@@ -117,4 +131,18 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa
         $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
         return $this->paymentInformationManagement->getPaymentInformation($quoteIdMask->getQuoteId());
     }
+
+    /**
+     * Get logger instance
+     *
+     * @return \Psr\Log\LoggerInterface
+     * @deprecated
+     */
+    private function getLogger()
+    {
+        if (!$this->logger) {
+            $this->logger = \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class);
+        }
+        return $this->logger;
+    }
 }
diff --git a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
index 140917dcdfeff22eaa73b9a1dc928d5d83f6ccd5..79e76feb4366190cb1d81389e7c54ac4f97cca9e 100644
--- a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
+++ b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
@@ -7,6 +7,9 @@ namespace Magento\Checkout\Model;
 
 use Magento\Framework\Exception\CouldNotSaveException;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInformationManagementInterface
 {
     /**
@@ -34,6 +37,11 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor
      */
     protected $cartTotalsRepository;
 
+    /**
+     * @var \Psr\Log\LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement
      * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
@@ -67,7 +75,13 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor
         $this->savePaymentInformation($cartId, $paymentMethod, $billingAddress);
         try {
             $orderId = $this->cartManagement->placeOrder($cartId);
+        } catch (\Magento\Framework\Exception\LocalizedException $e) {
+            throw new CouldNotSaveException(
+                __($e->getMessage()),
+                $e
+            );
         } catch (\Exception $e) {
+            $this->getLogger()->critical($e);
             throw new CouldNotSaveException(
                 __('An error occurred on the server. Please try to place the order again.'),
                 $e
@@ -102,4 +116,18 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor
         $paymentDetails->setTotals($this->cartTotalsRepository->get($cartId));
         return $paymentDetails;
     }
+
+    /**
+     * Get logger instance
+     *
+     * @return \Psr\Log\LoggerInterface
+     * @deprecated
+     */
+    private function getLogger()
+    {
+        if (!$this->logger) {
+            $this->logger = \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class);
+        }
+        return $this->logger;
+    }
 }
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterCompositeTest.php b/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterCompositeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c758cf4661fdab253a58b04f70969dc845e89d1
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterCompositeTest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Test\Unit\Model\Cart;
+
+/**
+ * Class RequestInfoFilterTest
+ */
+class RequestInfoFilterCompositeTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Checkout\Model\Cart\RequestInfoFilterComposite
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * Setup the test
+     */
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $requestInfoFilterMock1  = $this->getMock(
+            \Magento\Checkout\Model\Cart\RequestInfoFilter::class,
+            ['filter'],
+            [],
+            '',
+            false
+        );
+        $requestInfoFilterMock2  = $this->getMock(
+            \Magento\Checkout\Model\Cart\RequestInfoFilter::class,
+            ['filter'],
+            [],
+            '',
+            false
+        );
+
+        $requestInfoFilterMock1->expects($this->atLeastOnce())
+            ->method('filter');
+        $requestInfoFilterMock2->expects($this->atLeastOnce())
+            ->method('filter');
+
+        $filterList = [ $requestInfoFilterMock1, $requestInfoFilterMock2];
+
+        $this->model = $this->objectManager->getObject(
+            \Magento\Checkout\Model\Cart\RequestInfoFilterComposite::class,
+            [
+                'filters' => $filterList,
+            ]
+        );
+    }
+
+    /**
+     * Test Filter method
+     */
+    public function testFilter()
+    {
+        /** @var \Magento\Framework\DataObject $params */
+        $params = $this->objectManager->getObject(
+            \Magento\Framework\DataObject::class,
+            ['data' => ['abc' => 1, 'efg' => 1, 'xyz' => 1]]
+        );
+        $result = $this->model->filter($params);
+        $this->assertEquals($this->model, $result);
+    }
+}
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterTest.php b/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd6ca330da1b2d7252b8911f1820d7bc217d3561
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Model/Cart/RequestInfoFilterTest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Test\Unit\Model\Cart;
+
+/**
+ * Class RequestInfoFilterTest
+ */
+class RequestInfoFilterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Checkout\Model\Cart\RequestInfoFilter
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * Setup the test
+     */
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->model = $this->objectManager->getObject(
+            \Magento\Checkout\Model\Cart\RequestInfoFilter::class,
+            [
+                'filterList' => ['efg', 'xyz'],
+            ]
+        );
+    }
+
+    /**
+     * Test Filter method
+     */
+    public function testFilter()
+    {
+        /** @var \Magento\Framework\DataObject $params */
+        $params = $this->objectManager->getObject(
+            \Magento\Framework\DataObject::class,
+            ['data' => ['abc' => 1, 'efg' => 1, 'xyz' => 1]]
+        );
+        $result = $this->model->filter($params);
+        $this->assertEquals($this->model, $result);
+        $this->assertEquals(['abc' => 1], $params->convertToArray());
+    }
+}
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/CartTest.php b/app/code/Magento/Checkout/Test/Unit/Model/CartTest.php
index 199e6692e68d1777c382c8125391cac88326a549..9984fe12d3792e95f0b29d0d2c71ff36b37a5897 100644
--- a/app/code/Magento/Checkout/Test/Unit/Model/CartTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Model/CartTest.php
@@ -29,7 +29,7 @@ class CartTest extends \PHPUnit_Framework_TestCase
      */
     protected $customerSessionMock;
 
-    /** @var \Magento\CatalogInventory\Api\StockItem|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\CatalogInventory\Api\Data\StockItemInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $stockItemMock;
 
     /**
@@ -57,16 +57,39 @@ class CartTest extends \PHPUnit_Framework_TestCase
      */
     protected $stockState;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productRepository;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $requestInfoFilterMock;
+
     protected function setUp()
     {
         $this->checkoutSessionMock = $this->getMock(\Magento\Checkout\Model\Session::class, [], [], '', false);
         $this->customerSessionMock = $this->getMock(\Magento\Customer\Model\Session::class, [], [], '', false);
         $this->scopeConfigMock = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
+        $this->quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false);
+        $this->eventManagerMock = $this->getMock(\Magento\Framework\Event\ManagerInterface::class);
+        $this->storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class);
+        $this->productRepository = $this->getMock(\Magento\Catalog\Api\ProductRepositoryInterface::class);
         $this->stockRegistry = $this->getMockBuilder(\Magento\CatalogInventory\Model\StockRegistry::class)
             ->disableOriginalConstructor()
             ->setMethods(['getStockItem', '__wakeup'])
             ->getMock();
-
         $this->stockItemMock = $this->getMock(
             \Magento\CatalogInventory\Model\Stock\Item::class,
             ['getMinSaleQty', '__wakeup'],
@@ -74,7 +97,6 @@ class CartTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-
         $this->stockState = $this->getMock(
             \Magento\CatalogInventory\Model\StockState::class,
             ['suggestQty', '__wakeup'],
@@ -82,12 +104,22 @@ class CartTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $this->storeMock =
+            $this->getMock(\Magento\Store\Model\Store::class, ['getWebsiteId', 'getId', '__wakeup'], [], '', false);
+        $this->requestInfoFilterMock = $this->getMock(\Magento\Checkout\Model\Cart\RequestInfoFilterInterface::class);
 
         $this->stockRegistry->expects($this->any())
             ->method('getStockItem')
             ->will($this->returnValue($this->stockItemMock));
-        $this->quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false);
-        $this->eventManagerMock = $this->getMock(\Magento\Framework\Event\ManagerInterface::class);
+        $this->storeMock->expects($this->any())
+            ->method('getWebsiteId')
+            ->will($this->returnValue(10));
+        $this->storeMock->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(10));
+        $this->storeManagerMock->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($this->storeMock));
 
         $this->objectManagerHelper = new ObjectManagerHelper($this);
         $this->cart = $this->objectManagerHelper->getObject(
@@ -98,9 +130,14 @@ class CartTest extends \PHPUnit_Framework_TestCase
                 'stockRegistry' => $this->stockRegistry,
                 'stockState' => $this->stockState,
                 'customerSession' => $this->customerSessionMock,
-                'eventManager' => $this->eventManagerMock
+                'eventManager' => $this->eventManagerMock,
+                'storeManager' => $this->storeManagerMock,
+                'productRepository' => $this->productRepository
             ]
         );
+
+        $this->objectManagerHelper
+            ->setBackwardCompatibleProperty($this->cart, 'requestInfoFilter', $this->requestInfoFilterMock);
     }
 
     public function testSuggestItemsQty()
@@ -169,10 +206,17 @@ class CartTest extends \PHPUnit_Framework_TestCase
      */
     public function prepareQuoteItemMock($itemId)
     {
-        $store = $this->getMock(\Magento\Store\Model\Store::class, ['getWebsiteId', '__wakeup'], [], '', false);
+        $store = $this->getMock(\Magento\Store\Model\Store::class, ['getId', '__wakeup'], [], '', false);
         $store->expects($this->any())
             ->method('getWebsiteId')
             ->will($this->returnValue(10));
+        $store->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(10));
+        $this->storeManagerMock->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($store));
+
         switch ($itemId) {
             case 2:
                 $product = $this->getMock(
@@ -255,4 +299,162 @@ class CartTest extends \PHPUnit_Framework_TestCase
             ['useQty' => false]
         ];
     }
+
+    /**
+     * Test successful scenarios for AddProduct
+     *
+     * @param int|\Magento\Catalog\Model\Product $productInfo
+     * @param \Magento\Framework\DataObject|int|array $requestInfo
+     * @dataProvider addProductDataProvider
+     */
+    public function testAddProduct($productInfo, $requestInfo)
+    {
+        $product = $this->getMock(
+            \Magento\Catalog\Model\Product::class,
+            ['getStore', 'getWebsiteIds', 'getProductUrl', 'getId', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $product->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(4));
+        $product->expects($this->once())
+            ->method('getStore')
+            ->will($this->returnValue($this->storeMock));
+        $product->expects($this->any())
+            ->method('getWebsiteIds')
+            ->will($this->returnValue([10]));
+        $product->expects($this->any())
+            ->method('getProductUrl')
+            ->will($this->returnValue('url'));
+        $this->productRepository->expects($this->any())
+            ->method('getById')
+            ->will($this->returnValue($product));
+        $this->quoteMock->expects($this->once())
+        ->method('addProduct')
+        ->will($this->returnValue(1));
+        $this->checkoutSessionMock->expects($this->once())
+            ->method('getQuote')
+            ->will($this->returnValue($this->quoteMock));
+
+        $this->eventManagerMock->expects($this->at(0))->method('dispatch')->with(
+            'checkout_cart_product_add_after',
+            ['quote_item' => 1, 'product' => $product]
+        );
+
+        if (!$productInfo) {
+            $productInfo = $product;
+        }
+        $result = $this->cart->addProduct($productInfo, $requestInfo);
+        $this->assertSame($this->cart, $result);
+    }
+
+    /**
+     * Test exception on adding product for AddProduct
+     *
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function testAddProductException()
+    {
+        $product = $this->getMock(
+            \Magento\Catalog\Model\Product::class,
+            ['getStore', 'getWebsiteIds', 'getProductUrl', 'getId', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $product->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(4));
+        $product->expects($this->once())
+            ->method('getStore')
+            ->will($this->returnValue($this->storeMock));
+        $product->expects($this->any())
+            ->method('getWebsiteIds')
+            ->will($this->returnValue([10]));
+        $product->expects($this->any())
+            ->method('getProductUrl')
+            ->will($this->returnValue('url'));
+        $this->productRepository->expects($this->any())
+            ->method('getById')
+            ->will($this->returnValue($product));
+        $this->quoteMock->expects($this->once())
+            ->method('addProduct')
+            ->will($this->returnValue('error'));
+        $this->checkoutSessionMock->expects($this->once())
+            ->method('getQuote')
+            ->will($this->returnValue($this->quoteMock));
+
+        $this->eventManagerMock->expects($this->never())->method('dispatch')->with(
+            'checkout_cart_product_add_after',
+            ['quote_item' => 1, 'product' => $product]
+        );
+        $this->setExpectedException(\Magento\Framework\Exception\LocalizedException::class);
+        $this->cart->addProduct(4, 4);
+    }
+
+    /**
+     * Test bad parameters on adding product for AddProduct
+     *
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function testAddProductExceptionBadParams()
+    {
+        $product = $this->getMock(
+            \Magento\Catalog\Model\Product::class,
+            ['getWebsiteIds', 'getId', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $product->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(4));
+        $product->expects($this->any())
+            ->method('getWebsiteIds')
+            ->will($this->returnValue([10]));
+        $this->productRepository->expects($this->any())
+            ->method('getById')
+            ->will($this->returnValue($product));
+
+        $this->eventManagerMock->expects($this->never())->method('dispatch')->with(
+            'checkout_cart_product_add_after',
+            ['quote_item' => 1, 'product' => $product]
+        );
+        $this->setExpectedException(\Magento\Framework\Exception\LocalizedException::class);
+        $this->cart->addProduct(4, 'bad');
+    }
+
+    /**
+     * Data provider for testAddProduct
+     *
+     * @return array
+     */
+    public function addProductDataProvider()
+    {
+        $obj = new ObjectManagerHelper($this) ;
+        $data = ['qty' => 5.5, 'sku' => 'prod'];
+
+        return [
+            'prod_int_info_int' => [4, 4],
+            'prod_int_info_array' => [ 4, $data],
+            'prod_int_info_object' => [
+                4,
+                $obj->getObject(
+                    \Magento\Framework\DataObject::class,
+                    ['data' => $data]
+                )
+            ],
+            'prod_obj_info_int' => [null, 4],
+            'prod_obj_info_array' => [ null, $data],
+            'prod_obj_info_object' => [
+                null,
+                $obj->getObject(
+                    \Magento\Framework\DataObject::class,
+                    ['data' => $data]
+                )
+            ]
+        ];
+    }
 }
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php
index 093bbf4a5accc66bdd5c00fa4f30660409e09f79..76cbafb48ebd47e4fd83d01ef1361ef29df2f3be 100644
--- a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php
@@ -42,6 +42,11 @@ class GuestPaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
      */
     protected $model;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $loggerMock;
+
     protected function setUp()
     {
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
@@ -61,6 +66,7 @@ class GuestPaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $this->loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class);
         $this->model = $objectManager->getObject(
             \Magento\Checkout\Model\GuestPaymentInformationManagement::class,
             [
@@ -71,6 +77,7 @@ class GuestPaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
                 'quoteIdMaskFactory' => $this->quoteIdMaskFactoryMock
             ]
         );
+        $objectManager->setBackwardCompatibleProperty($this->model, 'logger', $this->loggerMock);
     }
 
     public function testSavePaymentInformationAndPlaceOrder()
@@ -112,7 +119,7 @@ class GuestPaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
             ->method('assign')
             ->with($cartId, $billingAddressMock);
         $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock);
-        $exception = new CouldNotSaveException(__('DB exception'));
+        $exception = new \Exception(__('DB exception'));
         $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception);
 
         $this->model->savePaymentInformationAndPlaceOrder($cartId, $email, $paymentMock, $billingAddressMock);
@@ -161,4 +168,29 @@ class GuestPaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
         $billingAddressMock->expects($this->once())->method('setEmail')->with($email);
         $this->assertTrue($this->model->savePaymentInformation($cartId, $email, $paymentMock));
     }
+
+    /**
+     * @expectedExceptionMessage DB exception
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function testSavePaymentInformationAndPlaceOrderWithLocolizedException()
+    {
+        $cartId = 100;
+        $email = 'email@magento.com';
+        $paymentMock = $this->getMock(\Magento\Quote\Api\Data\PaymentInterface::class);
+        $billingAddressMock = $this->getMock(\Magento\Quote\Api\Data\AddressInterface::class);
+
+        $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf();
+
+        $this->billingAddressManagementMock->expects($this->once())
+            ->method('assign')
+            ->with($cartId, $billingAddressMock);
+        $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock);
+        $phrase = new \Magento\Framework\Phrase(__('DB exception'));
+        $exception = new \Magento\Framework\Exception\LocalizedException($phrase);
+        $this->loggerMock->expects($this->never())->method('critical');
+        $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception);
+
+        $this->model->savePaymentInformationAndPlaceOrder($cartId, $email, $paymentMock, $billingAddressMock);
+    }
 }
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php
index 496054b2c7b1e0a0b9e60c119a8c25d322832a26..8da67a1fcb71512dd218a2c62d51b7922bb36c25 100644
--- a/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php
@@ -29,6 +29,11 @@ class PaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
      */
     protected $model;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $loggerMock;
+
     protected function setUp()
     {
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
@@ -40,6 +45,8 @@ class PaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
         );
         $this->cartManagementMock = $this->getMock(\Magento\Quote\Api\CartManagementInterface::class);
 
+        $this->loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class);
+
         $this->model = $objectManager->getObject(
             \Magento\Checkout\Model\PaymentInformationManagement::class,
             [
@@ -48,6 +55,7 @@ class PaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
                 'cartManagement' => $this->cartManagementMock
             ]
         );
+        $objectManager->setBackwardCompatibleProperty($this->model, 'logger', $this->loggerMock);
     }
 
     public function testSavePaymentInformationAndPlaceOrder()
@@ -83,7 +91,8 @@ class PaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
             ->method('assign')
             ->with($cartId, $billingAddressMock);
         $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock);
-        $exception = new CouldNotSaveException(__('DB exception'));
+        $exception = new \Exception(__('DB exception'));
+        $this->loggerMock->expects($this->once())->method('critical');
         $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception);
 
         $this->model->savePaymentInformationAndPlaceOrder($cartId, $paymentMock, $billingAddressMock);
@@ -129,4 +138,26 @@ class PaymentInformationManagementTest extends \PHPUnit_Framework_TestCase
 
         $this->assertTrue($this->model->savePaymentInformation($cartId, $paymentMock));
     }
+
+    /**
+     * @expectedExceptionMessage DB exception
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function testSavePaymentInformationAndPlaceOrderWithLocolizedException()
+    {
+        $cartId = 100;
+        $paymentMock = $this->getMock(\Magento\Quote\Api\Data\PaymentInterface::class);
+        $billingAddressMock = $this->getMock(\Magento\Quote\Api\Data\AddressInterface::class);
+
+        $this->billingAddressManagementMock->expects($this->once())
+            ->method('assign')
+            ->with($cartId, $billingAddressMock);
+        $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock);
+        $phrase = new \Magento\Framework\Phrase(__('DB exception'));
+        $exception = new \Magento\Framework\Exception\LocalizedException($phrase);
+        $this->loggerMock->expects($this->never())->method('critical');
+        $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception);
+
+        $this->model->savePaymentInformationAndPlaceOrder($cartId, $paymentMock, $billingAddressMock);
+    }
 }
diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json
index 5545e409b65abb3fb381e593c4ec34298dba6b80..60919d9fa2ca949817641c43328ad3be88edc8be 100644
--- a/app/code/Magento/Checkout/composer.json
+++ b/app/code/Magento/Checkout/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-checkout",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-sales": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Checkout/etc/di.xml b/app/code/Magento/Checkout/etc/di.xml
index c55598fdff5e792dd7404967d12f9fcc5e78e828..a2243b33a04edc0af4dc71ed79b802eac68f4cc2 100644
--- a/app/code/Magento/Checkout/etc/di.xml
+++ b/app/code/Magento/Checkout/etc/di.xml
@@ -26,4 +26,20 @@
     <preference for="Magento\Checkout\Api\GuestTotalsInformationManagementInterface" type="Magento\Checkout\Model\GuestTotalsInformationManagement" />
     <preference for="Magento\Checkout\Api\TotalsInformationManagementInterface" type="Magento\Checkout\Model\TotalsInformationManagement" />
     <preference for="Magento\Checkout\Api\AgreementsValidatorInterface" type="Magento\Checkout\Model\AgreementsValidator" />
+    <preference for="Magento\Checkout\Model\Cart\RequestInfoFilterInterface"
+                type="Magento\Checkout\Model\Cart\RequestInfoFilterComposite"/>
+    <type name="Magento\Checkout\Model\Cart\RequestInfoFilter">
+        <arguments>
+            <argument name="filterList" xsi:type="array">
+                <item name="form_key" xsi:type="string">form_key</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Checkout\Model\Cart\RequestInfoFilterComposite">
+        <arguments>
+            <argument name="filters" xsi:type="array">
+                <item name="filter" xsi:type="object">Magento\Checkout\Model\Cart\RequestInfoFilter</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml
index bccf81bcb6ee81c97bd6bef98d3c5f08ec33b9cc..6fb9058c3b7681c8905a40a5eace5d88d8566b6f 100644
--- a/app/code/Magento/Checkout/etc/frontend/di.xml
+++ b/app/code/Magento/Checkout/etc/frontend/di.xml
@@ -72,4 +72,12 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Checkout\Model\Cart\RequestInfoFilter">
+        <arguments>
+            <argument name="filterList" xsi:type="array">
+                <item name="form_key" xsi:type="string">form_key</item>
+                <item name="custom_price" xsi:type="string">custom_price</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/full-screen-loader.js b/app/code/Magento/Checkout/view/frontend/web/js/model/full-screen-loader.js
index ca9d6493a16740f1a43555d84459df4403bd3c88..9005015d2460e12c5462551aecce97f1bd31c003 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/full-screen-loader.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/full-screen-loader.js
@@ -24,7 +24,7 @@ define([
             /**
              * Stop full page loader action
              *
-             * @param {Boolean} forceStop
+             * @param {Boolean} [forceStop]
              */
             stopLoader: function (forceStop) {
                 var $elem = $(containerId),
diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json
index afb706a39a25ec97915abfe0bc6bfcb99c95f6d4..56a2b567745c2dd81fa3ca691309c4a76fe05aed 100644
--- a/app/code/Magento/CheckoutAgreements/composer.json
+++ b/app/code/Magento/CheckoutAgreements/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-checkout-agreements",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-checkout": "100.2.*",
         "magento/module-quote": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/model/agreement-validator.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/model/agreement-validator.js
index 3d030a62eb425cdb0365331c8fac5325a5dbc91d..2fa3c2cddd3d5af870f02db0e189cae8456c51aa 100644
--- a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/model/agreement-validator.js
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/model/agreement-validator.js
@@ -12,9 +12,8 @@ define(
     function ($) {
         'use strict';
         var checkoutConfig = window.checkoutConfig,
-            agreementsConfig = checkoutConfig ? checkoutConfig.checkoutAgreements : {};
-
-        var agreementsInputPath = '.payment-method._active div.checkout-agreements input';
+            agreementsConfig = checkoutConfig ? checkoutConfig.checkoutAgreements : {},
+            agreementsInputPath = '.payment-method._active div.checkout-agreements input';
 
         return {
             /**
@@ -23,26 +22,11 @@ define(
              * @returns {boolean}
              */
             validate: function() {
-                if (!agreementsConfig.isEnabled) {
-                    return true;
-                }
-
-                if ($(agreementsInputPath).length == 0) {
+                if (!agreementsConfig.isEnabled || $(agreementsInputPath).length == 0) {
                     return true;
                 }
 
-                return $('#co-payment-form').validate({
-                    errorClass: 'mage-error',
-                    errorElement: 'div',
-                    meta: 'validate',
-                    errorPlacement: function (error, element) {
-                        var errorPlacement = element;
-                        if (element.is(':checkbox') || element.is(':radio')) {
-                            errorPlacement = element.siblings('label').last();
-                        }
-                        errorPlacement.after(error);
-                    }
-                }).element(agreementsInputPath);
+                return $.validator.validateSingleElement(agreementsInputPath, {errorElement: 'div'});
             }
         }
     }
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/checkout-agreements.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/checkout-agreements.html
index bb7d5de636ce5fd98b5f98943500910603d56267..7d8ef43084f3264c09bb65d2939f6660fa343f7f 100644
--- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/checkout-agreements.html
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/checkout-agreements.html
@@ -8,14 +8,13 @@
     <div class="checkout-agreements" data-bind="visible: isVisible">
         <!-- ko foreach: agreements -->
             <!-- ko if: ($parent.isAgreementRequired($data)) -->
-            <div class="checkout-agreement">
-                <input type="checkbox"
+            <div class="checkout-agreement required">
+                <input type="checkbox" class="required-entry"
                        data-bind="attr: {
                                     'id': 'agreement_' + agreementId,
                                     'name': 'agreement[' + agreementId + ']',
                                     'value': agreementId
-                                    }"
-                       data-validate="{required:true}" />
+                                    }"/>
                 <label data-bind="attr: {'for': 'agreement_' + agreementId}">
                     <button type="button"
                             class="action action-show"
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
index ec5a438247e5cddc205d2f49c8d49ea746943e34..1bd96eff4dceef562040df73978679cc236a00bb 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
@@ -41,6 +41,7 @@ class Collection extends AbstractCollection
     {
         $this->_init(\Magento\Cms\Model\Block::class, \Magento\Cms\Model\ResourceModel\Block::class);
         $this->_map['fields']['store'] = 'store_table.store_id';
+        $this->_map['fields']['block_id'] = 'main_table.block_id';
     }
 
     /**
diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e1de289e5ef0e004a34d70dd793c1715a8bf292
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Test\Unit\Ui\Component\Listing\Column;
+
+use Magento\Cms\Ui\Component\Listing\Column\BlockActions;
+use Magento\Framework\Escaper;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Framework\UrlInterface;
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+use Magento\Framework\View\Element\UiComponent\Processor;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
+/**
+ * BlockActionsTest contains unit tests for \Magento\Cms\Ui\Component\Listing\Column\BlockActions class
+ */
+class BlockActionsTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var BlockActions
+     */
+    private $blockActions;
+
+    /**
+     * @var Escaper|MockObject
+     */
+    private $escaper;
+
+    /**
+     * @var UrlInterface|MockObject
+     */
+    private $urlBuilder;
+
+    protected function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+
+        $context = $this->getMock(ContextInterface::class);
+
+        $processor = $this->getMockBuilder(Processor::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $context->expects(static::once())
+            ->method('getProcessor')
+            ->willReturn($processor);
+
+        $this->urlBuilder = $this->getMock(UrlInterface::class);
+
+        $this->escaper = $this->getMockBuilder(Escaper::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['escapeHtml'])
+            ->getMock();
+
+        $this->blockActions = $objectManager->getObject(BlockActions::class, [
+            'context' => $context,
+            'urlBuilder' => $this->urlBuilder
+        ]);
+
+        $objectManager->setBackwardCompatibleProperty($this->blockActions, 'escaper', $this->escaper);
+    }
+
+    /**
+     * @covers \Magento\Cms\Ui\Component\Listing\Column\BlockActions::prepareDataSource
+     */
+    public function testPrepareDataSource()
+    {
+        $blockId = 1;
+        $title = 'block title';
+        $items = [
+            'data' => [
+                'items' => [
+                    [
+                        'block_id' => $blockId,
+                        'title' => $title
+                    ]
+                ]
+            ]
+        ];
+        $name = 'item_name';
+        $expectedItems = [
+            [
+                'block_id' => $blockId,
+                'title' => $title,
+                $name => [
+                    'edit' => [
+                        'href' => 'test/url/edit',
+                        'label' => __('Edit'),
+                    ],
+                    'delete' => [
+                        'href' => 'test/url/delete',
+                        'label' => __('Delete'),
+                        'confirm' => [
+                            'title' => __('Delete %1', $title),
+                            'message' => __('Are you sure you wan\'t to delete a %1 record?', $title)
+                        ],
+                    ]
+                ],
+            ]
+        ];
+
+        $this->escaper->expects(static::once())
+            ->method('escapeHtml')
+            ->with($title)
+            ->willReturn($title);
+
+        $this->urlBuilder->expects(static::exactly(2))
+            ->method('getUrl')
+            ->willReturnMap(
+                [
+                    [
+                        BlockActions::URL_PATH_EDIT,
+                        [
+                            'block_id' => $blockId
+                        ],
+                        'test/url/edit',
+                    ],
+                    [
+                        BlockActions::URL_PATH_DELETE,
+                        [
+                            'block_id' => $blockId
+                        ],
+                        'test/url/delete',
+                    ],
+                ]
+            );
+
+        $this->blockActions->setData('name', $name);
+
+        $actual = $this->blockActions->prepareDataSource($items);
+        static::assertEquals($expectedItems, $actual['data']['items']);
+    }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php
index 4b6ce1ae2ff42d39bf53a9e57bd3b9f6aa639f89..731c08fbc64dd59a967b4d74ea52ba188336d0a9 100644
--- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php
@@ -6,6 +6,7 @@
 namespace Magento\Cms\Test\Unit\Ui\Component\Listing\Column;
 
 use Magento\Cms\Ui\Component\Listing\Column\PageActions;
+use Magento\Framework\Escaper;
 
 class PageActionsTest extends \PHPUnit_Framework_TestCase
 {
@@ -34,12 +35,20 @@ class PageActionsTest extends \PHPUnit_Framework_TestCase
             ]
         );
 
+        $escaper = $this->getMockBuilder(Escaper::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['escapeHtml'])
+            ->getMock();
+        $objectManager->setBackwardCompatibleProperty($model, 'escaper', $escaper);
+
         // Define test input and expectations
+        $title = 'page title';
         $items = [
             'data' => [
                 'items' => [
                     [
-                        'page_id' => $pageId
+                        'page_id' => $pageId,
+                        'title' => $title
                     ]
                 ]
             ]
@@ -48,6 +57,7 @@ class PageActionsTest extends \PHPUnit_Framework_TestCase
         $expectedItems = [
             [
                 'page_id' => $pageId,
+                'title' => $title,
                 $name => [
                     'edit' => [
                         'href' => 'test/url/edit',
@@ -57,14 +67,19 @@ class PageActionsTest extends \PHPUnit_Framework_TestCase
                         'href' => 'test/url/delete',
                         'label' => __('Delete'),
                         'confirm' => [
-                            'title' => __('Delete ${ $.$data.title }'),
-                            'message' => __('Are you sure you wan\'t to delete a ${ $.$data.title } record?')
+                            'title' => __('Delete %1', $title),
+                            'message' => __('Are you sure you wan\'t to delete a %1 record?', $title)
                         ],
                     ]
                 ],
             ]
         ];
 
+        $escaper->expects(static::once())
+            ->method('escapeHtml')
+            ->with($title)
+            ->willReturn($title);
+
         // Configure mocks and object data
         $urlBuilderMock->expects($this->any())
             ->method('getUrl')
diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php
index e71352c465333396312cc0bd0242cbe45f62bd17..f0a1fe7981f8c3007055973eb4e296c23afe5ab8 100644
--- a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php
+++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php
@@ -9,6 +9,8 @@ use Magento\Framework\UrlInterface;
 use Magento\Framework\View\Element\UiComponent\ContextInterface;
 use Magento\Framework\View\Element\UiComponentFactory;
 use Magento\Ui\Component\Listing\Columns\Column;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Escaper;
 
 /**
  * Class BlockActions
@@ -27,6 +29,11 @@ class BlockActions extends Column
      */
     protected $urlBuilder;
 
+    /**
+     * @var Escaper
+     */
+    private $escaper;
+
     /**
      * Constructor
      *
@@ -47,10 +54,6 @@ class BlockActions extends Column
         parent::__construct($context, $uiComponentFactory, $components, $data);
     }
 
-    /**
-     * @param array $items
-     * @return array
-     */
     /**
      * Prepare Data Source
      *
@@ -62,6 +65,7 @@ class BlockActions extends Column
         if (isset($dataSource['data']['items'])) {
             foreach ($dataSource['data']['items'] as & $item) {
                 if (isset($item['block_id'])) {
+                    $title = $this->getEscaper()->escapeHtml($item['title']);
                     $item[$this->getData('name')] = [
                         'edit' => [
                             'href' => $this->urlBuilder->getUrl(
@@ -81,8 +85,8 @@ class BlockActions extends Column
                             ),
                             'label' => __('Delete'),
                             'confirm' => [
-                                'title' => __('Delete "${ $.$data.title }"'),
-                                'message' => __('Are you sure you wan\'t to delete a "${ $.$data.title }" record?')
+                                'title' => __('Delete %1', $title),
+                                'message' => __('Are you sure you wan\'t to delete a %1 record?', $title)
                             ]
                         ]
                     ];
@@ -92,4 +96,17 @@ class BlockActions extends Column
 
         return $dataSource;
     }
+
+    /**
+     * Get instance of escaper
+     * @return Escaper
+     * @deprecated
+     */
+    private function getEscaper()
+    {
+        if (!$this->escaper) {
+            $this->escaper = ObjectManager::getInstance()->get(Escaper::class);
+        }
+        return $this->escaper;
+    }
 }
diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php
index fe85fd0ef314070c5c6cdb6f34435e72af3e152b..f23afbffa792e6b5b92166b5268e3942735bd21f 100644
--- a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php
+++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php
@@ -5,11 +5,13 @@
  */
 namespace Magento\Cms\Ui\Component\Listing\Column;
 
+use Magento\Cms\Block\Adminhtml\Page\Grid\Renderer\Action\UrlBuilder;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Escaper;
+use Magento\Framework\UrlInterface;
 use Magento\Framework\View\Element\UiComponent\ContextInterface;
 use Magento\Framework\View\Element\UiComponentFactory;
 use Magento\Ui\Component\Listing\Columns\Column;
-use Magento\Cms\Block\Adminhtml\Page\Grid\Renderer\Action\UrlBuilder;
-use Magento\Framework\UrlInterface;
 
 /**
  * Class PageActions
@@ -31,6 +33,11 @@ class PageActions extends Column
      */
     private $editUrl;
 
+    /**
+     * @var Escaper
+     */
+    private $escaper;
+
     /**
      * @param ContextInterface $context
      * @param UiComponentFactory $uiComponentFactory
@@ -71,12 +78,13 @@ class PageActions extends Column
                         'href' => $this->urlBuilder->getUrl($this->editUrl, ['page_id' => $item['page_id']]),
                         'label' => __('Edit')
                     ];
+                    $title = $this->getEscaper()->escapeHtml($item['title']);
                     $item[$name]['delete'] = [
                         'href' => $this->urlBuilder->getUrl(self::CMS_URL_PATH_DELETE, ['page_id' => $item['page_id']]),
                         'label' => __('Delete'),
                         'confirm' => [
-                            'title' => __('Delete ${ $.$data.title }'),
-                            'message' => __('Are you sure you wan\'t to delete a ${ $.$data.title } record?')
+                            'title' => __('Delete %1', $title),
+                            'message' => __('Are you sure you wan\'t to delete a %1 record?', $title)
                         ]
                     ];
                 }
@@ -95,4 +103,17 @@ class PageActions extends Column
 
         return $dataSource;
     }
+
+    /**
+     * Get instance of escaper
+     * @return Escaper
+     * @deprecated
+     */
+    private function getEscaper()
+    {
+        if (!$this->escaper) {
+            $this->escaper = ObjectManager::getInstance()->get(Escaper::class);
+        }
+        return $this->escaper;
+    }
 }
diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json
index 66f6da042e6c9a77e25eb5c9e8f1595c16e3e5f6..7f2ed4d7a7dcdc59916c34c796f7f3fc05ec6cc9 100644
--- a/app/code/Magento/Cms/composer.json
+++ b/app/code/Magento/Cms/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-cms",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-theme": "100.2.*",
         "magento/module-widget": "100.2.*",
diff --git a/app/code/Magento/Cms/i18n/en_US.csv b/app/code/Magento/Cms/i18n/en_US.csv
index 6f3a2955a5c65b5cf1760519741fd60d49133123..9a9f6ac4c6888e386d44c679c94a87533844342d 100644
--- a/app/code/Magento/Cms/i18n/en_US.csv
+++ b/app/code/Magento/Cms/i18n/en_US.csv
@@ -84,10 +84,8 @@ Exception,Exception
 "All Store Views","All Store Views"
 Edit,Edit
 Delete,Delete
-"Delete ${ $.$data.title }","Delete ${ $.$data.title }"
-"Are you sure you wan\'t to delete a ${ $.$data.title } record?","Are you sure you wan\'t to delete a ${ $.$data.title } record?"
-"Delete ""${ $.$data.title }""","Delete ""${ $.$data.title }"""
-"Are you sure you wan\'t to delete a ""${ $.$data.title }"" record?","Are you sure you wan\'t to delete a ""${ $.$data.title }"" record?"
+"Delete %1","Delete %1"
+"Are you sure you wan\'t to delete a %1 record?","Are you sure you wan\'t to delete a %1 record?"
 View,View
 px.,px.
 "No files found","No files found"
diff --git a/app/code/Magento/CmsUrlRewrite/composer.json b/app/code/Magento/CmsUrlRewrite/composer.json
index 1ae1efd9350a760846e76fcac8939ef574194361..1d2e70c74eb4f9fd0876f92c37b30b5e9387d2cd 100644
--- a/app/code/Magento/CmsUrlRewrite/composer.json
+++ b/app/code/Magento/CmsUrlRewrite/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-cms-url-rewrite",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-cms": "101.1.*",
         "magento/module-url-rewrite": "100.2.*",
diff --git a/app/code/Magento/Config/Model/Config/Backend/Baseurl.php b/app/code/Magento/Config/Model/Config/Backend/Baseurl.php
index 09fd99773813117a71b43240eaafc5b96bf967ca..f08c2f8e04434c7a26645669ff3a4c1c8d1840c7 100644
--- a/app/code/Magento/Config/Model/Config/Backend/Baseurl.php
+++ b/app/code/Magento/Config/Model/Config/Backend/Baseurl.php
@@ -5,6 +5,9 @@
  */
 namespace Magento\Config\Model\Config\Backend;
 
+use Magento\Framework\Validator\Url as UrlValidator;
+use Magento\Framework\App\ObjectManager;
+
 class Baseurl extends \Magento\Framework\App\Config\Value
 {
     /**
@@ -12,6 +15,11 @@ class Baseurl extends \Magento\Framework\App\Config\Value
      */
     protected $_mergeService;
 
+    /**
+     * @var UrlValidator
+     */
+    private $urlValidator;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -193,8 +201,7 @@ class Baseurl extends \Magento\Framework\App\Config\Value
      */
     private function _isFullyQualifiedUrl($value)
     {
-        $url = parse_url($value);
-        return isset($url['scheme']) && isset($url['host']) && preg_match('/\/$/', $value);
+        return preg_match('/\/$/', $value) && $this->getUrlValidator()->isValid($value, ['http', 'https']);
     }
 
     /**
@@ -216,4 +223,18 @@ class Baseurl extends \Magento\Framework\App\Config\Value
         }
         return parent::afterSave();
     }
+
+    /**
+     * Get URL Validator
+     *
+     * @deprecated
+     * @return UrlValidator
+     */
+    private function getUrlValidator()
+    {
+        if (!$this->urlValidator) {
+            $this->urlValidator = ObjectManager::getInstance()->get(UrlValidator::class);
+        }
+        return $this->urlValidator;
+    }
 }
diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json
index 54f25860572d07ab371458b5bafcc1e4e358aab0..ab9c95e1166536ebb71adf36a1b5f1b9aea06b68 100644
--- a/app/code/Magento/Config/composer.json
+++ b/app/code/Magento/Config/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-config",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-cron": "100.2.*",
diff --git a/app/code/Magento/ConfigurableImportExport/composer.json b/app/code/Magento/ConfigurableImportExport/composer.json
index 6c249134d28626b4c8846fd7491cf25b2e278638..d292e73198435431015dff6bcfe1a69d516debc9 100644
--- a/app/code/Magento/ConfigurableImportExport/composer.json
+++ b/app/code/Magento/ConfigurableImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-configurable-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-import-export": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php
index 0fdfbd3bfa172ee597414ed3ab4c46bbac2a9549..5575d6f7ef56fa4f7f2fed433299c01eaa4ba98d 100644
--- a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php
+++ b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php
@@ -32,6 +32,16 @@ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementI
      */
     private $dataObjectHelper;
 
+    /**
+     * @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory;
+     */
+    private $optionsFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory
+     */
+    private $attributeFactory;
+
     /**
      * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
      * @param \Magento\Catalog\Api\Data\ProductInterfaceFactory $productFactory
@@ -102,9 +112,28 @@ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementI
             throw new StateException(__('Product has been already attached'));
         }
 
+        $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions();
+        if (empty($configurableProductOptions)) {
+            throw new StateException(__('Parent product does not have configurable product options'));
+        }
+
+        $attributeIds = [];
+        foreach ($configurableProductOptions as $configurableProductOption) {
+            $attributeCode = $configurableProductOption->getProductAttribute()->getAttributeCode();
+            if (!$child->getData($attributeCode)) {
+                throw new StateException(__('Child product does not have attribute value %1', $attributeCode));
+            }
+            $attributeIds[] = $configurableProductOption->getAttributeId();
+        }
+        $configurableOptionData = $this->getConfigurableAttributesData($attributeIds);
+
+        /** @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory $optionFactory */
+        $optionFactory = $this->getOptionsFactory();
+        $options = $optionFactory->create($configurableOptionData);
         $childrenIds[] = $child->getId();
+        $product->getExtensionAttributes()->setConfigurableProductOptions($options);
         $product->getExtensionAttributes()->setConfigurableProductLinks($childrenIds);
-        $product->save();
+        $this->productRepository->save($product);
         return true;
     }
 
@@ -133,7 +162,75 @@ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementI
             throw new NoSuchEntityException(__('Requested option doesn\'t exist'));
         }
         $product->getExtensionAttributes()->setConfigurableProductLinks($ids);
-        $product->save();
+        $this->productRepository->save($product);
         return true;
     }
+
+    /**
+     * Get Options Factory
+     *
+     * @return \Magento\ConfigurableProduct\Helper\Product\Options\Factory
+     *
+     * @deprecated
+     */
+    private function getOptionsFactory()
+    {
+        if (!$this->optionsFactory) {
+            $this->optionsFactory = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class);
+        }
+        return $this->optionsFactory;
+    }
+
+    /**
+     * Get Attribute Factory
+     *
+     * @return \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory
+     *
+     * @deprecated
+     */
+    private function getAttributeFactory()
+    {
+        if (!$this->attributeFactory) {
+            $this->attributeFactory = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class);
+        }
+        return $this->attributeFactory;
+    }
+
+    /**
+     * Get Configurable Attribute Data
+     *
+     * @param int[] $attributeIds
+     * @return array
+     */
+    private function getConfigurableAttributesData($attributeIds)
+    {
+        $configurableAttributesData = [];
+        $attributeValues = [];
+        $attributes = $this->getAttributeFactory()->create()
+            ->getCollection()
+            ->addFieldToFilter('attribute_id', $attributeIds)
+            ->getItems();
+        foreach ($attributes as $attribute) {
+            foreach ($attribute->getOptions() as $option) {
+                if ($option->getValue()) {
+                    $attributeValues[] = [
+                        'label' => $option->getLabel(),
+                        'attribute_id' => $attribute->getId(),
+                        'value_index' => $option->getValue(),
+                    ];
+                }
+            }
+            $configurableAttributesData[] =
+                [
+                    'attribute_id' => $attribute->getId(),
+                    'code' => $attribute->getAttributeCode(),
+                    'label' => $attribute->getStoreLabel(),
+                    'values' => $attributeValues,
+                ];
+        }
+
+        return $configurableAttributesData;
+    }
 }
diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php
index 4e6fa8ae5210d77726b393047a7433ca03d69c7d..fbb69798ff94fbdf8caafc7486e564da662cf655 100644
--- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php
@@ -8,6 +8,7 @@
 namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Indexer\Price;
 
 use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
 
 class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice
 {
@@ -166,6 +167,9 @@ class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\
         $this->_prepareConfigurableOptionAggregateTable();
         $this->_prepareConfigurableOptionPriceTable();
 
+        $statusAttribute = $this->_getAttribute(ProductInterface::STATUS);
+        $linkField = $metadata->getLinkField();
+
         $select = $connection->select()->from(
             ['i' => $this->_getDefaultFinalPriceTable()],
             []
@@ -175,7 +179,7 @@ class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\
             ['parent_id' => 'e.entity_id']
         )->join(
             ['l' => $this->getTable('catalog_product_super_link')],
-            'l.parent_id = e.' . $metadata->getLinkField(),
+            'l.parent_id = e.' . $linkField,
             ['product_id']
         )->columns(
             ['customer_group_id', 'website_id'],
@@ -186,11 +190,21 @@ class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\
             []
         )->where(
             'le.required_options=0'
+        )->join(
+            ['product_status' => $this->getTable($statusAttribute->getBackend()->getTable())],
+            sprintf(
+                'le.%1$s = product_status.%1$s AND product_status.attribute_id = %2$s',
+                $linkField,
+                $statusAttribute->getAttributeId()
+            ),
+            []
+        )->where(
+            'product_status.value=' . ProductStatus::STATUS_ENABLED
         )->group(
-            ['parent_id', 'i.customer_group_id', 'i.website_id', 'l.product_id']
+            ['e.entity_id', 'i.customer_group_id', 'i.website_id', 'l.product_id']
         );
-        $priceColumn = $this->_addAttributeToSelect($select, 'price', 'l.product_id', 0, null, true);
-        $tierPriceColumn = $connection->getCheckSql("MIN(i.tier_price) IS NOT NULL", "i.tier_price", 'NULL');
+        $priceColumn = $this->_addAttributeToSelect($select, 'price', 'le.' . $linkField, 0, null, true);
+        $tierPriceColumn = $connection->getIfNullSql('MIN(i.tier_price)', 'NULL');
 
         $select->columns(
             ['price' => $priceColumn, 'tier_price' => $tierPriceColumn]
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php
index 6b69888e6dd0924cf6e090bdb1eb0af2daddaab1..5a7886ea3ea640c2f276ffb7eedeaa243ff9e790 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php
@@ -6,8 +6,8 @@
 
 namespace Magento\ConfigurableProduct\Test\Unit\Model;
 
+use Magento\ConfigurableProduct\Model\LinkManagement;
 use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
-use Magento\ConfigurableProduct\Test\Unit\Model\Product\ProductExtensionAttributes;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -146,15 +146,59 @@ class LinkManagementTest extends \PHPUnit_Framework_TestCase
 
         $configurable = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
             ->disableOriginalConstructor()
+            ->setMethods(['getId', 'getExtensionAttributes'])
+            ->getMock();
+        $simple = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getId', 'getData'])
             ->getMock();
 
-        $configurable->expects($this->any())->method('getId')->will($this->returnValue(666));
+        $extensionAttributesMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class)
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'getConfigurableProductOptions', 'setConfigurableProductOptions', 'setConfigurableProductLinks'
+            ])
+            ->getMock();
+        $optionMock = $this->getMockBuilder(\Magento\ConfigurableProduct\Api\Data\Option::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getProductAttribute', 'getAttributeId'])
+            ->getMock();
+        $productAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getAttributeCode'])
+            ->getMock();
+        $optionsFactoryMock = $this->getMockBuilder(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $reflectionClass = new \ReflectionClass(\Magento\ConfigurableProduct\Model\LinkManagement::class);
+        $optionsFactoryReflectionProperty = $reflectionClass->getProperty('optionsFactory');
+        $optionsFactoryReflectionProperty->setAccessible(true);
+        $optionsFactoryReflectionProperty->setValue($this->object, $optionsFactoryMock);
 
-        $simple = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+        $attributeFactoryMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class)
             ->disableOriginalConstructor()
+            ->setMethods(['create'])
             ->getMock();
+        $attributeFactoryReflectionProperty = $reflectionClass->getProperty('attributeFactory');
+        $attributeFactoryReflectionProperty->setAccessible(true);
+        $attributeFactoryReflectionProperty->setValue($this->object, $attributeFactoryMock);
 
-        $simple->expects($this->any())->method('getId')->will($this->returnValue(999));
+        $attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getCollection', 'getOptions', 'getId', 'getAttributeCode', 'getStoreLabel'])
+            ->getMock();
+        $attributeOptionMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Option::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getValue', 'getLabel'])
+            ->getMock();
+
+        $attributeCollectionMock = $this->getMockBuilder(
+            \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection::class
+        )
+            ->disableOriginalConstructor()
+            ->setMethods(['addFieldToFilter', 'getItems'])
+            ->getMock();
 
         $this->productRepository->expects($this->at(0))->method('get')->with($productSku)->willReturn($configurable);
         $this->productRepository->expects($this->at(1))->method('get')->with($childSku)->willReturn($simple);
@@ -164,15 +208,30 @@ class LinkManagementTest extends \PHPUnit_Framework_TestCase
                 $this->returnValue([0 => [1, 2, 3]])
             );
 
-        $extensionAttributes = $this->getMockBuilder(ProductExtensionAttributes::class)
-            ->setMethods(['setConfigurableProductLinks'])
-            ->disableOriginalConstructor()
-            ->getMockForAbstractClass();
+        $configurable->expects($this->any())->method('getId')->will($this->returnValue(666));
+        $simple->expects($this->any())->method('getId')->will($this->returnValue(999));
+
+        $configurable->expects($this->any())->method('getExtensionAttributes')->willReturn($extensionAttributesMock);
+        $extensionAttributesMock->expects($this->any())
+            ->method('getConfigurableProductOptions')
+            ->willReturn([$optionMock]);
+        $optionMock->expects($this->any())->method('getProductAttribute')->willReturn($productAttributeMock);
+        $productAttributeMock->expects($this->any())->method('getAttributeCode')->willReturn('color');
+        $simple->expects($this->any())->method('getData')->willReturn('color');
+        $optionMock->expects($this->any())->method('getAttributeId')->willReturn('1');
 
-        $configurable->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes);
-        $extensionAttributes->expects($this->once())->method('setConfigurableProductLinks')->willReturnSelf();
+        $optionsFactoryMock->expects($this->any())->method('create')->willReturn([$optionMock]);
+        $attributeFactoryMock->expects($this->any())->method('create')->willReturn($attributeMock);
+        $attributeMock->expects($this->any())->method('getCollection')->willReturn($attributeCollectionMock);
+        $attributeCollectionMock->expects($this->any())->method('addFieldToFilter')->willReturnSelf();
+        $attributeCollectionMock->expects($this->any())->method('getItems')->willReturn([$attributeMock]);
 
-        $configurable->expects($this->once())->method('save');
+        $attributeMock->expects($this->any())->method('getOptions')->willReturn([$attributeOptionMock]);
+
+        $extensionAttributesMock->expects($this->any())->method('setConfigurableProductOptions');
+        $extensionAttributesMock->expects($this->any())->method('setConfigurableProductLinks');
+
+        $this->productRepository->expects($this->once())->method('save');
 
         $this->assertTrue(true, $this->object->addChild($productSku, $childSku));
     }
@@ -243,15 +302,13 @@ class LinkManagementTest extends \PHPUnit_Framework_TestCase
         $productType->expects($this->once())->method('getUsedProducts')
             ->will($this->returnValue([$option]));
 
-        $extensionAttributes = $this->getMockBuilder(ProductExtensionAttributes::class)
+        $extensionAttributesMock = $this->getMockBuilder(\Magento\Framework\Api\ExtensionAttributesInterface::class)
             ->setMethods(['setConfigurableProductLinks'])
             ->disableOriginalConstructor()
             ->getMockForAbstractClass();
 
-        $product->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes);
-        $extensionAttributes->expects($this->once())->method('setConfigurableProductLinks')->willReturnSelf();
-
-        $product->expects($this->once())->method('save');
+        $product->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributesMock);
+        $this->productRepository->expects($this->once())->method('save');
         $this->assertTrue($this->object->removeChild($productSku, $childSku));
     }
 
diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json
index 8dda841250ff126d0fed90a03dd4272169266392..755b94a600a099a0ada188d435f3682cf6736e69 100644
--- a/app/code/Magento/ConfigurableProduct/composer.json
+++ b/app/code/Magento/ConfigurableProduct/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-configurable-product",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-inventory": "100.2.*",
diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json
index b541f1e7a0ed3afe8f8bfb8c25b7f27282bc9372..377e46256c0886c5479cbe256451310bac14b896 100644
--- a/app/code/Magento/Contact/composer.json
+++ b/app/code/Magento/Contact/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-contact",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Cookie/composer.json b/app/code/Magento/Cookie/composer.json
index 5222975723385a48adf043f695c08e319f11d57b..96a050f2ad20dfa94958fd11f7a24cfb73010642 100644
--- a/app/code/Magento/Cookie/composer.json
+++ b/app/code/Magento/Cookie/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-cookie",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json
index b1155c028f91971b5508269a06ebef675032e5b5..75a7ce27a2aa110d55398a0588ae4f4907c724c2 100644
--- a/app/code/Magento/Cron/composer.json
+++ b/app/code/Magento/Cron/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-cron",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json
index 2cdfedadf7a38c7c792a27de4498772cc59c692b..29f0bd7435eef99279f54273163f17041d64a351 100644
--- a/app/code/Magento/CurrencySymbol/composer.json
+++ b/app/code/Magento/CurrencySymbol/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-currency-symbol",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-page-cache": "100.2.*",
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php
index 77bf7af2a4031ac71488b7644225a6c13dc520f2..59e12d72ded6c6cd4de5aaf323acd5f1ffbbd122 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php
@@ -84,7 +84,7 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index
         $result = $metadataForm->compactData($formData);
 
         // Re-initialize additional attributes
-        $formData = array_replace($formData, $result);
+        $formData = array_replace($result, $formData);
 
         // Unset unused attributes
         $formAttributes = $metadataForm->getAttributes();
diff --git a/app/code/Magento/Customer/Controller/Section/Load.php b/app/code/Magento/Customer/Controller/Section/Load.php
index 19b361b2c830d763681184b5055f0d477c4641ae..c1ec593e4a7aeec51a53323052aeae62cb7036ff 100644
--- a/app/code/Magento/Customer/Controller/Section/Load.php
+++ b/app/code/Magento/Customer/Controller/Section/Load.php
@@ -5,10 +5,10 @@
  */
 namespace Magento\Customer\Controller\Section;
 
+use Magento\Customer\CustomerData\Section\Identifier;
 use Magento\Customer\CustomerData\SectionPoolInterface;
 use Magento\Framework\App\Action\Context;
 use Magento\Framework\Controller\Result\JsonFactory;
-use Magento\Framework\Exception\LocalizedException;
 
 /**
  * Customer section controller
@@ -22,6 +22,7 @@ class Load extends \Magento\Framework\App\Action\Action
 
     /**
      * @var Identifier
+     * @deprecated
      */
     protected $sectionIdentifier;
 
@@ -30,26 +31,34 @@ class Load extends \Magento\Framework\App\Action\Action
      */
     protected $sectionPool;
 
+    /**
+     * @var \Magento\Framework\Escaper
+     */
+    private $escaper;
+
     /**
      * @param Context $context
      * @param JsonFactory $resultJsonFactory
-     * @param \Magento\Customer\CustomerData\Section\Identifier $sectionIdentifier
+     * @param Identifier $sectionIdentifier
      * @param SectionPoolInterface $sectionPool
+     * @param Escaper $escaper
      */
     public function __construct(
         Context $context,
         JsonFactory $resultJsonFactory,
-        \Magento\Customer\CustomerData\Section\Identifier $sectionIdentifier,
-        SectionPoolInterface $sectionPool
+        Identifier $sectionIdentifier,
+        SectionPoolInterface $sectionPool,
+        \Magento\Framework\Escaper $escaper = null
     ) {
         parent::__construct($context);
         $this->resultJsonFactory = $resultJsonFactory;
         $this->sectionIdentifier = $sectionIdentifier;
         $this->sectionPool = $sectionPool;
+        $this->escaper = $escaper ?: $this->_objectManager->get(\Magento\Framework\Escaper::class);
     }
 
     /**
-     * @return \Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\Result\Redirect
+     * @return \Magento\Framework\Controller\Result\Json
      */
     public function execute()
     {
@@ -60,7 +69,7 @@ class Load extends \Magento\Framework\App\Action\Action
             $sectionNames = $sectionNames ? array_unique(\explode(',', $sectionNames)) : null;
 
             $updateSectionId = $this->getRequest()->getParam('update_section_id');
-            if ('false' == $updateSectionId) {
+            if ('false' === $updateSectionId) {
                 $updateSectionId = false;
             }
             $response = $this->sectionPool->getSectionsData($sectionNames, (bool)$updateSectionId);
@@ -70,7 +79,7 @@ class Load extends \Magento\Framework\App\Action\Action
                 \Zend\Http\AbstractMessage::VERSION_11,
                 'Bad Request'
             );
-            $response = ['message' => $e->getMessage()];
+            $response = ['message' => $this->escaper->escapeHtml($e->getMessage())];
         }
 
         return $resultJson->setData($response);
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index 74f0ebc2b5e0026acbdc5061949c10ad04aa8d9c..53e1a270fb3b04a791a368a375ce7e8b1ef62d8d 100644
--- a/app/code/Magento/Customer/composer.json
+++ b/app/code/Magento/Customer/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-customer",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-eav": "100.2.*",
         "magento/module-directory": "100.2.*",
diff --git a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
index 1ff64fffe20369a5675afcc573c99b9f926ba30a..9ad2cf5265043b4fd1850514258d99276d500ff3 100644
--- a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
+++ b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
@@ -78,7 +78,6 @@
                     <!-- ko foreach: getRegion('additional-login-form-fields') -->
                     <!-- ko template: getTemplate() --><!-- /ko -->
                     <!-- /ko -->
-                    </div>
                     <div class="actions-toolbar">
                         <input name="context" type="hidden" value="checkout" />
                         <div class="primary">
diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json
index 533f40c7688e4aa8269bedfe84f5331a772b0b2a..cd02f6dbfb38b46bda32ebdcb87720124eab37e4 100644
--- a/app/code/Magento/CustomerImportExport/composer.json
+++ b/app/code/Magento/CustomerImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-customer-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Deploy/composer.json b/app/code/Magento/Deploy/composer.json
index 856e0d8b3e542a37cdd7fcf7554b9e4e158de245..ed0b8520ca645afa8af2506616f9dccde6965f08 100644
--- a/app/code/Magento/Deploy/composer.json
+++ b/app/code/Magento/Deploy/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-deploy",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-require-js": "100.2.*",
diff --git a/app/code/Magento/Developer/composer.json b/app/code/Magento/Developer/composer.json
index 23f6d20c2aab74dc0f23c03f5727aa99379fbf54..73fd1c17750c6749bd0f89cd9fe55939fbe2d419 100644
--- a/app/code/Magento/Developer/composer.json
+++ b/app/code/Magento/Developer/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-developer",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/framework": "100.2.*",
         "magento/module-config": "100.2.*"
diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json
index e88cd535952d628628bbc984137430d5370a6ecd..15ca7882331a145ba1993ded371bd084bc8c83b3 100644
--- a/app/code/Magento/Dhl/composer.json
+++ b/app/code/Magento/Dhl/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-dhl",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-shipping": "100.2.*",
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php
index 9ea0babbfd9982c3e9c5657e218668c384b47501..ed36ad3ace22b232c8071bbb195184066a2ebd50 100644
--- a/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php
@@ -12,7 +12,10 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
      *
      * @var array
      */
-    protected $_idAttributes = ['/config/zip' => 'countryCode'];
+    protected $_idAttributes = [
+        '/config/zip' => 'countryCode',
+        '/config/zip/codes/code' => 'id',
+    ];
 
     /**
      * Construct the FileSystem Reader Class
diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json
index 9b3b253c26a35ed14c4de51c77624a10750ce5f2..82d8bca34da840e57511bb3912c9b531297d9e86 100644
--- a/app/code/Magento/Directory/composer.json
+++ b/app/code/Magento/Directory/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-directory",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Downloadable/composer.json b/app/code/Magento/Downloadable/composer.json
index 8d8814740ccd13248b1e7ab903052ca429567ead..ea8eef6436ef9174e9643c742684f29d1129799f 100644
--- a/app/code/Magento/Downloadable/composer.json
+++ b/app/code/Magento/Downloadable/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-downloadable",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/DownloadableImportExport/composer.json b/app/code/Magento/DownloadableImportExport/composer.json
index c99a0d6d05b822e792e24a27a69f68f240f8b002..4f95711b279d0f907934fc4cf2bc4b8056ff4817 100644
--- a/app/code/Magento/DownloadableImportExport/composer.json
+++ b/app/code/Magento/DownloadableImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-downloadable-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-import-export": "100.2.*",
         "magento/module-catalog-import-export": "100.2.*",
diff --git a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/AttributeTest.php b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/AttributeTest.php
index bcad34654b98aa2d6d3844d1a780d585713c8d86..c18af6380a3b71ca7adfd6af5146f853926b419d 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/AttributeTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/AttributeTest.php
@@ -29,7 +29,7 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
     {
         $this->contextMock = $this->getMock(
             \Magento\Framework\Model\Context::class,
-            ['getCacheManager', 'getEventDispatcher', 'getLogger', 'getAppState', 'getActionValidator'],
+            [],
             [],
             '',
             false
diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json
index 16e62a6434a26aa358a3491d697ce7cd3bb54ad7..9863a89fff5d3d64ccbf8eaa4b3f5691168e0155 100644
--- a/app/code/Magento/Eav/composer.json
+++ b/app/code/Magento/Eav/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-eav",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json
index 33d04b921278d3c57ce0107792c6deef458c73ab..648c984de0bbb6e93d16f84110075dc36909cfda 100644
--- a/app/code/Magento/Email/composer.json
+++ b/app/code/Magento/Email/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-email",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-theme": "100.2.*",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/EncryptionKey/composer.json b/app/code/Magento/EncryptionKey/composer.json
index 6d7ff5558734ab1952b59b2e02db4cc5093f9984..11b1c034a76a792cd782be06db484e494764553f 100644
--- a/app/code/Magento/EncryptionKey/composer.json
+++ b/app/code/Magento/EncryptionKey/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-encryption-key",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/framework": "100.2.*"
diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json
index d27d5c1c60d407ce4d1d5b3781b0209c5955a0d4..8d487485c0d210824949657ab7444ba937ef9996 100644
--- a/app/code/Magento/Fedex/composer.json
+++ b/app/code/Magento/Fedex/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-fedex",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-shipping": "100.2.*",
         "magento/module-directory": "100.2.*",
diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json
index 04c620dc36db5829f9c8c6aa8a6aec620d211e95..067bf16017b231977183491ff6a4e8cdf91dfe68 100644
--- a/app/code/Magento/GiftMessage/composer.json
+++ b/app/code/Magento/GiftMessage/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-gift-message",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-checkout": "100.2.*",
diff --git a/app/code/Magento/GoogleAdwords/composer.json b/app/code/Magento/GoogleAdwords/composer.json
index ad3df5c0b8b2621f395acbfe81bfde3c6b7bae27..cacbbe2088c778ff4a3777f129aea263cf9dee79 100644
--- a/app/code/Magento/GoogleAdwords/composer.json
+++ b/app/code/Magento/GoogleAdwords/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-google-adwords",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-sales": "100.2.*",
         "magento/framework": "100.2.*"
diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json
index 4cccc7bd0cbff69369ae852138045ed06a0dbf4a..8653e93d7a98338160895c65011cdc2f7471270f 100644
--- a/app/code/Magento/GoogleAnalytics/composer.json
+++ b/app/code/Magento/GoogleAnalytics/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-google-analytics",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-sales": "100.2.*",
         "magento/framework": "100.2.*",
diff --git a/app/code/Magento/GoogleOptimizer/composer.json b/app/code/Magento/GoogleOptimizer/composer.json
index 20a48fc78060b53fb144aa5da405b343ce696063..8c61e9f068ea122b74a7dea02ed5c110d26629b6 100644
--- a/app/code/Magento/GoogleOptimizer/composer.json
+++ b/app/code/Magento/GoogleOptimizer/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-google-optimizer",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-google-analytics": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/GroupedImportExport/composer.json b/app/code/Magento/GroupedImportExport/composer.json
index b036a8d5d528bd3959ea66b294d7b51736f7ba2c..50c061e5b56da30c1faf2bfab9439460be6908a3 100644
--- a/app/code/Magento/GroupedImportExport/composer.json
+++ b/app/code/Magento/GroupedImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-grouped-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-import-export": "100.2.*",
         "magento/module-catalog-import-export": "100.2.*",
diff --git a/app/code/Magento/GroupedProduct/composer.json b/app/code/Magento/GroupedProduct/composer.json
index 69aed214284454722708703068de37e3134393f0..0f207eb414789becda0c4e57846f0a48ced13d7a 100644
--- a/app/code/Magento/GroupedProduct/composer.json
+++ b/app/code/Magento/GroupedProduct/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-grouped-product",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-catalog-inventory": "100.2.*",
diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json
index 35a088cbd9c91907c3f9f2c434f16cfb86ed57a8..5e403d2180652a6f3565bf03b573abf75310f19f 100644
--- a/app/code/Magento/ImportExport/composer.json
+++ b/app/code/Magento/ImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/Indexer/composer.json b/app/code/Magento/Indexer/composer.json
index cbaab12f6ee285ac1207f8c01d5ed5ff5af42c07..e80d8a9f7bc90d63dfbbced39431571d73fdc937 100644
--- a/app/code/Magento/Indexer/composer.json
+++ b/app/code/Magento/Indexer/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-indexer",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/Integration/composer.json b/app/code/Magento/Integration/composer.json
index 028e56472268abc0e0fcc612107a5bd8072da806..f76d60c957c87d828cc773e96a5edf10266293c9 100644
--- a/app/code/Magento/Integration/composer.json
+++ b/app/code/Magento/Integration/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-integration",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/LayeredNavigation/composer.json b/app/code/Magento/LayeredNavigation/composer.json
index 99299c3e4a32cccd465af4131bc549b033142545..d1d82781bb5c881cceaaf0b8ccdf85fa02c54e86 100644
--- a/app/code/Magento/LayeredNavigation/composer.json
+++ b/app/code/Magento/LayeredNavigation/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-layered-navigation",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/framework": "100.2.*"
diff --git a/app/code/Magento/Marketplace/composer.json b/app/code/Magento/Marketplace/composer.json
index 2916ff94544bcc46cd59a9e48e9385e89ea6283b..ed79a80bc0c35d81efa3f27867b33846e3a19007 100644
--- a/app/code/Magento/Marketplace/composer.json
+++ b/app/code/Magento/Marketplace/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-marketplace",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/module-backend": "100.2.*"
     },
diff --git a/app/code/Magento/MediaStorage/composer.json b/app/code/Magento/MediaStorage/composer.json
index fa7858d5b0aff32de7d37f2756aca1891cb15cf7..141e1c19c532cc67f8152459de7e12d50fb0b9d8 100644
--- a/app/code/Magento/MediaStorage/composer.json
+++ b/app/code/Magento/MediaStorage/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-media-storage",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-config": "100.2.*",
diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json
index b86374e6be2779d14fd3d2b3e8a4d5b46b1b881f..422aac99869919aa08c31e7ac4edd39d9e0a6f2e 100644
--- a/app/code/Magento/Msrp/composer.json
+++ b/app/code/Magento/Msrp/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-msrp",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-downloadable": "100.2.*",
diff --git a/app/code/Magento/Multishipping/composer.json b/app/code/Magento/Multishipping/composer.json
index 8d9ac91cd05a07b78c19588cbcd34ce3a110cc9f..970c7ea0569a28d226f8f50c419b3d5ee998a17f 100644
--- a/app/code/Magento/Multishipping/composer.json
+++ b/app/code/Magento/Multishipping/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-multishipping",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-checkout": "100.2.*",
         "magento/module-sales": "100.2.*",
diff --git a/app/code/Magento/NewRelicReporting/composer.json b/app/code/Magento/NewRelicReporting/composer.json
index 9faa17d454e5072f7dc9ec5473057bfad1533dce..097de6bea926c60644bedefec56adde409f5aa04 100644
--- a/app/code/Magento/NewRelicReporting/composer.json
+++ b/app/code/Magento/NewRelicReporting/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-new-relic-reporting",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json
index 06a278aef6d48692c856f56daf213e4bab162db8..ab5cdd1510a35285d42698ee999737a74b699d54 100644
--- a/app/code/Magento/Newsletter/composer.json
+++ b/app/code/Magento/Newsletter/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-newsletter",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-customer": "100.2.*",
         "magento/module-widget": "100.2.*",
diff --git a/app/code/Magento/OfflinePayments/Block/Info/Checkmo.php b/app/code/Magento/OfflinePayments/Block/Info/Checkmo.php
index 84b6e554d4cfb193e1418f3d9460f9fcc44f6a7d..8616c186555e3e71db0a13a13c648b5c20ff3e0c 100644
--- a/app/code/Magento/OfflinePayments/Block/Info/Checkmo.php
+++ b/app/code/Magento/OfflinePayments/Block/Info/Checkmo.php
@@ -49,20 +49,13 @@ class Checkmo extends \Magento\Payment\Block\Info
     }
 
     /**
-     * Enter description here...
-     *
+     * @deprecated
      * @return $this
      */
     protected function _convertAdditionalData()
     {
-        $details = @unserialize($this->getInfo()->getAdditionalData());
-        if (is_array($details)) {
-            $this->_payableTo = isset($details['payable_to']) ? (string)$details['payable_to'] : '';
-            $this->_mailingAddress = isset($details['mailing_address']) ? (string)$details['mailing_address'] : '';
-        } else {
-            $this->_payableTo = '';
-            $this->_mailingAddress = '';
-        }
+        $this->_payableTo = $this->getInfo()->getAdditionalInformation('payable_to');
+        $this->_mailingAddress = $this->getInfo()->getAdditionalInformation('mailing_address');
         return $this;
     }
 
diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Block/Info/CheckmoTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Block/Info/CheckmoTest.php
index 848cfbae52b25a0b4b202b296f43ae4b79c5c19a..27209fc8d3538a1465e985929ef6adb52408de93 100644
--- a/app/code/Magento/OfflinePayments/Test/Unit/Block/Info/CheckmoTest.php
+++ b/app/code/Magento/OfflinePayments/Test/Unit/Block/Info/CheckmoTest.php
@@ -5,81 +5,118 @@
  */
 namespace Magento\OfflinePayments\Test\Unit\Block\Info;
 
+use Magento\Framework\View\Element\Template\Context;
+use Magento\OfflinePayments\Block\Info\Checkmo;
+use Magento\Payment\Model\Info;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
+/**
+ * CheckmoTest contains list of test for block methods testing
+ */
 class CheckmoTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\OfflinePayments\Block\Info\Checkmo
+     * @var Info|MockObject
+     */
+    private $info;
+
+    /**
+     * @var Checkmo
      */
-    protected $_model;
+    private $block;
 
+    /**
+     * @inheritdoc
+     */
     protected function setUp()
     {
-        $context = $this->getMock(\Magento\Framework\View\Element\Template\Context::class, [], [], '', false);
-        $this->_model = new \Magento\OfflinePayments\Block\Info\Checkmo($context);
+        $context = $this->getMockBuilder(Context::class)
+            ->disableOriginalConstructor()
+            ->setMethods([])
+            ->getMock();
+
+        $this->info = $this->getMockBuilder(Info::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getAdditionalInformation'])
+            ->getMock();
+
+        $this->block = new Checkmo($context);
     }
 
     /**
+     * @covers \Magento\OfflinePayments\Block\Info\Checkmo::getPayableTo
+     * @param array $details
+     * @param string|null $expected
      * @dataProvider getPayableToDataProvider
      */
     public function testGetPayableTo($details, $expected)
     {
-        $info = $this->getMock(\Magento\Payment\Model\Info::class, ['getAdditionalData'], [], '', false);
-        $info->expects($this->once())
-            ->method('getAdditionalData')
-            ->willReturn(serialize($details));
-        $this->_model->setData('info', $info);
+        $this->info->expects(static::at(0))
+            ->method('getAdditionalInformation')
+            ->with('payable_to')
+            ->willReturn($details);
+        $this->block->setData('info', $this->info);
 
-        $this->assertEquals($expected, $this->_model->getPayableTo());
+        static::assertEquals($expected, $this->block->getPayableTo());
     }
 
     /**
+     * Get list of variations for payable configuration option testing
      * @return array
      */
     public function getPayableToDataProvider()
     {
         return [
-            [['payable_to' => 'payable'], 'payable'],
-            ['', '']
+            ['payable_to' => 'payable', 'payable'],
+            ['', null]
         ];
     }
 
     /**
+     * @covers \Magento\OfflinePayments\Block\Info\Checkmo::getMailingAddress
+     * @param array $details
+     * @param string|null $expected
      * @dataProvider getMailingAddressDataProvider
      */
     public function testGetMailingAddress($details, $expected)
     {
-        $info = $this->getMock(\Magento\Payment\Model\Info::class, ['getAdditionalData'], [], '', false);
-        $info->expects($this->once())
-            ->method('getAdditionalData')
-            ->willReturn(serialize($details));
-        $this->_model->setData('info', $info);
+        $this->info->expects(static::at(1))
+            ->method('getAdditionalInformation')
+            ->with('mailing_address')
+            ->willReturn($details);
+        $this->block->setData('info', $this->info);
 
-        $this->assertEquals($expected, $this->_model->getMailingAddress());
+        static::assertEquals($expected, $this->block->getMailingAddress());
     }
 
     /**
+     * Get list of variations for mailing address testing
      * @return array
      */
     public function getMailingAddressDataProvider()
     {
         return [
-            [['mailing_address' => 'blah@blah.com'], 'blah@blah.com'],
-            ['', '']
+            ['mailing_address' => 'blah@blah.com', 'blah@blah.com'],
+            ['mailing_address' => '', null]
         ];
     }
 
+    /**
+     * @covers \Magento\OfflinePayments\Block\Info\Checkmo::getMailingAddress
+     */
     public function testConvertAdditionalDataIsNeverCalled()
     {
-        $info = $this->getMock(\Magento\Payment\Model\Info::class, ['getAdditionalData'], [], '', false);
-        $info->expects($this->once())
-            ->method('getAdditionalData')
-            ->willReturn(serialize(['mailing_address' => 'blah@blah.com']));
-        $this->_model->setData('info', $info);
+        $mailingAddress = 'blah@blah.com';
+        $this->info->expects(static::at(1))
+            ->method('getAdditionalInformation')
+            ->with('mailing_address')
+            ->willReturn($mailingAddress);
+        $this->block->setData('info', $this->info);
 
         // First we set the property $this->_mailingAddress
-        $this->_model->getMailingAddress();
+        $this->block->getMailingAddress();
 
         // And now we get already setted property $this->_mailingAddress
-        $this->assertEquals('blah@blah.com', $this->_model->getMailingAddress());
+        static::assertEquals($mailingAddress, $this->block->getMailingAddress());
     }
 }
diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json
index 52deb08ba3d904a824faa762391ddf67ae29b026..cf728aaa1c5f6a7ea7c36163b021cb378d7df7f0 100644
--- a/app/code/Magento/OfflinePayments/composer.json
+++ b/app/code/Magento/OfflinePayments/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-offline-payments",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-checkout": "100.2.*",
         "magento/module-payment": "100.2.*",
         "magento/framework": "100.2.*"
diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml
index d5bff77e002d17d5ad8a80349ea646aee0135fa4..8c5cfd50cc110f2f8c61414c14ed2d48965929d6 100644
--- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml
+++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml
@@ -10,7 +10,7 @@
  */
 ?>
 <?php echo $block->escapeHtml($block->getMethod()->getTitle()) ?>
-<?php if ($block->getInfo()->getAdditionalData()): ?>
+<?php if ($block->getInfo()->getAdditionalInformation()): ?>
     <?php if ($block->getPayableTo()): ?>
         <br /><?php echo $block->escapeHtml(__('Make Check payable to: %1', $block->getPayableTo())) ?>
     <?php endif; ?>
diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml
index 6195cdbd776548c229a6d1dfca03c8f4c1b2a61f..5587ac239d37e84a21348cfd994d9d0b73f0ba97 100644
--- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml
+++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml
@@ -11,7 +11,7 @@
 ?>
 <?php echo $block->escapeHtml($block->getMethod()->getTitle()) ?>
     {{pdf_row_separator}}
-<?php if ($block->getInfo()->getAdditionalData()): ?>
+<?php if ($block->getInfo()->getAdditionalInformation()): ?>
     {{pdf_row_separator}}
     <?php if ($block->getPayableTo()): ?>
         <?php echo $block->escapeHtml(__('Make Check payable to: %1', $block->getPayableTo())) ?>
diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
index f0dbff1add32b2fd7d49e3b6ca5f14c4038fc2ca..3c0b6bb23086a67b48de1134cdb245daffeab045 100644
--- a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
+++ b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
@@ -11,7 +11,7 @@
 ?>
 <dl class="payment-method checkmemo">
     <dt class="title"><?php echo $block->escapeHtml($block->getMethod()->getTitle()) ?></dt>
-    <?php if ($block->getInfo()->getAdditionalData()): ?>
+    <?php if ($block->getInfo()->getAdditionalInformation()): ?>
         <?php if ($block->getPayableTo()): ?>
             <dd class="content">
                 <strong><?php echo $block->escapeHtml(__('Make Check payable to')) ?></strong>
diff --git a/app/code/Magento/OfflineShipping/composer.json b/app/code/Magento/OfflineShipping/composer.json
index 3c959b4dec766fe09cf81df46571051b714ee4e1..b429376c6cd7adc0a70b133a633b4edf068d684e 100644
--- a/app/code/Magento/OfflineShipping/composer.json
+++ b/app/code/Magento/OfflineShipping/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-offline-shipping",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/OfflineShipping/etc/adminhtml/system.xml b/app/code/Magento/OfflineShipping/etc/adminhtml/system.xml
index 50ed4cdc9417833683a04e3a715ff828f04b9674..4a4f550588f5366668f4ceee0ff895964246172b 100644
--- a/app/code/Magento/OfflineShipping/etc/adminhtml/system.xml
+++ b/app/code/Magento/OfflineShipping/etc/adminhtml/system.xml
@@ -52,6 +52,7 @@
                 <field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Show Method if Not Applicable</label>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                    <frontend_class>shipping-skip-hide</frontend_class>
                 </field>
                 <field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
                     <label>Displayed Error Message</label>
@@ -146,6 +147,7 @@
                 <field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Show Method if Not Applicable</label>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                    <frontend_class>shipping-skip-hide</frontend_class>
                 </field>
                 <field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
                     <label>Displayed Error Message</label>
diff --git a/app/code/Magento/PageCache/composer.json b/app/code/Magento/PageCache/composer.json
index 5c29e4fc3c97081626ae4a77243ccd6ac9843d38..f18eb7bbe94edd31a48c4796dc41b21cdef38a8b 100644
--- a/app/code/Magento/PageCache/composer.json
+++ b/app/code/Magento/PageCache/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-page-cache",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json
index 35ff326d916bd43f8ae2366d9b50f5b77fe46dc8..c8d7254ce9e002ced1ecfb1067d821c63dbeb5be 100644
--- a/app/code/Magento/Payment/composer.json
+++ b/app/code/Magento/Payment/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-payment",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-sales": "100.2.*",
diff --git a/app/code/Magento/Paypal/composer.json b/app/code/Magento/Paypal/composer.json
index bddc5d91a94587f4d26532246d8c83f8de6ba7f7..7503db18f008ca76252f8687df6d52f88dc0e02d 100644
--- a/app/code/Magento/Paypal/composer.json
+++ b/app/code/Magento/Paypal/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-paypal",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-checkout": "100.2.*",
diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
index 1876f07830ba7b55df25230bc256b829f65b2fc3..90cb60186e34e3730ae6d068b34e4002add00a6c 100644
--- a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
+++ b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
@@ -23,7 +23,8 @@
                 <label>Express Checkout</label>
                 <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded</frontend_model>
                 <field id="business_account" translate="label comment tooltip" showInDefault="1" showInWebsite="1" sortOrder="5">
-                    <label>Email Associated with PayPal Merchant Account</label>
+                    <label>Email Associated with PayPal Merchant Account (Optional)</label>
+                    <frontend_class>not-required</frontend_class>
                     <comment>
                         <![CDATA[<a href="http://www.magentocommerce.com/paypal">Start accepting payments via PayPal!</a>]]>
                     </comment>
diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json
index 25cc9d76acd768fe970363628abad60945e418d9..61f77a104c016d23f3734433efd8646bd21b42f4 100644
--- a/app/code/Magento/Persistent/composer.json
+++ b/app/code/Magento/Persistent/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-persistent",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-checkout": "100.2.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json
index a43a52209740318e0f5adcc8bea03a8860c04037..9c63c6958a465852ea3148cab659102880b07630 100644
--- a/app/code/Magento/ProductAlert/composer.json
+++ b/app/code/Magento/ProductAlert/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-product-alert",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
index f0edccbaf812acbf8495d97817515395635af409..7a087f769877160a316635baf9017b8b37ebbd38 100644
--- a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
+++ b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
@@ -6,6 +6,7 @@
 namespace Magento\ProductVideo\Controller\Adminhtml\Product\Gallery;
 
 use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\File\Uploader;
 
 /**
@@ -43,6 +44,13 @@ class RetrieveImage extends \Magento\Backend\App\Action
      */
     protected $fileUtility;
 
+    /**
+     * URI validator
+     *
+     * @var \Magento\Framework\Validator\ValidatorInterface
+     */
+    private $protocolValidator;
+
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory
@@ -51,6 +59,7 @@ class RetrieveImage extends \Magento\Backend\App\Action
      * @param \Magento\Framework\Image\AdapterFactory $imageAdapterFactory
      * @param \Magento\Framework\HTTP\Adapter\Curl $curl
      * @param \Magento\MediaStorage\Model\ResourceModel\File\Storage\File $fileUtility
+     * @param \Magento\Framework\Validator\ValidatorInterface $protocolValidator
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
@@ -59,7 +68,8 @@ class RetrieveImage extends \Magento\Backend\App\Action
         \Magento\Framework\Filesystem $fileSystem,
         \Magento\Framework\Image\AdapterFactory $imageAdapterFactory,
         \Magento\Framework\HTTP\Adapter\Curl $curl,
-        \Magento\MediaStorage\Model\ResourceModel\File\Storage\File $fileUtility
+        \Magento\MediaStorage\Model\ResourceModel\File\Storage\File $fileUtility,
+        \Magento\Framework\Validator\ValidatorInterface $protocolValidator = null
     ) {
         parent::__construct($context);
         $this->resultRawFactory = $resultRawFactory;
@@ -68,6 +78,10 @@ class RetrieveImage extends \Magento\Backend\App\Action
         $this->imageAdapter = $imageAdapterFactory->create();
         $this->curl = $curl;
         $this->fileUtility = $fileUtility;
+
+        $this->protocolValidator = $protocolValidator ?:
+            \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\Framework\Validator\ValidatorInterface::class);
     }
 
     /**
@@ -78,15 +92,15 @@ class RetrieveImage extends \Magento\Backend\App\Action
         $baseTmpMediaPath = $this->mediaConfig->getBaseTmpMediaPath();
         try {
             $remoteFileUrl = $this->getRequest()->getParam('remote_image');
-            $originalFileName = basename($remoteFileUrl);
-            $localFileName = Uploader::getCorrectFileName($originalFileName);
+            $this->validateRemoteFile($remoteFileUrl);
+            $localFileName = Uploader::getCorrectFileName(basename($remoteFileUrl));
             $localTmpFileName = Uploader::getDispretionPath($localFileName) . DIRECTORY_SEPARATOR . $localFileName;
-            $localFileMediaPath = $baseTmpMediaPath . ($localTmpFileName);
-            $localUniqueFileMediaPath = $this->appendNewFileName($localFileMediaPath);
-            $this->retrieveRemoteImage($remoteFileUrl, $localUniqueFileMediaPath);
-            $localFileFullPath = $this->appendAbsoluteFileSystemPath($localUniqueFileMediaPath);
+            $localFilePath = $baseTmpMediaPath . ($localTmpFileName);
+            $localUniqFilePath = $this->appendNewFileName($localFilePath);
+            $this->retrieveRemoteImage($remoteFileUrl, $localUniqFilePath);
+            $localFileFullPath = $this->appendAbsoluteFileSystemPath($localUniqFilePath);
             $this->imageAdapter->validateUploadFile($localFileFullPath);
-            $result = $this->appendResultSaveRemoteImage($localUniqueFileMediaPath);
+            $result = $this->appendResultSaveRemoteImage($localUniqFilePath);
         } catch (\Exception $e) {
             $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
         }
@@ -98,6 +112,25 @@ class RetrieveImage extends \Magento\Backend\App\Action
         return $response;
     }
 
+    /**
+     * Validate remote file
+     *
+     * @param string $remoteFileUrl
+     * @throws LocalizedException
+     *
+     * @return $this
+     */
+    private function validateRemoteFile($remoteFileUrl)
+    {
+        if (!$this->protocolValidator->isValid($remoteFileUrl)) {
+            throw new LocalizedException(
+                __("Protocol isn't allowed")
+            );
+        }
+
+        return $this;
+    }
+
     /**
      * @param string $fileName
      * @return mixed
@@ -116,6 +149,8 @@ class RetrieveImage extends \Magento\Backend\App\Action
     }
 
     /**
+     * Trying to get remote image to save it locally
+     *
      * @param string $fileUrl
      * @param string $localFilePath
      * @return void
@@ -127,7 +162,7 @@ class RetrieveImage extends \Magento\Backend\App\Action
         $this->curl->write('GET', $fileUrl);
         $image = $this->curl->read();
         if (empty($image)) {
-            throw new \Magento\Framework\Exception\LocalizedException(
+            throw new LocalizedException(
                 __('Could not get preview image information. Please check your connection and try again.')
             );
         }
diff --git a/app/code/Magento/ProductVideo/Test/Unit/Controller/Adminhtml/Product/Gallery/RetrieveImageTest.php b/app/code/Magento/ProductVideo/Test/Unit/Controller/Adminhtml/Product/Gallery/RetrieveImageTest.php
index 79d83f38421bba1a2e582efc3bc90f261c8b79dc..64149d529e5ca8f993e300594279a7e0842f9b8b 100644
--- a/app/code/Magento/ProductVideo/Test/Unit/Controller/Adminhtml/Product/Gallery/RetrieveImageTest.php
+++ b/app/code/Magento/ProductVideo/Test/Unit/Controller/Adminhtml/Product/Gallery/RetrieveImageTest.php
@@ -73,17 +73,11 @@ class RetrieveImageTest extends \PHPUnit_Framework_TestCase
      */
     protected function setUp()
     {
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->contextMock = $this->getMock(\Magento\Backend\App\Action\Context::class, [], [], '', false);
         $this->rawFactoryMock =
             $this->getMock(\Magento\Framework\Controller\Result\RawFactory::class, ['create'], [], '', false);
-        $response =
-            $this->getMock(
-                \Magento\Framework\Controller\Result\Raw::class,
-                [],
-                [],
-                '',
-                false
-            );
+        $response = new \Magento\Framework\DataObject();
         $this->rawFactoryMock->expects($this->once())->method('create')->willReturn($response);
         $this->configMock = $this->getMock(\Magento\Catalog\Model\Product\Media\Config::class, [], [], '', false);
         $this->filesystemMock = $this->getMock(\Magento\Framework\Filesystem::class, [], [], '', false);
@@ -101,11 +95,15 @@ class RetrieveImageTest extends \PHPUnit_Framework_TestCase
         $this->adapterFactoryMock->expects($this->once())->method('create')->willReturn($this->abstractAdapter);
         $this->curlMock = $this->getMock(\Magento\Framework\HTTP\Adapter\Curl::class, [], [], '', false);
         $this->storageFileMock =
-            $this->getMock(\Magento\MediaStorage\Model\ResourceModel\File\Storage\File::class, [], [], '', false);
+        $this->getMock(\Magento\MediaStorage\Model\ResourceModel\File\Storage\File::class, [], [], '', false);
         $this->request = $this->getMock(\Magento\Framework\App\RequestInterface::class);
         $this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->request));
-
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $managerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['get'])
+            ->getMockForAbstractClass();
+        $this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->request));
+        $this->contextMock->expects($this->any())->method('getObjectManager')->willReturn($managerMock);
 
         $this->image = $objectManager->getObject(
             \Magento\ProductVideo\Controller\Adminhtml\Product\Gallery\RetrieveImage::class,
@@ -117,6 +115,7 @@ class RetrieveImageTest extends \PHPUnit_Framework_TestCase
                 'imageAdapterFactory' => $this->adapterFactoryMock,
                 'curl' => $this->curlMock,
                 'fileUtility' => $this->storageFileMock,
+                'protocolValidator' => new \Magento\Framework\Validator\AllowedProtocols(),
             ]
         );
     }
diff --git a/app/code/Magento/ProductVideo/composer.json b/app/code/Magento/ProductVideo/composer.json
index 362fd006d2690c9f9b60b7be3abb71d5ce0b4da7..08d21e4c2abbfb167aed2ca24c0ba012d6b2e8c8 100644
--- a/app/code/Magento/ProductVideo/composer.json
+++ b/app/code/Magento/ProductVideo/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-product-video",
     "description": "Add Video to Products",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-backend": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/ProductVideo/etc/di.xml b/app/code/Magento/ProductVideo/etc/di.xml
index 09c15d8fccecc64d3dd183e7940aa26b6819d6df..7242a9d48ce1e3c0da66a3f4d5953cda705132cd 100644
--- a/app/code/Magento/ProductVideo/etc/di.xml
+++ b/app/code/Magento/ProductVideo/etc/di.xml
@@ -7,6 +7,7 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
     <preference for="Magento\Framework\Api\Data\VideoContentInterface" type="Magento\ProductVideo\Model\Product\Attribute\Media\VideoEntry" />
+    <preference for="Magento\Framework\Validator\ValidatorInterface" type="Magento\Framework\Validator\AllowedProtocols" />
     <type name="Magento\Catalog\Model\Product\Attribute\Backend\Media\EntryConverterPool">
         <arguments>
             <argument name="mediaGalleryEntryConvertersCollection" xsi:type="array">
diff --git a/app/code/Magento/ProductVideo/i18n/en_US.csv b/app/code/Magento/ProductVideo/i18n/en_US.csv
index 4cfabe1592dd2d0ce5c8072f0bdaafbc847689e6..64a08075c19548bc092f3918e7dabf606dd2052e 100644
--- a/app/code/Magento/ProductVideo/i18n/en_US.csv
+++ b/app/code/Magento/ProductVideo/i18n/en_US.csv
@@ -40,3 +40,4 @@ Delete,Delete
 "Show related video","Show related video"
 "Auto restart video","Auto restart video"
 "Images And Videos","Images And Videos"
+"Protocol isn't allowed", "Protocol isn't allowed"
diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json
index 79c3a1aaa9d907cea1c505ece12a22e4ee3986f2..76063b177d46c2eb93626dea77a346aaaeb5c21d 100644
--- a/app/code/Magento/Quote/composer.json
+++ b/app/code/Magento/Quote/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-quote",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json
index 0bb989cb54ac8cb84e3da943a231634b6707f256..9c76abd07b9b35276f1f923138c9dd47031c289d 100644
--- a/app/code/Magento/Reports/composer.json
+++ b/app/code/Magento/Reports/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-reports",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/RequireJs/composer.json b/app/code/Magento/RequireJs/composer.json
index 8c9fed33ab730dd2431b222b2edd04aa2252e12f..68428caa867bf7108fc466ebfd1fa2829a2b75fa 100644
--- a/app/code/Magento/RequireJs/composer.json
+++ b/app/code/Magento/RequireJs/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-require-js",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json
index 09f5529feabdd97512839be2dacd00f791083c3c..3ec82943476088c3aa307de1b5a934a3cac8ca0d 100644
--- a/app/code/Magento/Review/composer.json
+++ b/app/code/Magento/Review/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-review",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Review/view/frontend/templates/form.phtml b/app/code/Magento/Review/view/frontend/templates/form.phtml
index 7c89fd8740c5607ec83f0d0a4dda761de50d97ed..bcac1dbca059833749faf9db4d759f8a06a6f24a 100644
--- a/app/code/Magento/Review/view/frontend/templates/form.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/form.phtml
@@ -20,7 +20,7 @@
         <?php if ($block->getRatings() && $block->getRatings()->getSize()): ?>
         <span id="input-message-box"></span>
         <fieldset class="field required review-field-ratings">
-            <legend class="label"><span><?php echo $block->escapeHtml(__('Your Rating')) ?><span></legend><br/>
+            <legend class="label"><span><?php echo $block->escapeHtml(__('Your Rating')) ?></span></legend><br/>
             <div class="control">
                 <div class="nested" id="product-review-table">
                     <?php foreach ($block->getRatings() as $_rating): ?>
diff --git a/app/code/Magento/Rss/composer.json b/app/code/Magento/Rss/composer.json
index d35f0ee6ebecbf75af87566d776f172ab3d22c0d..fedd0ffeaacfe9577ea6e5971411540d4925fe4c 100644
--- a/app/code/Magento/Rss/composer.json
+++ b/app/code/Magento/Rss/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-rss",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/framework": "100.2.*",
diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json
index 95b8e6ffec2a682895b3459ca7bdcc7b4f001669..31ee3254d99b98a10ce9973e3a8a4adb1c5818da 100644
--- a/app/code/Magento/Rule/composer.json
+++ b/app/code/Magento/Rule/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-rule",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-eav": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json
index 09d1a9d6b7dd41ea95a09b26c0f72276327fe245..6b5638455a1c5986fb487f7f9c948d9ddf19aad3 100644
--- a/app/code/Magento/Sales/composer.json
+++ b/app/code/Magento/Sales/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sales",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml
index 775c7214c2f104771c79d5fd299229187595b167..20cfcdeadf22a0f18d81b262134058640c04877f 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml
@@ -38,10 +38,10 @@ $orderStoreDate = $block->formatDate(
             <div class="admin__page-section-item-title">
                 <span class="title">
                     <?php if ($block->getNoUseOrderLink()): ?>
-                        <?php /* @escapeNotVerified */ echo __('Order # %1', $_order->getRealOrderId()) ?> (<span><?php /* @escapeNotVerified */ echo $_email ?></span>)
+                        <?php /* @escapeNotVerified */ echo __('Order # %1', $_order->getRealOrderId()) ?> (<span><?php echo $block->escapeHtml($_email) ?></span>)
                     <?php else: ?>
                         <a href="<?php /* @escapeNotVerified */ echo $block->getViewUrl($_order->getId()) ?>"><?php /* @escapeNotVerified */ echo __('Order # %1', $_order->getRealOrderId()) ?></a>
-                        <span>(<?php /* @escapeNotVerified */ echo $_email ?>)</span>
+                        <span>(<?php echo $block->escapeHtml($_email) ?>)</span>
                     <?php endif; ?>
                 </span>
             </div>
@@ -49,7 +49,7 @@ $orderStoreDate = $block->formatDate(
                 <table class="admin__table-secondary order-information-table">
                 <tr>
                     <th><?php /* @escapeNotVerified */ echo __('Order Date') ?></th>
-                    <td><?php /* @escapeNotVerified */ echo $orderAdminDate ?></td>
+                    <td><?php echo $block->escapeHtml($orderAdminDate) ?></td>
                 </tr>
                 <?php if ($orderAdminDate != $orderStoreDate):?>
                     <tr>
@@ -57,12 +57,12 @@ $orderStoreDate = $block->formatDate(
                                 'Order Date (%1)',
                                 $block->getTimezoneForStore($_order->getStore())
                             ) ?></th>
-                        <td><?php /* @escapeNotVerified */ echo $orderStoreDate ?></td>
+                        <td><?php echo $block->escapeHtml($orderStoreDate) ?></td>
                     </tr>
                 <?php endif;?>
                 <tr>
                     <th><?php /* @escapeNotVerified */ echo __('Order Status') ?></th>
-                    <td><span id="order_status"><?php /* @escapeNotVerified */ echo $_order->getStatusLabel() ?></span></td>
+                    <td><span id="order_status"><?php echo $block->escapeHtml($_order->getStatusLabel()) ?></span></td>
                 </tr>
                 <?php echo $block->getChildHtml(); ?>
                 <?php if ($block->isSingleStoreMode() == false):?>
@@ -136,13 +136,13 @@ $orderStoreDate = $block->formatDate(
                     <?php if ($_groupName = $block->getCustomerGroupName()) : ?>
                         <tr>
                             <th><?php /* @escapeNotVerified */ echo __('Customer Group') ?></th>
-                            <td><?php /* @escapeNotVerified */ echo $_groupName ?></td>
+                            <td><?php echo $block->escapeHtml($_groupName) ?></td>
                         </tr>
                     <?php endif; ?>
                     <?php foreach ($block->getCustomerAccountData() as $data):?>
                         <tr>
-                            <th><?php /* @escapeNotVerified */ echo $data['label'] ?></th>
-                            <td><?php /* @escapeNotVerified */ echo $data['value'] ?></td>
+                            <th><?php echo $block->escapeHtml($data['label']) ?></th>
+                            <td><?php echo $block->escapeHtml($data['value']) ?></td>
                         </tr>
                     <?php endforeach;?>
                 </table>
diff --git a/app/code/Magento/SalesInventory/composer.json b/app/code/Magento/SalesInventory/composer.json
index ff72ce7f0022690682b356235c506512e65497b9..d7f9075cdd310141bab6b25869f33d6229f513dc 100644
--- a/app/code/Magento/SalesInventory/composer.json
+++ b/app/code/Magento/SalesInventory/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sales-inventory",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog-inventory": "100.2.*",
         "magento/module-sales": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
index 57477b5ce0623f57bfc048839cc8bdaee8d40593..efa45512acc8320cd878c97b92c5912c7713f882 100644
--- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
+++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
@@ -26,8 +26,13 @@ class Save extends \Magento\SalesRule\Controller\Adminhtml\Promo\Quote
                     ['request' => $this->getRequest()]
                 );
                 $data = $this->getRequest()->getPostValue();
+
+                $filterValues = ['from_date' => $this->_dateFilter];
+                if ($this->getRequest()->getParam('to_date')) {
+                    $filterValues['to_date'] = $this->_dateFilter;
+                }
                 $inputFilter = new \Zend_Filter_Input(
-                    ['from_date' => $this->_dateFilter, 'to_date' => $this->_dateFilter],
+                    $filterValues,
                     [],
                     $data
                 );
diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json
index fabef581762a84cac8844bf7e7099b0bb8b6b6c0..8479acad47246a1f91bc6b098d88cfa6f6027f76 100644
--- a/app/code/Magento/SalesRule/composer.json
+++ b/app/code/Magento/SalesRule/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sales-rule",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-rule": "100.2.*",
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js
index ed5744feb6ce84df31a5a59b42f520bb97316792..d1e294c9a8f0c1dc4edf82e52cbe509b09da8fbe 100644
--- a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js
@@ -17,16 +17,20 @@ define(
         'mage/storage',
         'Magento_Checkout/js/action/get-payment-information',
         'Magento_Checkout/js/model/totals',
-        'mage/translate'
+        'mage/translate',
+        'Magento_Checkout/js/model/full-screen-loader'
     ],
-    function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t) {
+    function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t,
+              fullScreenLoader) {
         'use strict';
 
-        return function (isApplied, isLoading) {
+        return function (isApplied) {
             var quoteId = quote.getQuoteId(),
                 url = urlManager.getCancelCouponUrl(quoteId),
                 message = $t('Your coupon was successfully removed.');
+
             messageContainer.clear();
+            fullScreenLoader.startLoader();
 
             return storage.delete(
                 url,
@@ -39,6 +43,7 @@ define(
                     $.when(deferred).done(function () {
                         isApplied(false);
                         totals.isLoading(false);
+                        fullScreenLoader.stopLoader();
                     });
                     messageContainer.addSuccessMessage({
                         'message': message
@@ -47,12 +52,9 @@ define(
             ).fail(
                 function (response) {
                     totals.isLoading(false);
+                    fullScreenLoader.stopLoader();
                     errorProcessor.process(response, messageContainer);
                 }
-            ).always(
-                function () {
-                    isLoading(false);
-                }
             );
         };
     }
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
index 606fe4013ea762c5460c49202907463d7c7952f2..a2b7ff19f2139ffa7e23b37eda039d5b9ccc32a8 100644
--- a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
@@ -18,25 +18,22 @@ define(
         'mage/storage',
         'mage/translate',
         'Magento_Checkout/js/action/get-payment-information',
-        'Magento_Checkout/js/model/totals'
+        'Magento_Checkout/js/model/totals',
+        'Magento_Checkout/js/model/full-screen-loader'
     ],
     function (
-        ko,
-        $,
-        quote,
-        urlManager,
-        errorProcessor,
-        messageContainer,
-        storage,
-        $t,
-        getPaymentInformationAction,
-        totals
+        ko, $, quote, urlManager, errorProcessor, messageContainer, storage, $t, getPaymentInformationAction, totals,
+        fullScreenLoader
     ) {
         'use strict';
-        return function (couponCode, isApplied, isLoading) {
-            var quoteId = quote.getQuoteId();
-            var url = urlManager.getApplyCouponUrl(couponCode, quoteId);
-            var message = $t('Your coupon was successfully applied.');
+
+        return function (couponCode, isApplied) {
+            var quoteId = quote.getQuoteId(),
+                url = urlManager.getApplyCouponUrl(couponCode, quoteId),
+                message = $t('Your coupon was successfully applied.');
+
+            fullScreenLoader.startLoader();
+
             return storage.put(
                 url,
                 {},
@@ -45,19 +42,22 @@ define(
                 function (response) {
                     if (response) {
                         var deferred = $.Deferred();
-                        isLoading(false);
+
                         isApplied(true);
                         totals.isLoading(true);
                         getPaymentInformationAction(deferred);
                         $.when(deferred).done(function () {
+                            fullScreenLoader.stopLoader();
                             totals.isLoading(false);
                         });
-                        messageContainer.addSuccessMessage({'message': message});
+                        messageContainer.addSuccessMessage({
+                            'message': message
+                        });
                     }
                 }
             ).fail(
                 function (response) {
-                    isLoading(false);
+                    fullScreenLoader.stopLoader();
                     totals.isLoading(false);
                     errorProcessor.process(response, messageContainer);
                 }
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js
index 8e8c0798ff3b59ce0ffa0a803242abe1d02fcee7..6dc973a7a1e4298469251f71f6e26f09a95cc5d0 100644
--- a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js
@@ -13,49 +13,53 @@ define(
     ],
     function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction) {
         'use strict';
-        var totals = quote.getTotals();
-        var couponCode = ko.observable(null);
+
+        var totals = quote.getTotals(),
+            couponCode = ko.observable(null),
+            isApplied = ko.observable(couponCode() != null);
+
         if (totals()) {
             couponCode(totals()['coupon_code']);
         }
-        var isApplied = ko.observable(couponCode() != null);
-        var isLoading = ko.observable(false);
+
         return Component.extend({
             defaults: {
                 template: 'Magento_SalesRule/payment/discount'
             },
             couponCode: couponCode,
+
             /**
              * Applied flag
              */
             isApplied: isApplied,
-            isLoading: isLoading,
+
             /**
              * Coupon code application procedure
              */
             apply: function() {
                 if (this.validate()) {
-                    isLoading(true);
-                    setCouponCodeAction(couponCode(), isApplied, isLoading);
+                    setCouponCodeAction(couponCode(), isApplied);
                 }
             },
+
             /**
              * Cancel using coupon
              */
             cancel: function() {
                 if (this.validate()) {
-                    isLoading(true);
                     couponCode('');
-                    cancelCouponAction(isApplied, isLoading);
+                    cancelCouponAction(isApplied);
                 }
             },
+
             /**
              * Coupon form validation
              *
-             * @returns {boolean}
+             * @returns {Boolean}
              */
-            validate: function() {
+            validate: function () {
                 var form = '#discount-form';
+
                 return $(form).validation() && $(form).validation('isValid');
             }
         });
diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html
index d6bc4c764d5714382d017adce856deaf84c8b3ff..4ba38906fe9c1e98c8d248574585cc01ef815914 100644
--- a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html
+++ b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html
@@ -15,7 +15,7 @@
         <!-- ko foreach: getRegion('messages') -->
         <!-- ko template: getTemplate() --><!-- /ko -->
         <!--/ko-->
-        <form class="form form-discount" id="discount-form" data-bind="blockLoader: isLoading">
+        <form class="form form-discount" id="discount-form">
             <div class="payment-option-inner">
                 <div class="field">
                     <label class="label" for="discount-code">
diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json
index eeda2be05e68f86cb5552e6f48ca502dd96cb9be..5b9efe61f72724e28d23c1af0dc197fede8e117f 100644
--- a/app/code/Magento/SalesSequence/composer.json
+++ b/app/code/Magento/SalesSequence/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sales-sequence",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
diff --git a/app/code/Magento/SampleData/composer.json b/app/code/Magento/SampleData/composer.json
index 936bbf0d6be3a7399babc2e835282e7c71bea4c2..4c98a5abd3a16ab72b5ea04e0606955986924ebd 100644
--- a/app/code/Magento/SampleData/composer.json
+++ b/app/code/Magento/SampleData/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sample-data",
     "description": "Sample Data fixtures",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "suggest": {
diff --git a/app/code/Magento/Search/composer.json b/app/code/Magento/Search/composer.json
index cc95e6784526f33bb65246b599a4147e8a1afa1d..8f809fb3b8af3533c4715aea1e13854650e0cbac 100644
--- a/app/code/Magento/Search/composer.json
+++ b/app/code/Magento/Search/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-search",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-catalog-search": "100.2.*",
diff --git a/app/code/Magento/Security/composer.json b/app/code/Magento/Security/composer.json
index f64c0f0b29d282b0feaefb24ebb3963086f0e083..4048b63bf607030d27ae7fa84dbec6a0da838957 100644
--- a/app/code/Magento/Security/composer.json
+++ b/app/code/Magento/Security/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-security",
     "description": "Security management module",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/framework": "100.2.*"
diff --git a/app/code/Magento/SendFriend/composer.json b/app/code/Magento/SendFriend/composer.json
index de9dbf7a84576022d8f6b1a38324f902565870df..1095dedc0ba6606107660d65373096d8c82b204c 100644
--- a/app/code/Magento/SendFriend/composer.json
+++ b/app/code/Magento/SendFriend/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-send-friend",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-customer": "100.2.*",
diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json
index dc9ea808c0f7b19e396a7c73f2b416221729a34b..03f51bbd95e0ff5f65b88e565cfbe77102a44760 100644
--- a/app/code/Magento/Shipping/composer.json
+++ b/app/code/Magento/Shipping/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-shipping",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-sales": "100.2.*",
diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json
index be553a4da194f4dbf64fb4237fd92bb27e4e17ff..9f556178fc2cccfd070c272a89164e438f1d33e8 100644
--- a/app/code/Magento/Sitemap/composer.json
+++ b/app/code/Magento/Sitemap/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-sitemap",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json
index a03aa6fee9e2d84134aa0b3bd63ded9c1e7f8bd3..1c74c46cdf89f3aaa0bf5efc3143556d610e518b 100644
--- a/app/code/Magento/Store/composer.json
+++ b/app/code/Magento/Store/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-store",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-directory": "100.2.*",
         "magento/module-ui": "100.2.*",
diff --git a/app/code/Magento/Swagger/composer.json b/app/code/Magento/Swagger/composer.json
index dc2d1cbee003de647cf72f7312ad7f7fcc222e3b..47e347426c83fdb1b969c5a03bd46d1776e89950 100644
--- a/app/code/Magento/Swagger/composer.json
+++ b/app/code/Magento/Swagger/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-swagger",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
diff --git a/app/code/Magento/Swatches/composer.json b/app/code/Magento/Swatches/composer.json
index f87fdb635cb73386b40fec6ac932eaee3f9cd398..b61ff41d8c955890aae0c22baedcdb8abd22e004 100644
--- a/app/code/Magento/Swatches/composer.json
+++ b/app/code/Magento/Swatches/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-swatches",
     "description": "Add Swatches to Products",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-configurable-product": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/SwatchesLayeredNavigation/composer.json b/app/code/Magento/SwatchesLayeredNavigation/composer.json
index 9b658d0a42e61e0b556f1aa5aed6e12ed8cfdbe7..67c6d90c51e7f81de645451da6553bcdb750fddd 100644
--- a/app/code/Magento/SwatchesLayeredNavigation/composer.json
+++ b/app/code/Magento/SwatchesLayeredNavigation/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-swatches-layered-navigation",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/magento-composer-installer": "*"
     },
diff --git a/app/code/Magento/Tax/composer.json b/app/code/Magento/Tax/composer.json
index 4553fdbb383323732b667df9be3e140aca011744..3dfacaaecd9635dec8229175de2876da6c957a77 100644
--- a/app/code/Magento/Tax/composer.json
+++ b/app/code/Magento/Tax/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-tax",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-config": "100.2.*",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/code/Magento/TaxImportExport/composer.json b/app/code/Magento/TaxImportExport/composer.json
index c3d09e4926e02d67a98c0e15c050d67997ae1ecd..9d9cac5dec59c94e8013bc5ab3275fee84c73b6b 100644
--- a/app/code/Magento/TaxImportExport/composer.json
+++ b/app/code/Magento/TaxImportExport/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-tax-import-export",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-tax": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-directory": "100.2.*",
diff --git a/app/code/Magento/Theme/composer.json b/app/code/Magento/Theme/composer.json
index 49382f9642fa5d2b88d7d2f4cea79c07d5306cb1..7158ac314076d38aae4766bbea1a917dc869b5dd 100644
--- a/app/code/Magento/Theme/composer.json
+++ b/app/code/Magento/Theme/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-theme",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-customer": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json
index 6359d5925149630694e5bf598a99ce09cfd08fed..6c6c5fad3e7b9abcab6211e1c2326f9a31054088 100644
--- a/app/code/Magento/Translation/composer.json
+++ b/app/code/Magento/Translation/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-translation",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/module-developer": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/Ui/README.md b/app/code/Magento/Ui/README.md
index 1337383ea3fb83bf3e2927589859587aad5a48f7..b7dd1a858e4a8161f836b3ea73d1483ae56ba2dd 100644
--- a/app/code/Magento/Ui/README.md
+++ b/app/code/Magento/Ui/README.md
@@ -1,7 +1,7 @@
 # Overview
 ## Purpose of module
 
-The Magento\Ui module introduces a set of common UI components, which could be easily used and configured via layout XML files.
+The Magento\Ui module introduces a set of common UI components, which could be used and configured via layout XML files.
 
 # Deployment
 ## System requirements
diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json
index 43c7b7fa3011fd7c6386fcde17eb45b6c5e02695..a3de6c6dfbdde7860dbb07503e0e6fe25e8b3dcf 100644
--- a/app/code/Magento/Ui/composer.json
+++ b/app/code/Magento/Ui/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-ui",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/framework": "100.2.*",
         "magento/module-eav": "100.2.*",
diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js
index de10c065d123bf773f9fba66135b2308a2abe3e9..518f09fa73ba6c6771654c7c9fc3f3ce07be79be 100644
--- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js
+++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js
@@ -52,13 +52,15 @@ define([
                 obj;
 
             if (this.recordData().length && !this.update) {
-                this.recordData.each(function (recordData) {
+                _.each(this.recordData(), function (recordData) {
                     obj = {};
                     obj[this.map[this.identificationProperty]] = recordData[this.identificationProperty];
                     insertData.push(obj);
                 }, this);
 
-                this.source.set(this.dataProvider, insertData);
+                if (insertData.length) {
+                    this.source.set(this.dataProvider, insertData);
+                }
             }
         },
 
@@ -178,7 +180,7 @@ define([
                 tmpObj = {};
 
             if (data.length !== this.relatedData.length) {
-                data.forEach(function (obj) {
+                _.each(data, function (obj) {
                     tmpObj[this.identificationDRProperty] = obj[this.identificationDRProperty];
 
                     if (!_.findWhere(this.relatedData, tmpObj)) {
@@ -193,7 +195,7 @@ define([
         /**
          * Processing insert data
          *
-         * @param {Array} data
+         * @param {Object} data
          */
         processingInsertData: function (data) {
             var changes,
diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js
index 16c102b8367f4b8762030057c4d249adb132693b..77d3a069ccef76bbcacad28459820b3359b025e7 100644
--- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js
+++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js
@@ -51,7 +51,12 @@ define([
 
             observable() && $(el).datepicker(
                 'setDate',
-                moment(observable(), utils.normalizeDate(config.options.dateFormat)).toDate()
+                moment(
+                    observable(),
+                    utils.normalizeDate(
+                        options.dateFormat + (options.showsTime ? ' ' + options.timeFormat : '')
+                    )
+                ).toDate()
             );
 
             $(el).blur();
diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html
index f3319a05525f2f55bc4ba43ec5ce9bc1e4e2c300..d1ec1d26df6c56dff099b09aa0eb83232687573e 100644
--- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html
+++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html
@@ -43,6 +43,7 @@
                             </div>
 
                             <button class="action-delete"
+                                    data-index="delete_button"
                                     type="button"
                                     title="'Delete'"
                                     click="function(){
diff --git a/app/code/Magento/Ups/composer.json b/app/code/Magento/Ups/composer.json
index ade4e738a68efe0499041830892bb6b61f5a3156..c20dd28ba88876a70c04ea49038b94f82d3d9b06 100644
--- a/app/code/Magento/Ups/composer.json
+++ b/app/code/Magento/Ups/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-ups",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-sales": "100.2.*",
diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json
index ac75ecdf61b8fd0531f2b14f76d2aec7d72581be..290ffc6731d89ce142e94c58616ca1a74c82c54b 100644
--- a/app/code/Magento/UrlRewrite/composer.json
+++ b/app/code/Magento/UrlRewrite/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-url-rewrite",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-catalog": "101.1.*",
         "magento/module-store": "100.2.*",
         "magento/framework": "100.2.*",
diff --git a/app/code/Magento/User/composer.json b/app/code/Magento/User/composer.json
index 755c47ac1147612e1e55b589e72afa705b39b0ce..4632e32bc17f90549f7271cadc5e1ef7ba08869e 100644
--- a/app/code/Magento/User/composer.json
+++ b/app/code/Magento/User/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-user",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-authorization": "100.2.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Usps/composer.json b/app/code/Magento/Usps/composer.json
index 5baccddf4884307f4ebdeed9199fedb00debf4bc..15e93d0bea4fb6d0e89f21f180b2c91486c8f5aa 100644
--- a/app/code/Magento/Usps/composer.json
+++ b/app/code/Magento/Usps/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-usps",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-shipping": "100.2.*",
         "magento/module-directory": "100.2.*",
diff --git a/app/code/Magento/Variable/composer.json b/app/code/Magento/Variable/composer.json
index 21f3ec1dd467f240c609d5931ffa5cbde8dc3e15..e4b06d0edb34ab25d4d1279fb463a4f630ee77e9 100644
--- a/app/code/Magento/Variable/composer.json
+++ b/app/code/Magento/Variable/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-variable",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-backend": "100.2.*",
         "magento/module-email": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/Vault/composer.json b/app/code/Magento/Vault/composer.json
index 74dd568e3b45ee4e3e7f9e235d3389191b7a93e4..b2edf040674d83f6335d407089201b46fe16ecce 100644
--- a/app/code/Magento/Vault/composer.json
+++ b/app/code/Magento/Vault/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-vault",
     "description": "",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*",
         "magento/module-sales": "100.2.*",
         "magento/module-store": "100.2.*",
diff --git a/app/code/Magento/Version/composer.json b/app/code/Magento/Version/composer.json
index 3a972432101154fa2c4f167473fc6f4d6aa113a0..4396f1fb2b3bf4e114dd2ab4dfbd37eb7c2ffd7e 100644
--- a/app/code/Magento/Version/composer.json
+++ b/app/code/Magento/Version/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-version",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
diff --git a/app/code/Magento/Webapi/composer.json b/app/code/Magento/Webapi/composer.json
index f2796df70a8fae522a34d0c94e079afd9f525f9c..6fc712722adddf10c16e4add70913a62c2ef2bc7 100644
--- a/app/code/Magento/Webapi/composer.json
+++ b/app/code/Magento/Webapi/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-webapi",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-authorization": "100.2.*",
         "magento/module-integration": "100.2.*",
diff --git a/app/code/Magento/WebapiSecurity/composer.json b/app/code/Magento/WebapiSecurity/composer.json
index 506975f1aa188d4f0d90f8d2f0484153998f2c39..0f4ef7b3dc8839518bcc2982e9975c53d99a6c1b 100644
--- a/app/code/Magento/WebapiSecurity/composer.json
+++ b/app/code/Magento/WebapiSecurity/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-webapi-security",
     "description": "WebapiSecurity module provides option to loosen security on some webapi resources.",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-webapi": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/app/code/Magento/Weee/composer.json b/app/code/Magento/Weee/composer.json
index 035d66e5a96b416f1f5e3140ef9e45e299c1b52a..70fd4a25d0310d94d4254a8079755eab01ad610f 100644
--- a/app/code/Magento/Weee/composer.json
+++ b/app/code/Magento/Weee/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-weee",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-catalog": "101.1.*",
         "magento/module-tax": "100.2.*",
diff --git a/app/code/Magento/Widget/composer.json b/app/code/Magento/Widget/composer.json
index f59c4180eb2bb56522ae20f3615da92dd0c60370..b5a5e9e5569e3c62641cfc2d3cbc34030229020b 100644
--- a/app/code/Magento/Widget/composer.json
+++ b/app/code/Magento/Widget/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-widget",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-cms": "101.1.*",
         "magento/module-backend": "100.2.*",
diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php
index 6d8e4bcd2fd1c41844cd4398043b61dec4ff36ff..be995258794cc05f1fca4a2124cac04e8c0e1c87 100644
--- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php
+++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php
@@ -21,15 +21,12 @@ class ConfigurableProduct extends FinalPrice implements ConfiguredPriceInterface
      */
     public function getValue()
     {
-        $result = 0.;
         /** @var \Magento\Wishlist\Model\Item\Option $customOption */
         $customOption = $this->getProduct()->getCustomOption('simple_product');
-        if ($customOption) {
-            /** @var \Magento\Framework\Pricing\PriceInfoInterface $priceInfo */
-            $priceInfo = $customOption->getProduct()->getPriceInfo();
-            $result = $priceInfo->getPrice(self::PRICE_CODE)->getValue();
-        }
-        return max(0, $result);
+        $product = $customOption ? $customOption->getProduct() : $this->getProduct();
+        $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue();
+
+        return max(0, $price);
     }
 
     /**
diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php
index 9e05a578080efbd7ec91f49babfbbafc447e330d..ee4841ef79f2e6e31545f12e44fe49073166a8e3 100644
--- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php
+++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php
@@ -5,36 +5,30 @@
  */
 namespace Magento\Wishlist\Test\Unit\Pricing\ConfiguredPrice;
 
-use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
-use Magento\Framework\Pricing\PriceCurrencyInterface;
-use Magento\Framework\Pricing\PriceInfoInterface;
-use Magento\Framework\Pricing\SaleableInterface;
-use Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct;
-
 class ConfigurableProductTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var SaleableInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Pricing\SaleableInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     private $saleableItem;
 
     /**
-     * @var CalculatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Pricing\Adjustment\CalculatorInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     private $calculator;
 
     /**
-     * @var PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     private $priceCurrency;
 
     /**
-     * @var ConfigurableProduct
+     * @var \Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct
      */
     private $model;
 
     /**
-     * @var PriceInfoInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Pricing\PriceInfoInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     private $priceInfoMock;
 
@@ -49,9 +43,6 @@ class ConfigurableProductTest extends \PHPUnit_Framework_TestCase
                 'getCustomOption',
             ])
             ->getMockForAbstractClass();
-        $this->saleableItem->expects($this->once())
-            ->method('getPriceInfo')
-            ->willReturn($this->priceInfoMock);
 
         $this->calculator = $this->getMockBuilder(\Magento\Framework\Pricing\Adjustment\CalculatorInterface::class)
             ->getMockForAbstractClass();
@@ -59,7 +50,7 @@ class ConfigurableProductTest extends \PHPUnit_Framework_TestCase
         $this->priceCurrency = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
             ->getMockForAbstractClass();
 
-        $this->model = new ConfigurableProduct(
+        $this->model = new \Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct(
             $this->saleableItem,
             null,
             $this->calculator,
@@ -82,7 +73,7 @@ class ConfigurableProductTest extends \PHPUnit_Framework_TestCase
             ->getMock();
         $this->priceInfoMock->expects($this->once())
             ->method('getPrice')
-            ->with(ConfigurableProduct::PRICE_CODE)
+            ->with(\Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct::PRICE_CODE)
             ->willReturn($priceMock);
 
         $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
@@ -109,11 +100,28 @@ class ConfigurableProductTest extends \PHPUnit_Framework_TestCase
 
     public function testGetValueWithNoCustomOption()
     {
+        $priceValue = 100;
+
+        $priceMock = $this->getMockBuilder(\Magento\Framework\Pricing\Price\PriceInterface::class)
+            ->getMockForAbstractClass();
+        $priceMock->expects($this->once())
+            ->method('getValue')
+            ->willReturn($priceValue);
+
         $this->saleableItem->expects($this->once())
             ->method('getCustomOption')
             ->with('simple_product')
             ->willReturn(null);
 
-        $this->assertEquals(0, $this->model->getValue());
+        $this->saleableItem->expects($this->once())
+            ->method('getPriceInfo')
+            ->willReturn($this->priceInfoMock);
+
+        $this->priceInfoMock->expects($this->once())
+            ->method('getPrice')
+            ->with(\Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct::PRICE_CODE)
+            ->willReturn($priceMock);
+
+        $this->assertEquals(100, $this->model->getValue());
     }
 }
diff --git a/app/code/Magento/Wishlist/composer.json b/app/code/Magento/Wishlist/composer.json
index 3faee8912493c96092f70d7fc3ca0e77164b39bc..b341edde760b0761872aecc488216faa37392c22 100644
--- a/app/code/Magento/Wishlist/composer.json
+++ b/app/code/Magento/Wishlist/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/module-wishlist",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/module-store": "100.2.*",
         "magento/module-customer": "100.2.*",
         "magento/module-catalog": "101.1.*",
diff --git a/app/design/adminhtml/Magento/backend/composer.json b/app/design/adminhtml/Magento/backend/composer.json
index 29569db622d2ccc9fad9e9b87b3ad4f7ae4757d2..ff0eda055bba6a9e9899d66839216c14bbdbe02e 100644
--- a/app/design/adminhtml/Magento/backend/composer.json
+++ b/app/design/adminhtml/Magento/backend/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/theme-adminhtml-backend",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-theme",
diff --git a/app/design/frontend/Magento/blank/composer.json b/app/design/frontend/Magento/blank/composer.json
index 27ed40860dd5b065dc51e82f487722eb519ba215..7c03167ebc23278eaab5a72cddd381de7cd5afcc 100644
--- a/app/design/frontend/Magento/blank/composer.json
+++ b/app/design/frontend/Magento/blank/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/theme-frontend-blank",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "100.2.*"
     },
     "type": "magento2-theme",
diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml
index 3a92ad0a6741040e0adb3fc25e00948520cfa565..6c53a8613f09ca1f91c9e024b8e2cec723f0b309 100644
--- a/app/design/frontend/Magento/blank/etc/view.xml
+++ b/app/design/frontend/Magento/blank/etc/view.xml
@@ -227,7 +227,7 @@
                 </var>
                 <var name="options">
                     <var name="options">
-                        <var name="navigation">dots</var>
+                        <var name="nav">dots</var>
                     </var>
                 </var>
             </var>
diff --git a/app/design/frontend/Magento/luma/composer.json b/app/design/frontend/Magento/luma/composer.json
index 98fe0ebf8061c23fa37d30a9551f05d5c41bce1b..97eb48f3c7e9efe028eae034757a6a17c4d98bd0 100644
--- a/app/design/frontend/Magento/luma/composer.json
+++ b/app/design/frontend/Magento/luma/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/theme-frontend-luma",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/theme-frontend-blank": "100.2.*",
         "magento/framework": "100.2.*"
     },
diff --git a/composer.json b/composer.json
index fed4465140724cef3c24cd7facdd2ec5ceeba5b6..f9e49415d6ad3aff6976144df442861909155d2d 100644
--- a/composer.json
+++ b/composer.json
@@ -8,7 +8,7 @@
         "AFL-3.0"
     ],
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "zendframework/zend-stdlib": "~2.4.6",
         "zendframework/zend-code": "~2.4.6",
         "zendframework/zend-server": "~2.4.6",
diff --git a/composer.lock b/composer.lock
index 7feb568d766d012e009c59a50226f3ea8bd7b74a..02f0e31a325638840641667cac1c6783cf381e87 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "c23e80be1cc71ab108ce5ac19b3fe509",
-    "content-hash": "5b9734c1bdbda68cf20507525cafa0f2",
+    "hash": "1f34dce6d48c9e4e694c27e001414000",
+    "content-hash": "600aca1692cf3fe5c2ea1cbf66de09ab",
     "packages": [
         {
             "name": "braintree/braintree_php",
@@ -56,7 +56,7 @@
         },
         {
             "name": "colinmollenhour/cache-backend-file",
-            "version": "1.4",
+            "version": "1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_File.git",
@@ -818,16 +818,16 @@
         },
         {
             "name": "paragonie/random_compat",
-            "version": "v2.0.2",
+            "version": "v2.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/random_compat.git",
-                "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf"
+                "reference": "c0125896dbb151380ab47e96c621741e79623beb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf",
-                "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c0125896dbb151380ab47e96c621741e79623beb",
+                "reference": "c0125896dbb151380ab47e96c621741e79623beb",
                 "shasum": ""
             },
             "require": {
@@ -862,7 +862,7 @@
                 "pseudorandom",
                 "random"
             ],
-            "time": "2016-04-03 06:00:07"
+            "time": "2016-10-17 15:23:22"
         },
         {
             "name": "pelago/emogrifier",
@@ -922,16 +922,16 @@
         },
         {
             "name": "phpseclib/phpseclib",
-            "version": "2.0.3",
+            "version": "2.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpseclib/phpseclib.git",
-                "reference": "41f85e9c2582b3f6d1b7d20395fb40c687ad5370"
+                "reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/41f85e9c2582b3f6d1b7d20395fb40c687ad5370",
-                "reference": "41f85e9c2582b3f6d1b7d20395fb40c687ad5370",
+                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
+                "reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
                 "shasum": ""
             },
             "require": {
@@ -1010,20 +1010,20 @@
                 "x.509",
                 "x509"
             ],
-            "time": "2016-08-18 18:49:14"
+            "time": "2016-10-04 00:57:04"
         },
         {
             "name": "psr/log",
-            "version": "1.0.1",
+            "version": "1.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-fig/log.git",
-                "reference": "5277094ed527a1c4477177d102fe4c53551953e0"
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0",
-                "reference": "5277094ed527a1c4477177d102fe4c53551953e0",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
                 "shasum": ""
             },
             "require": {
@@ -1057,7 +1057,7 @@
                 "psr",
                 "psr-3"
             ],
-            "time": "2016-09-19 16:02:08"
+            "time": "2016-10-10 12:19:37"
         },
         {
             "name": "ramsey/uuid",
@@ -1390,7 +1390,7 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
@@ -1450,7 +1450,7 @@
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
@@ -1499,16 +1499,16 @@
         },
         {
             "name": "symfony/finder",
-            "version": "v3.1.4",
+            "version": "v3.1.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577"
+                "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/e568ef1784f447a0e54dcb6f6de30b9747b0f577",
-                "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
+                "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
                 "shasum": ""
             },
             "require": {
@@ -1544,20 +1544,20 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2016-08-26 12:04:02"
+            "time": "2016-09-28 00:11:12"
         },
         {
             "name": "symfony/process",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "05a03ed27073638658cab9405d99a67dd1014987"
+                "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/05a03ed27073638658cab9405d99a67dd1014987",
-                "reference": "05a03ed27073638658cab9405d99a67dd1014987",
+                "url": "https://api.github.com/repos/symfony/process/zipball/024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
+                "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
                 "shasum": ""
             },
             "require": {
@@ -1593,7 +1593,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-06 10:55:00"
+            "time": "2016-09-29 14:03:54"
         },
         {
             "name": "tedivm/jshrink",
@@ -4329,16 +4329,16 @@
         },
         {
             "name": "symfony/config",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "005bf10c156335ede2e89fb9a9ee10a0b742bc84"
+                "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/005bf10c156335ede2e89fb9a9ee10a0b742bc84",
-                "reference": "005bf10c156335ede2e89fb9a9ee10a0b742bc84",
+                "url": "https://api.github.com/repos/symfony/config/zipball/f8b1922bbda9d2ac86aecd649399040bce849fde",
+                "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde",
                 "shasum": ""
             },
             "require": {
@@ -4378,20 +4378,20 @@
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2016-08-16 14:56:08"
+            "time": "2016-09-14 20:31:12"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "0a732a9cafc30e54077967da4d019e1d618a8cb9"
+                "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0a732a9cafc30e54077967da4d019e1d618a8cb9",
-                "reference": "0a732a9cafc30e54077967da4d019e1d618a8cb9",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ee9ec9ac2b046462d341e9de7c4346142d335e75",
+                "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75",
                 "shasum": ""
             },
             "require": {
@@ -4441,11 +4441,11 @@
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-06 23:19:39"
+            "time": "2016-09-24 09:47:20"
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v3.1.4",
+            "version": "v3.1.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git",
@@ -4494,7 +4494,7 @@
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.8.11",
+            "version": "v2.8.12",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
@@ -4590,7 +4590,7 @@
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "lib-libxml": "*",
         "ext-ctype": "*",
         "ext-gd": "*",
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/composer.json b/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/composer.json
index 629afd442a46e7549206c1520b1b6c75f024dcb1..00888c7baf74990c6ba4d98ba6569c210ba08c7e 100644
--- a/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/composer.json
+++ b/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/composer.json
@@ -2,7 +2,7 @@
   "name": "magento/module-test-module-integration-from-config",
   "description": "test integration create from config",
   "require": {
-    "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+    "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
     "magento/framework": "0.42.0-beta8",
     "magento/module-integration": "0.42.0-beta8"
   },
@@ -16,4 +16,4 @@
       ]
     ]
   }
-}
\ No newline at end of file
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/composer.json b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/composer.json
index 1e2d9c0fa13dd80fcfe69374a7e02700f6b570ea..a9aa5a2ede89ce314a1f2257bc70c6b20b3bb2a0 100644
--- a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/composer.json
+++ b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/composer.json
@@ -2,7 +2,7 @@
   "name": "magento/module-test-join-directives",
   "description": "test integration for join directives",
   "require": {
-    "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+    "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
     "magento/framework": "0.42.0-beta8",
     "magento/module-sales": "0.42.0-beta8"
   },
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
index 4191ec1faa959aa1203ee45850c298f1d43bb988..cd02c6d4d7500ef9adf7d17ac9f866bfc8ef0711 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
@@ -713,6 +713,18 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
 
         $this->assertNotNull($response['items'][0]['sku']);
         $this->assertEquals('simple', $response['items'][0]['sku']);
+
+        $index = null;
+        foreach ($response['items'][0]['custom_attributes'] as $key => $customAttribute) {
+            if ($customAttribute['attribute_code'] == 'category_ids') {
+                $index = $key;
+                break;
+            }
+        }
+        $this->assertNotNull($index, 'Category information wasn\'t set');
+
+        $expectedResult = (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ? ['string' => '2'] : ['2'];
+        $this->assertEquals($expectedResult, $response['items'][0]['custom_attributes'][$index]['value']);
     }
 
     /**
diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php
index e4129a0739912c05dbb8546beab7f028945ad5f6..1a06be978d34c897f10aadd32e7f3e1720b1983b 100644
--- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php
@@ -6,12 +6,33 @@
  */
 namespace Magento\ConfigurableProduct\Api;
 
+use Magento\Eav\Model\AttributeRepository;
+
 class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
 {
     const SERVICE_NAME = 'configurableProductLinkManagementV1';
     const SERVICE_VERSION = 'V1';
     const RESOURCE_PATH = '/V1/configurable-products';
 
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * @var AttributeRepository
+     */
+    protected $attributeRepository;
+
+    /**
+     * Execute per test initialization
+     */
+    public function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->attributeRepository = $this->objectManager->get(\Magento\Eav\Model\AttributeRepository::class);
+    }
+
     /**
      * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
      */
@@ -40,14 +61,76 @@ class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
     }
 
     /**
-     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_simple_77.php
      * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_simple_77.php
      * @magentoApiDataFixture Magento/ConfigurableProduct/_files/delete_association.php
      */
     public function testAddChild()
     {
         $productSku = 'configurable';
         $childSku = 'simple_77';
+        $res = $this->addChild($productSku, $childSku);
+        $this->assertTrue($res);
+    }
+
+    /**
+     * Test the full flow of creating a configurable product and adding a child via REST
+     *
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php
+     */
+    public function testAddChildFullRestCreation()
+    {
+        $productSku = 'configurable-product-sku';
+        $childSku = 'simple-product-sku';
+
+        $this->createConfigurableProduct($productSku);
+        $attribute = $this->attributeRepository->get('catalog_product', 'test_configurable');
+        $attributeValue = $attribute->getOptions()[1]->getValue();
+        $this->addOptionToConfigurableProduct($productSku, $attribute->getAttributeId(), $attributeValue);
+        $this->createSimpleProduct($childSku, $attributeValue);
+        $res = $this->addChild($productSku, $childSku);
+        $this->assertTrue($res);
+
+        // confirm that the simple product was added
+        $children = $this->getChildren($productSku);
+        $added = false;
+        foreach ($children as $child) {
+            if ($child['sku'] == $childSku) {
+                $added = true;
+                break;
+            }
+        }
+        $this->assertTrue($added);
+
+        // clean up products
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku,
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE
+            ],
+            'soap' => [
+                'service' => 'catalogProductRepositoryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogProductRepositoryV1DeleteById',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, ['sku' => $productSku]);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $childSku,
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE
+            ],
+            'soap' => [
+                'service' => 'catalogProductRepositoryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogProductRepositoryV1DeleteById',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, ['sku' => $childSku]);
+    }
+
+    private function addChild($productSku, $childSku)
+    {
         $serviceInfo = [
             'rest' => [
                 'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/child',
@@ -59,8 +142,90 @@ class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
                 'operation' => self::SERVICE_NAME . 'AddChild'
             ]
         ];
-        $res = $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'childSku' => $childSku]);
-        $this->assertTrue($res);
+        return $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'childSku' => $childSku]);
+    }
+
+    protected function createConfigurableProduct($productSku)
+    {
+        $requestData = [
+            'product' => [
+                'sku' => $productSku,
+                'name' => 'configurable-product-' . $productSku,
+                'type_id' => 'configurable',
+                'price' => 50,
+                'attribute_set_id' => 4
+            ]
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => 'catalogProductRepositoryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogProductRepositoryV1Save',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    protected function addOptionToConfigurableProduct($productSku, $attributeId, $attributeValue)
+    {
+        $requestData = [
+            'sku' => $productSku,
+            'option' => [
+                'attribute_id' => $attributeId,
+                'label' => 'test_configurable',
+                'position' => 0,
+                'is_use_default' => true,
+                'values' => [
+                    ['value_index' => $attributeValue],
+                ]
+            ]
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/configurable-products/'. $productSku .'/options',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'configurableProductOptionRepositoryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'configurableProductOptionRepositoryV1Save',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    protected function createSimpleProduct($sku, $attributeValue)
+    {
+        $requestData = [
+            'product' => [
+                'sku' => $sku,
+                'name' => 'simple-product-' . $sku,
+                'type_id' => 'simple',
+                'attribute_set_id' => 4,
+                'price' => 3.62,
+                'status' => 1,
+                'visibility' => 4,
+                'custom_attributes' => [
+                    ['attribute_code' => 'test_configurable', 'value' => $attributeValue],
+                ]
+            ]
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'catalogProductRepositoryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogProductRepositoryV1Save',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, $requestData);
     }
 
     /**
@@ -93,7 +258,7 @@ class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
 
     /**
      * @param string $productSku
-     * @return string
+     * @return string[]
      */
     protected function getChildren($productSku)
     {
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index 512c5bc8d5df666ced655806af0da64952d0f4ef..cef145167860c8ebad9695d870b6cc73580e47f3 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,7 +1,7 @@
 {
     "require": {
         "magento/mtf": "1.0.0-rc48",
-        "php": "~5.6.0|7.0.2|~7.0.6",
+        "php": "~5.6.5|7.0.2|~7.0.6",
         "phpunit/phpunit": "~4.8.0|~5.5.0",
         "phpunit/phpunit-selenium": ">=1.2"
     },
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Template.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Template.php
index 29361ced38bcc6b4ba344e2191f3c963eb92576d..fb22754faf483aa32b97d3e1672aeb17d58bec26 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Template.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Template.php
@@ -19,7 +19,7 @@ class Template extends Block
      *
      * @var string
      */
-    protected $spinner = '[data-role="spinner"]';
+    protected $spinner = '#container [data-role="spinner"]';
 
     /**
      * Magento loader.
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml
index 23fc729edb99f9645f7587d8e350464c81083fcd..f8ffa51982f1fae4d34a6290e1bebce28ba85712 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml
@@ -30,5 +30,25 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
         </variation>
+        <variation name="OnePageCheckoutWithDiscountTestVariation2" summary="Checkout with 100% discount and free shipping if Braintree through PayPal is enabled" ticketId="MAGETWO-59940">
+            <data name="description" xsi:type="string">Use saved for Braintree credit card on checkout</data>
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="salesRule" xsi:type="string">active_sales_rule_with_fixed_price_discount_coupon</data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="checkoutMethod" xsi:type="string">login</data>
+            <data name="shipping/shipping_service" xsi:type="string">Free Shipping</data>
+            <data name="shipping/shipping_method" xsi:type="string">Free</data>
+            <data name="payment/method" xsi:type="string">free</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">0.00</item>
+            </data>
+            <data name="configData" xsi:type="string">braintree, braintree_use_vault, freeshipping</data>
+            <data name="status" xsi:type="string">Pending</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Section/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Section/Bundle.php
index e94ec38d010f3d519e8ab2e06c5fdd21dccd544c..5cf84cf6764270708bd30327f2596253f510370d 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Section/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Section/Bundle.php
@@ -8,7 +8,6 @@ namespace Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Section;
 
 use Magento\Mtf\Client\Element\SimpleElement;
 use Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Section\Bundle\Option;
-use Magento\Mtf\Client\Element;
 use Magento\Mtf\Client\ElementInterface;
 use Magento\Mtf\Client\Locator;
 use Magento\Ui\Test\Block\Adminhtml\Section;
@@ -53,6 +52,13 @@ class Bundle extends Section
      */
     protected $bundleOptionRow = './tr[%d]';
 
+    /**
+     * Selector for trash can button in bundle option row.
+     *
+     * @var string
+     */
+    protected $deleteOption = './tr[%d]//*[@data-index="delete_button"]';
+
     /**
      * Get bundle options block.
      *
@@ -83,17 +89,49 @@ class Bundle extends Section
         if (!isset($fields['bundle_selections'])) {
             return $this;
         }
+
+        $context = $this->_rootElement->find($this->bundleOptions, Locator::SELECTOR_XPATH);
+
+        if (isset($fields['bundle_selections']['value']['bundle_options'])) {
+            foreach ($fields['bundle_selections']['value']['bundle_options'] as $key => $bundleOption) {
+                $count = $key + 1;
+                $itemOption = $context->find(sprintf($this->openOption, $count), Locator::SELECTOR_XPATH);
+                $isContent = $context->find(sprintf($this->optionContent, $count), Locator::SELECTOR_XPATH)
+                    ->isVisible();
+                if ($itemOption->isVisible() && !$isContent) {
+                    $itemOption->click();
+                } elseif (!$itemOption->isVisible()) {
+                    $this->_rootElement->find($this->addNewOption)->click();
+                }
+                $this->getBundleOptionBlock($count, $context)->fillOption($bundleOption);
+            }
+        }
+
+        if (isset($fields['bundle_selections']['value']['bundle_options_delete'])) {
+            $this->deleteFieldsData($fields['bundle_selections']['value']['bundle_options_delete']);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Delete some bundle options.
+     *
+     * @param array $fields
+     * @return $this
+     */
+    public function deleteFieldsData(array $fields)
+    {
         $context = $this->_rootElement->find($this->bundleOptions, Locator::SELECTOR_XPATH);
-        foreach ($fields['bundle_selections']['value']['bundle_options'] as $key => $bundleOption) {
-            $count = $key + 1;
-            $itemOption = $context->find(sprintf($this->openOption, $count), Locator::SELECTOR_XPATH);
-            $isContent = $context->find(sprintf($this->optionContent, $count), Locator::SELECTOR_XPATH)->isVisible();
-            if ($itemOption->isVisible() && !$isContent) {
-                $itemOption->click();
-            } elseif (!$itemOption->isVisible()) {
-                $this->_rootElement->find($this->addNewOption)->click();
+        foreach (array_keys($fields) as $key) {
+            $bundleOptionIndex = $key + 1;
+            $deleteOption = $context->find(
+                sprintf($this->deleteOption, $bundleOptionIndex),
+                Locator::SELECTOR_XPATH
+            );
+            if ($deleteOption->isVisible()) {
+                $deleteOption->click();
             }
-            $this->getBundleOptionBlock($count, $context)->fillOption($bundleOption);
         }
         return $this;
     }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionsDeleted.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionsDeleted.php
new file mode 100644
index 0000000000000000000000000000000000000000..69e694abd261ab4ca4e4102f542b72f612552d5b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionsDeleted.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Magento\Bundle\Test\Fixture\BundleProduct;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Fixture\FixtureInterface;
+
+/**
+ * Assert bundle product form.
+ */
+class AssertBundleOptionsDeleted extends AbstractConstraint
+{
+    /**
+     * Assert that displayed price view for bundle product on product page equals passed from fixture.
+     * @param BundleProduct $product
+     * @param BundleProduct $originalProduct
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        BundleProduct $product,
+        BundleProduct $originalProduct,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku()];
+        $productGrid->open();
+        $productGrid->getProductGrid()->searchAndOpen($filter);
+
+        $productData = $product->getData()['bundle_selections']['bundle_options'];
+        $originalProductData = $originalProduct->getData()['bundle_selections']['bundle_options'];
+        $formData = $productPage->getProductForm()->getData($product)['bundle_selections'];
+
+        $productDataLength = count($productData);
+        $formDataLength = count($productData);
+        \PHPUnit_Framework_Assert::assertEquals($productDataLength, $formDataLength);
+
+        foreach ($productData as $index => $option) {
+            $productAssociatedDataLength = count($option['assigned_products']);
+            $formAssociatedDataLength = count($formData[$index]['assigned_products']);
+            \PHPUnit_Framework_Assert::assertEquals($productAssociatedDataLength, $formAssociatedDataLength);
+
+            foreach ($option['assigned_products'] as $productIndex => $associatedProduct) {
+                $associatedProduct['data']['getProductName'] =
+                    $originalProductData[$index+1]['assigned_products'][$productIndex]['search_data']['name'];
+                $associatedProduct = $associatedProduct['data'];
+                $errorAssociatedProducts = array_diff(
+                    $associatedProduct,
+                    $formData[$index]['assigned_products'][$productIndex]
+                );
+                \PHPUnit_Framework_Assert::assertCount(0, $errorAssociatedProducts);
+            }
+
+            unset($option['assigned_products']);
+            unset($formData[$index]['assigned_products']);
+            $errorFields = array_diff($option, $formData[$index]);
+            \PHPUnit_Framework_Assert::assertCount(0, $errorFields);
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Bundle options were not deleted correctly. There is difference with expected options';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
index 2b5e9a437b32bdec615fd9e2a928b3784ba68fb4..6a507a7a99b437a793b4096f8f10d9e33ccb825a 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
@@ -225,5 +225,27 @@
                 <item name="dataset" xsi:type="string">bundle_fixed_100_dollar</item>
             </field>
         </dataset>
+
+        <dataset name="with_3_bundle_options">
+            <field name="name" xsi:type="string">Bundle with 3 options %isolation%</field>
+            <field name="url_key" xsi:type="string">with_3_bundle_options-%isolation%</field>
+            <field name="sku" xsi:type="string">sku_with_3_bundle_options_%isolation%</field>
+            <field name="sku_type" xsi:type="string">No</field>
+            <field name="price_type" xsi:type="string">No</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">100</item>
+            </field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="bundle_selections" xsi:type="array">
+                <item name="dataset" xsi:type="string">with_3_options</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
index 3e9b055c48ca5a1bfa5df3410ec48ef708a71fa7..7131aab3cffcbb69ca84f1078540a2dbada2ae28 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
@@ -665,5 +665,170 @@
                 </item>
             </field>
         </dataset>
+
+        <dataset name="with_3_options">
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 1</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">No</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">1</item>
+                                <item name="selection_price_value" xsi:type="string">1</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 2</item>
+                    <item name="type" xsi:type="string">Radio Buttons</item>
+                    <item name="required" xsi:type="string">No</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">20</item>
+                                <item name="selection_price_value" xsi:type="string">20</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                        <item name="1" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">21</item>
+                                <item name="selection_price_value" xsi:type="string">21</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                        <item name="2" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">22</item>
+                                <item name="selection_price_value" xsi:type="string">22</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+                <item name="2" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 3</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">No</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">3</item>
+                                <item name="selection_price_value" xsi:type="string">3</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                    <item name="1" xsi:type="string">catalogProductSimple::product_100_dollar</item>
+                    <item name="2" xsi:type="string">catalogProductSimple::product_without_category</item>
+                </item>
+                <item name="2" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="with_3_options_delete">
+            <field name="bundle_options_delete" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 1</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">No</item>
+                </item>
+            </field>
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 2</item>
+                    <item name="type" xsi:type="string">Radio Buttons</item>
+                    <item name="required" xsi:type="string">No</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">20</item>
+                                <item name="selection_price_value" xsi:type="string">20</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                        <item name="1" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">21</item>
+                                <item name="selection_price_value" xsi:type="string">21</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                        <item name="2" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">22</item>
+                                <item name="selection_price_value" xsi:type="string">22</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="title" xsi:type="string">Option 3</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">No</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">3</item>
+                                <item name="selection_price_value" xsi:type="string">3</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                    <item name="1" xsi:type="string">catalogProductSimple::product_100_dollar</item>
+                    <item name="2" xsi:type="string">catalogProductSimple::product_without_category</item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                </item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c17360200f44f2fe8875590578c6960ea7757d0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Bundle\Test\TestCase;
+
+use Magento\Bundle\Test\Fixture\BundleProduct;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Test Flow:
+ * 1. Login as admin
+ * 2. Navigate to the Products>Inventory>Catalog
+ * 3. Click on Bundle product in the grid to edit it
+ * 4. Fill in some Bundle Options data according to data set
+ * 5. Delete some Bundle Options data according to data set
+ * 6. Save product
+ * 7. Verify Bundle Options in the updated product
+ *
+ * @group Bundle_Product
+ * @ZephyrId MAGETWO-26195
+ */
+class UpdateBundleOptionsTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Page product on backend
+     *
+     * @var CatalogProductIndex
+     */
+    protected $catalogProductIndex;
+
+    /**
+     * Edit page on backend
+     *
+     * @var CatalogProductEdit
+     */
+    protected $catalogProductEdit;
+
+    /**
+     * Injection data
+     *
+     * @param CatalogProductIndex $catalogProductIndexNewPage
+     * @param CatalogProductEdit $catalogProductEditPage
+     * @return void
+     */
+    public function __inject(
+        CatalogProductIndex $catalogProductIndexNewPage,
+        CatalogProductEdit $catalogProductEditPage
+    ) {
+        $this->catalogProductIndex = $catalogProductIndexNewPage;
+        $this->catalogProductEdit = $catalogProductEditPage;
+    }
+
+    /**
+     * Test update bundle product
+     *
+     * @param BundleProduct $product
+     * @param BundleProduct $originalProduct
+     * @return void
+     */
+    public function test(BundleProduct $product, BundleProduct $originalProduct)
+    {
+        // Preconditions
+        $originalProduct->persist();
+
+        // Steps
+        $filter = ['sku' => $originalProduct->getSku()];
+
+        $this->catalogProductIndex->open();
+        $this->catalogProductIndex->getProductGrid()->searchAndOpen($filter);
+
+        $form = $this->catalogProductEdit->getProductForm();
+        $form->openSection('bundle');
+        $container = $form->getSection('bundle');
+        $containerFields = $product->getData()['bundle_selections']['bundle_options_delete'];
+        $container->deleteFieldsData($containerFields);
+
+        $form->openSection('product-details');
+        $container = $form->getSection('product-details');
+        $containerFields = $product->getData();
+        unset($containerFields['bundle_selections']);
+        $container->setFieldsData($containerFields);
+
+        $this->catalogProductEdit->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..795665d66d2bf7d34438381d3390e94c8458d3b7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleOptionsTest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Bundle\Test\TestCase\UpdateBundleOptionsTest" summary="Update Bundle Product Options" ticketId="MAGETWO-26195">
+        <variation name="UpdateBundleOptionsTestVariation1">
+            <data name="description" xsi:type="string">Update bundle product options</data>
+            <data name="originalProduct/dataset" xsi:type="string">with_3_bundle_options</data>
+            <data name="product/data/name" xsi:type="string">bundle_3_options_%isolation%</data>
+            <data name="product/data/sku" xsi:type="string">bundle_3_options_%isolation%</data>
+            <data name="product/data/bundle_selections/dataset" xsi:type="string">with_3_options_delete</data>
+            <constraint name="Magento\Bundle\Test\Constraint\AssertBundleOptionsDeleted" />
+        </variation>
+    </testCase>
+</config>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml
index 9ae1e2ebfacca405f8505496f546cf2182e2dd3f..c32999a6ebce7e0a4c44c1a10bc8fe4010a795f7 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml
@@ -34,5 +34,16 @@
                 <item name="inherit" xsi:type="number">1</item>
             </field>
         </dataset>
+        <dataset name="attribute_product_mask_sku">
+            <field name="catalog/fields_masks/sku" xsi:type="array">
+                <item name="value" xsi:type="string">{{name}} {{country_of_manufacture}}</item>
+            </field>
+        </dataset>
+        <dataset name="attribute_product_mask_sku_rollback">
+            <field name="catalog/fields_masks/sku" xsi:type="array">
+                <item name="value" xsi:type="string">{{name}}</item>
+                <item name="inherit" xsi:type="number">1</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0884e93387b2ac60c0be00e56791ae2b03443d38
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\TestCase\Product;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Steps:
+ * 1. Login to the backend.
+ * 2. Navigate to Products > Catalog.
+ * 3. Start to create simple product.
+ * 4. Fill in data according to data set.
+ * 5. Save Product.
+ * 6. Perform appropriate assertions.
+ *
+ * @group Products
+ * @ZephyrId MAGETWO-59861
+ */
+class CreateSimpleProductEntityByAttributeMaskSkuTest extends Injectable
+{
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * Should cache be flushed
+     *
+     * @var bool
+     */
+    private $flushCache;
+
+    /**
+     * @var \Magento\Mtf\Fixture\FixtureFactory
+     */
+    private $fixtureFactory;
+
+    /**
+     * Run create product simple entity by attribute mask SKU test.
+     *
+     * @param CatalogProductSimple $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductNew $newProductPage
+     * @param string $configData
+     * @param bool $flushCache
+     * @return array
+     */
+    public function testCreate(
+        CatalogProductSimple $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductNew $newProductPage,
+        \Magento\Mtf\Fixture\FixtureFactory $fixtureFactory,
+        $flushCache = false,
+        $configData = null
+    ) {
+        $this->configData = $configData;
+        $this->flushCache = $flushCache;
+        $this->fixtureFactory = $fixtureFactory;
+
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'flushCache' => $this->flushCache]
+        )->run();
+
+        // Steps
+        $productGrid->open();
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
+        $newProductPage->getProductForm()->fill($product);
+        $newProductPage->getFormPageActions()->save();
+
+        $skuMask = $this->prepareSkuByMask($product);
+
+        $productSimple = $fixtureFactory->createByCode(
+            'catalogProductSimple',
+            ['data' => array_merge($product->getData(), ['sku' => $skuMask])]
+        );
+
+        return ['product' => $productSimple];
+    }
+
+    /**
+     * Obtains product sku based on attributes define in Stores > Configuration->Catalog > Catalog > Mask for SKU
+     *
+     * @param CatalogProductSimple $product
+     * @return string
+     */
+    private function prepareSkuByMask(CatalogProductSimple $product)
+    {
+        $productData = $product->getData();
+        $skuMask = '';
+        $config = $this->fixtureFactory->createByCode('configData', ['dataset' => $this->configData]);
+        $section = $config->getData('section');
+        if (is_array($section) && array_key_exists('catalog/fields_masks/sku', $section)) {
+            $skuMask = $section['catalog/fields_masks/sku']['value'];
+        }
+
+        $attributesInPattern = [];
+        $count = preg_match_all('/{{(\w+)}}/', $skuMask, $matches);
+        if ($count > 0 && is_array($matches[0])) {
+            foreach ($matches[1] as $attributeName) {
+                if (array_key_exists($attributeName, $productData)) {
+                    $attributesInPattern[$attributeName] = $productData[$attributeName];
+                }
+            }
+        }
+        foreach ($attributesInPattern as $attributeName => $attributeValue) {
+            $skuMask = str_replace('{{' . $attributeName . '}}', $attributeValue, $skuMask);
+        }
+        return $skuMask;
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true, 'flushCache' => $this->flushCache]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..338f34a57ab5d8745a9cf53665d34e39a0369694
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityByAttributeMaskSkuTest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Catalog\Test\TestCase\Product\CreateSimpleProductEntityByAttributeMaskSkuTest" summary="Create Simple Product with attribute sku mask" ticketId="MAGETWO-59861">
+        <variation name="CreateSimpleProductEntityByAttributeMaskSkuTest1">
+            <data name="configData" xsi:type="string">attribute_product_mask_sku</data>
+            <data name="description" xsi:type="string">Create product with country of manufacture attribute sku mask</data>
+            <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data>
+            <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data>
+            <data name="product/data/price/value" xsi:type="string">10000</data>
+            <data name="product/data/weight" xsi:type="string">50</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">657</data>
+            <data name="product/data/country_of_manufacture" xsi:type="string">Ukraine</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
index f1776d2bf933e17d63006948795418309348ffe3..cad6dda90459845718bc3ab1e3ac2952cca16640 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
@@ -85,6 +85,7 @@ class Payment extends Block
         $paymentLabelSelector = sprintf($this->paymentMethodLabel, $payment['method']);
 
         try {
+            $this->waitForElementNotVisible($this->waitElement);
             $this->waitForElementVisible($paymentLabelSelector);
         } catch (\Exception $exception) {
             throw new \Exception('Such payment method is absent.');
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertGrandTotalOrderReview.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertGrandTotalOrderReview.php
index 3bf6bda89ad939ad4ae100006996cf4077e1aeb9..dc1433506f2623d2122f293b063a0707017edc13 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertGrandTotalOrderReview.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertGrandTotalOrderReview.php
@@ -14,6 +14,13 @@ use Magento\Mtf\Constraint\AbstractConstraint;
  */
 class AssertGrandTotalOrderReview extends AbstractConstraint
 {
+    /**
+     * Wait element.
+     *
+     * @var string
+     */
+    protected $waitElement = '.loading-mask';
+
     /**
      * Assert that Order Grand Total is correct on checkoutOnePage
      *
@@ -23,6 +30,7 @@ class AssertGrandTotalOrderReview extends AbstractConstraint
      */
     public function processAssert(CheckoutOnepage $checkoutOnepage, $grandTotal)
     {
+        $checkoutOnepage->getReviewBlock()->waitForElementNotVisible($this->waitElement);
         $checkoutReviewGrandTotal = $checkoutOnepage->getReviewBlock()->getGrandTotal();
 
         \PHPUnit_Framework_Assert::assertEquals(
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductPage.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductPage.php
index 62d6c72efe8c6aa8d0a8ed4aff4594316318c9e3..ad9807b76d6e532fd00e9f22fac7bf4007a80502 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductPage.php
@@ -125,15 +125,23 @@ class AssertConfigurableProductPage extends AssertProductPage
     protected function getLowestConfigurablePrice()
     {
         $price = null;
-        $configurableOptions = $this->product->getConfigurableAttributesData();
-
-        foreach ($configurableOptions['matrix'] as $option) {
-            $price = $price === null ? $option['price'] : $price;
-            if ($price > $option['price']) {
-                $price = $option['price'];
+        $priceDataConfig = $this->product->getDataFieldConfig('price');
+        if (isset($priceDataConfig['source'])) {
+            $priceData = $priceDataConfig['source']->getPriceData();
+            if (isset($priceData['price_from'])) {
+                $price = $priceData['price_from'];
             }
         }
 
+        if (null === $price) {
+            $configurableOptions = $this->product->getConfigurableAttributesData();
+            foreach ($configurableOptions['matrix'] as $option) {
+                $price = $price === null ? $option['price'] : $price;
+                if ($price > $option['price']) {
+                    $price = $option['price'];
+                }
+            }
+        }
         return $price;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
index 2e9d708dd42d82ca79d0507b6a698c0c5c897d3b..1b6282b9432c39fd444ca2089f1b8c8aa6bfb876 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
@@ -17,5 +17,8 @@
         <dataset name="MAGETWO-12620">
             <field name="category_price" xsi:type="string">11</field>
         </dataset>
+        <dataset name="from-9">
+            <field name="price_from" xsi:type="string">9</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
index 58435b066261ed28cc7f33ff01fc250940b6eb17..187283da4602fd56c6fb6f2441d11dc5c1ad05bd 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
@@ -58,6 +58,7 @@
             <data name="product/data/checkout_data/dataset" xsi:type="string">configurable_two_new_options_with_special_price</data>
             <data name="product/data/name" xsi:type="string">Configurable Product %isolation%</data>
             <data name="product/data/sku" xsi:type="string">configurable_sku_%isolation%</data>
+            <data name="product/data/price/dataset" xsi:type="string">from-9</data>
             <data name="product/data/price/value" xsi:type="string">100</data>
             <data name="product/data/special_price" xsi:type="string">9</data>
             <data name="product/data/short_description" xsi:type="string">Configurable short description</data>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php
index 03dbfee05ca6973d90da4a4205eb1b64f9f2edca..bf4886a9f208d4a9bf308ee8f5f8b26daf9c6d6e 100644
--- a/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php
@@ -21,7 +21,7 @@ class WebConfiguration extends Form
      *
      * @var string
      */
-    protected $next = "[ng-click*='next']";
+    protected $next = "[ng-click*='validateUrl']";
 
     /**
      * 'Advanced Options' locator.
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/ExpressCheckout.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/ExpressCheckout.php
index d83ae0c53ec0a575ba11280b9a8731bbe23a6f8a..6e4849669568851cbe4787766c6cf8b2f630e9e6 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/ExpressCheckout.php
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/ExpressCheckout.php
@@ -20,8 +20,6 @@ class ExpressCheckout extends Block
      * @var array
      */
     private $fields = [
-        'Email Associated with PayPal Merchant Account' => '#payment_us_paypal_alternative_payment_methods_express_' .
-            'checkout_us_express_checkout_required_express_checkout_required_express_checkout_business_account',
         'API Username' => '#payment_us_paypal_alternative_payment_methods_express_checkout_us_express_checkout_' .
             'required_express_checkout_required_express_checkout_api_username',
         'API Password' => '#payment_us_paypal_alternative_payment_methods_express_checkout_us_express_checkout_' .
@@ -72,8 +70,6 @@ class ExpressCheckout extends Block
      */
     public function specifyCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])
-            ->setValue('test@test.com');
         $this->_rootElement->find($this->fields['API Username'])->setValue('1');
         $this->_rootElement->find($this->fields['API Password'])->setValue('1');
         $this->_rootElement->find($this->fields['API Signature'])->setValue('1');
@@ -86,7 +82,6 @@ class ExpressCheckout extends Block
      */
     public function clearCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])->setValue('');
         $this->_rootElement->find($this->fields['API Username'])->setValue('');
         $this->_rootElement->find($this->fields['API Password'])->setValue('');
         $this->_rootElement->find($this->fields['API Signature'])->setValue('');
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowLink.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowLink.php
index de6eb107c61ce5e6b63451abdea0473351ddde43..f1af6acb6174e1b462651b7887d80159d6910952 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowLink.php
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowLink.php
@@ -20,8 +20,6 @@ class PayflowLink extends Block
      * @var array
      */
     private $fields = [
-        'Email Associated with PayPal Merchant Account' => '#payment_us_paypal_payment_gateways_payflow_link_us_' .
-            'payflow_link_required_payflow_link_payflow_link_business_account',
         'Partner' => '#payment_us_paypal_payment_gateways_payflow_link_us_payflow_link_required_payflow_link_payflow_' .
             'link_partner',
         'Vendor' => '#payment_us_paypal_payment_gateways_payflow_link_us_payflow_link_required_payflow_link_payflow_' .
@@ -60,8 +58,6 @@ class PayflowLink extends Block
      */
     public function specifyCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])
-            ->setValue('test@test.com');
         $this->_rootElement->find($this->fields['Partner'])->setValue('1');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('1');
         $this->_rootElement->find($this->fields['User'])->setValue('1');
@@ -75,7 +71,6 @@ class PayflowLink extends Block
      */
     public function clearCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])->setValue('');
         $this->_rootElement->find($this->fields['Partner'])->setValue('');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('');
         $this->_rootElement->find($this->fields['User'])->setValue('');
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowPro.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowPro.php
index e3b01aa3af9a0dfa4517ad3fe4b527eec9d30ad0..1db07ac435a37ed9c9d9d237f62b7debed956861 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowPro.php
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PayflowPro.php
@@ -20,8 +20,6 @@ class PayflowPro extends Block
      * @var array
      */
     private $fields = [
-        'Email Associated with PayPal Merchant Account' => '#payment_us_paypal_payment_gateways_paypal_payflowpro_' .
-            'with_express_checkout_paypal_payflow_required_paypal_payflow_api_settings_business_account',
         'Partner' => '#payment_us_paypal_payment_gateways_paypal_payflowpro_with_express_checkout_paypal_payflow_' .
             'required_paypal_payflow_api_settings_partner',
         'Vendor' => '#payment_us_paypal_payment_gateways_paypal_payflowpro_with_express_checkout_paypal_payflow_' .
@@ -60,8 +58,6 @@ class PayflowPro extends Block
      */
     public function specifyCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])
-            ->setValue('test@test.com');
         $this->_rootElement->find($this->fields['Partner'])->setValue('1');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('1');
         $this->_rootElement->find($this->fields['User'])->setValue('1');
@@ -75,7 +71,6 @@ class PayflowPro extends Block
      */
     public function clearCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])->setValue('');
         $this->_rootElement->find($this->fields['Partner'])->setValue('');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('');
         $this->_rootElement->find($this->fields['User'])->setValue('');
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsAdvanced.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsAdvanced.php
index cd6d1a5b1b38a016382ffa2e68ab73bd566c4116..87adb729a1646e6eb5b61e8e167d2eed20111e4e 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsAdvanced.php
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsAdvanced.php
@@ -20,8 +20,6 @@ class PaymentsAdvanced extends Block
      * @var array
      */
     private $fields = [
-        'Email Associated with PayPal Merchant Account' => '#payment_us_paypal_group_all_in_one_payflow_advanced_' .
-            'required_settings_payments_advanced_business_account',
         'Partner' => '#payment_us_paypal_group_all_in_one_payflow_advanced_required_settings_payments_advanced_partner',
         'Vendor' => '#payment_us_paypal_group_all_in_one_payflow_advanced_required_settings_payments_advanced_vendor',
         'User' => '#payment_us_paypal_group_all_in_one_payflow_advanced_required_settings_payments_advanced_user',
@@ -54,8 +52,6 @@ class PaymentsAdvanced extends Block
      */
     public function specifyCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])
-            ->setValue('test@test.com');
         $this->_rootElement->find($this->fields['Partner'])->setValue('1');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('1');
         $this->_rootElement->find($this->fields['User'])->setValue('1');
@@ -69,7 +65,6 @@ class PaymentsAdvanced extends Block
      */
     public function clearCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])->setValue('');
         $this->_rootElement->find($this->fields['Partner'])->setValue('');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('');
         $this->_rootElement->find($this->fields['User'])->setValue('');
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsPro.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsPro.php
index cd146aa8f809cf5de0cbddcb02be83a19e59928f..55fd7444ba50ad8dbf9662b758b10d7a70ee6c6d 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsPro.php
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/System/Config/PaymentsPro.php
@@ -20,8 +20,6 @@ class PaymentsPro extends Block
      * @var array
      */
     private $fields = [
-        'Email Associated with PayPal Merchant Account' => '#payment_us_paypal_group_all_in_one_wpp_usuk_paypal_' .
-            'payflow_required_paypal_payflow_api_settings_business_account',
         'Partner' => '#payment_us_paypal_group_all_in_one_wpp_usuk_paypal_payflow_required_paypal_payflow_api_' .
             'settings_partner',
         'Vendor' => '#payment_us_paypal_group_all_in_one_wpp_usuk_paypal_payflow_required_paypal_payflow_api_' .
@@ -60,8 +58,6 @@ class PaymentsPro extends Block
      */
     public function specifyCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])
-            ->setValue('test@test.com');
         $this->_rootElement->find($this->fields['Partner'])->setValue('1');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('1');
         $this->_rootElement->find($this->fields['User'])->setValue('1');
@@ -75,7 +71,6 @@ class PaymentsPro extends Block
      */
     public function clearCredentials()
     {
-        $this->_rootElement->find($this->fields['Email Associated with PayPal Merchant Account'])->setValue('');
         $this->_rootElement->find($this->fields['Partner'])->setValue('');
         $this->_rootElement->find($this->fields['Vendor'])->setValue('');
         $this->_rootElement->find($this->fields['User'])->setValue('');
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php
index bfe0bc9eabddfb0cc0f746f79efdad5b6ad0a43b..1f3f0e5a300b46ac9a193666796e52c584b8c944 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php
@@ -25,8 +25,6 @@ class AssertCartPriceRuleForm extends AbstractConstraint
     protected $skippedFields = [
         'conditions_serialized',
         'actions_serialized',
-        'from_date',
-        'to_date',
         'rule_id'
     ];
 
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
index 13b68aca6c6eb7867286019b3a9609b3b93db2a8..3a35215d841d50780d212084d76d014af8708aa4 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
@@ -114,10 +114,10 @@
             <field name="uses_per_coupon" xsi:type="string">13</field>
             <field name="uses_per_customer" xsi:type="string">63</field>
             <field name="from_date" xsi:type="array">
-                <item name="pattern" xsi:type="string">3/25/2014</item>
+                <item name="pattern" xsi:type="string">03/25/2014</item>
             </field>
             <field name="to_date" xsi:type="array">
-                <item name="pattern" xsi:type="string">6/29/2024</item>
+                <item name="pattern" xsi:type="string">-</item>
             </field>
             <field name="sort_order" xsi:type="string">1</field>
             <field name="is_rss" xsi:type="string">Yes</field>
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4b42430c0b8a81987b78d907f8b4a4c56d6db834
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Security\Test\TestCase;
+
+
+use Magento\User\Test\Page\Adminhtml\UserEdit;
+use Magento\User\Test\Page\Adminhtml\UserIndex;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\User\Test\Fixture\User;
+use Magento\Backend\Test\Page\AdminAuthLogin;
+
+/**
+ * Preconditions:
+ * 1. Create admin user.
+ * 2. Configure 'Maximum Login Failures to Lockout Account'.
+ *
+ * Steps:
+ * 1. Log in to backend as admin user.
+ * 2. Navigate to System > All Users.
+ * 3. Click on Add New User.
+ * 4. Fill in all data according to data set (password is incorrect).
+ * 5. Perform action 4 specified number of times.
+ * 6. "You have entered an invalid password for current user." appears after each attempt.
+ * 7. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-49034
+ */
+class LockAdminUserWhenCreatingNewUserTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const SEVERITY = 'S2';
+    /* end tags */
+
+    /**
+     * User grid page
+     *
+     * @var UserIndex
+     */
+    protected $userIndexPage;
+
+    /**
+     * User new/edit page
+     *
+     * @var UserEdit
+     */
+    protected $userEditPage;
+
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * @var AdminAuthLogin page
+     */
+    protected $adminAuthLogin;
+
+    /**
+     * Setup data for test.
+     * @param UserIndex $userIndex
+     * @param UserEdit $userEdit
+     * @param AdminAuthLogin $adminAuthLogin
+     */
+    public function __inject(
+        UserIndex $userIndex,
+        UserEdit $userEdit,
+        AdminAuthLogin $adminAuthLogin
+    ) {
+        $this->userIndexPage = $userIndex;
+        $this->userEditPage = $userEdit;
+        $this->adminAuthLogin = $adminAuthLogin;
+    }
+
+    /**
+     * Runs Lock admin user when creating new user test.
+     *
+     * @param int $attempts
+     * @param User $customAdmin,
+     * @param User $user,
+     * @param string $configData
+     * @return void
+     */
+    public function test(
+        $attempts,
+        User $customAdmin,
+        User $user,
+        $configData
+    ) {
+        $this->configData = $configData;
+
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+        $customAdmin->persist();
+
+        // Steps
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+        $this->userIndexPage->open();
+        $this->userIndexPage->getPageActions()->addNew();
+        for ($i = 0; $i < $attempts; $i++) {
+            $this->userEditPage->getUserForm()->fill($user);
+            $this->userEditPage->getPageActions()->save();
+        }
+
+        // Reload
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e36f8b4625dd66eeb5a41f15c74c4bdf6e7eeeea
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenCreatingNewUserTest" summary="Lock admin user after entering incorrect password while creating new User">
+        <variation name="LockAdminUserWhenCreatingNewUserTestVariation1">
+            <data name="configData" xsi:type="string">user_lockout_failures</data>
+            <data name="tag" xsi:type="string">severity:S2</data>
+            <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data>
+            <data name="user/data/username" xsi:type="string">AdminUser%isolation%</data>
+            <data name="user/data/firstname" xsi:type="string">FirstName%isolation%</data>
+            <data name="user/data/lastname" xsi:type="string">LastName%isolation%</data>
+            <data name="user/data/email" xsi:type="string">email%isolation%@example.com</data>
+            <data name="user/data/password" xsi:type="string">123123q</data>
+            <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
+            <data name="user/data/current_password" xsi:type="string">incorrect password</data>
+            <data name="attempts" xsi:type="string">4</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a1c1d0507c91ea3b9a86d254f6f2c01d58a7d2d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Security\Test\TestCase;
+
+use Magento\Integration\Test\Fixture\Integration;
+use Magento\User\Test\Fixture\User;
+use Magento\Integration\Test\Page\Adminhtml\IntegrationIndex;
+use Magento\Integration\Test\Page\Adminhtml\IntegrationNew;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Backend\Test\Page\AdminAuthLogin;
+
+/**
+ * Preconditions:
+ * 1. Create admin user.
+ * 2. Create integration.
+ * 3. Configure 'Maximum Login Failures to Lockout Account'.
+ *
+ * Steps:
+ * 1. Log in to backend as admin user.
+ * 2. Navigate to System > Extensions > Integrations.
+ * 3. Start to edit existing Integration.
+ * 4. Fill in all data according to data set (password is incorrect).
+ * 5. Perform action 4 specified number of times.
+ * 6. "You have entered an invalid password for current user." appears after each attempt.
+ * 7. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-49039
+ */
+class LockAdminUserWhenEditingIntegrationTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const SEVERITY = 'S2';
+    /* end tags */
+
+    /**
+     * Integration grid page.
+     *
+     * @var IntegrationIndex
+     */
+    protected $integrationIndexPage;
+
+    /**
+     * Integration new page.
+     *
+     * @var IntegrationNew
+     */
+    protected $integrationNewPage;
+
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * @var AdminAuthLogin
+     */
+    protected $adminAuthLogin;
+
+    /**
+     * Preparing pages for test.
+     *
+     * @param IntegrationIndex $integrationIndex
+     * @param IntegrationNew $integrationNew
+     * @param AdminAuthLogin $adminAuthLogin
+     * @return void
+     */
+    public function __inject(
+        IntegrationIndex $integrationIndex,
+        IntegrationNew $integrationNew,
+        AdminAuthLogin $adminAuthLogin
+    ) {
+        $this->integrationIndexPage = $integrationIndex;
+        $this->integrationNewPage = $integrationNew;
+        $this->adminAuthLogin = $adminAuthLogin;
+    }
+
+    /**
+     * Run Lock user when creating new integration test.
+     *
+     * @param Integration $initintegration
+     * @param Integration $integration
+     * @param int $attempts
+     * @param User $customAdmin
+     * @param string $configData
+     * @return void
+     */
+    public function test(
+        Integration $initintegration,
+        Integration $integration,
+        $attempts,
+        User $customAdmin,
+        $configData
+    ) {
+        $this->configData = $configData;
+
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+        $customAdmin->persist();
+        $initintegration->persist();
+
+        // login to backend with new user
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+
+        // Steps
+        $filter = ['name' => $initintegration->getName()];
+        $this->integrationIndexPage->open();
+        $this->integrationIndexPage->getIntegrationGrid()->searchAndOpen($filter);
+        for ($i = 0; $i < $attempts; $i++) {
+            $this->integrationNewPage->getIntegrationForm()->fill($integration);
+            $this->integrationNewPage->getFormPageActions()->save();
+        }
+
+        // Reload page
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6efc88d78cd3836f00db79d2c567d3e6e38d1bb1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenEditingIntegrationTest" summary="Lock admin user after entering incorrect password while editing integration">
+        <variation name="LockAdminUserWhenCreatingNewIntegrationTestVariation1">
+            <data name="configData" xsi:type="string">user_lockout_failures</data>
+            <data name="tag" xsi:type="string">severity:S2</data>
+            <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data>
+            <data name="initintegration/dataset" xsi:type="string">default_active</data>
+            <data name="integration/data/name" xsi:type="string">Integration%isolation%</data>
+            <data name="integration/data/current_password" xsi:type="string">incorrect password</data>
+            <data name="attempts" xsi:type="string">4</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" />
+        </variation>
+    </testCase>
+</config>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd7c8cef92d8a320b43615983a95ea724cce0d78
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Security\Test\TestCase;
+
+use Magento\User\Test\Page\Adminhtml\UserRoleEditRole;
+use Magento\User\Test\Page\Adminhtml\UserRoleIndex;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\User\Test\Fixture\User;
+use Magento\User\Test\Fixture\Role;
+use Magento\Backend\Test\Page\AdminAuthLogin;
+
+/**
+ * Preconditions:
+ * 1. Create new admin user and assign it to new role.
+ * 2. Configure 'Maximum Login Failures to Lockout Account'.
+ *
+ * Steps:
+ * 1. Log in to backend as new created admin user.
+ * 2. Navigate to System > User Roles.
+ * 3. Start editing existing User Role.
+ * 4. Fill in all data according to data set (password is incorrect).
+ * 5. Perform action 4 specified number of times.
+ * 6. Admin account is locked.
+ * 7. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-49037
+ * @Group Security
+ *
+ */
+class LockAdminUserWhenEditingRoleTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const SEVERITY = 'S2';
+    /* end tags */
+
+    /**
+     * UserRoleIndex page.
+     *
+     * @var UserRoleIndex
+     */
+    protected $userRoleIndex;
+
+    /**
+     * UserRoleEditRole page.
+     *
+     * @var UserRoleEditRole
+     */
+    protected $userRoleEditRole;
+
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * Admin login Page.
+     *
+     * @var AdminAuthLogin
+     */
+    protected $adminAuthLogin;
+
+    /**
+     * Setup data for test.
+     *
+     * @param UserRoleIndex $userRoleIndex
+     * @param UserRoleEditRole $userRoleEditRole
+     * @param AdminAuthLogin $adminAuthLogin
+     * @return void
+     */
+    public function __inject(
+        UserRoleIndex $userRoleIndex,
+        UserRoleEditRole $userRoleEditRole,
+        AdminAuthLogin $adminAuthLogin
+    ) {
+        $this->userRoleIndex = $userRoleIndex;
+        $this->userRoleEditRole = $userRoleEditRole;
+        $this->adminAuthLogin = $adminAuthLogin;
+    }
+
+    /**
+     * Runs Lock admin user when editing existing role test.
+     *
+     * @param Role $role
+     * @param Role $initrole
+     * @param int $attempts
+     * @param User $customAdmin
+     * @param string $configData
+     * @return void
+     */
+    public function test(
+        Role $role,
+        Role $initrole,
+        $attempts,
+        User $customAdmin,
+        $configData
+    ) {
+        $this->configData = $configData;
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+        $customAdmin->persist();
+        $initrole->persist();
+        // Steps login to backend with new user
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+        $filter = ['rolename' => $initrole->getRolename()];
+        $this->userRoleIndex->open();
+        $this->userRoleIndex->getRoleGrid()->searchAndOpen($filter);
+        for ($i = 0; $i < $attempts; $i++) {
+            $this->userRoleEditRole->getRoleFormTabs()->fill($role);
+            $this->userRoleEditRole->getPageActions()->save();
+        }
+        // Reload
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d081e5d2dd9af69f90aeed8b787c966238e62de
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingRoleTest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenEditingRoleTest" summary="Lock admin user after entering incorrect password while editing existing role">
+        <variation name="LockAdminUserWhenEditingUserRoleTestVariation1">
+            <data name="configData" xsi:type="string">user_lockout_failures</data>
+            <data name="tag" xsi:type="string">severity:S2</data>
+            <data name="initrole/dataset" xsi:type="string">default</data>
+            <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data>
+            <data name="role/data/rolename" xsi:type="string">NewAdminRole%isolation%</data>
+            <data name="role/data/current_password" xsi:type="string">incorrect password</data>
+            <data name="role/data/resource_access" xsi:type="string">All</data>
+            <data name="attempts" xsi:type="string">4</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..912ebef9e91054236cc6b85b91c3cd8d973b54e9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Security\Test\TestCase;
+
+use Magento\User\Test\Page\Adminhtml\UserEdit;
+use Magento\User\Test\Page\Adminhtml\UserIndex;
+use Magento\Backend\Test\Page\AdminAuthLogin;
+use Magento\User\Test\Fixture\User;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Preconditions:
+ * 1. Create new admin user.
+ * 2. Configure 'Maximum Login Failures to Lockout Account'.
+ *
+ * Steps:
+ * 1. Log in to backend as new created admin user.
+ * 2. Navigate to System > All Users.
+ * 3. Start editing existing User.
+ * 4. Fill in all data according to data set (password is incorrect).
+ * 5. Perform action 4 specified number of times.
+ * 6. Admin account is locked.
+ * 7. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-49035
+ */
+class LockAdminUserWhenEditingUserTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const SEVERITY = 'S2';
+    /* end tags */
+
+    /**
+     * User grid page
+     *
+     * @var UserIndex
+     */
+    protected $userIndexPage;
+
+    /**
+     * User edit page
+     *
+     * @var UserEdit
+     */
+    protected $userEditPage;
+
+    /**
+     * @var $configData
+     */
+    protected $configData;
+
+    /**
+     * @var AdminAuthLogin page
+     */
+    protected $adminAuthLogin;
+
+    /**
+     * Setup data for test.
+     * @param UserIndex $userIndex
+     * @param UserEdit $userEdit
+     * @param AdminAuthLogin $adminAuthLogin
+     */
+    public function __inject(
+        UserIndex $userIndex,
+        UserEdit $userEdit,
+        AdminAuthLogin $adminAuthLogin
+    ) {
+        $this->userIndexPage = $userIndex;
+        $this->userEditPage = $userEdit;
+        $this->adminAuthLogin = $adminAuthLogin;
+    }
+
+    /**
+     * Runs Lock admin user when editing existing role test.
+     *
+     * @param User $user
+     * @param int $attempts
+     * @param User $customAdmin
+     * @param string $configData
+     * @return void
+     */
+    public function test(
+        $attempts,
+        User $customAdmin,
+        User $user,
+        $configData
+    ) {
+        $this->configData = $configData;
+
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+        $customAdmin->persist();
+
+        // Steps login to backend with new user
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+        // Select user to edit.
+        $filter = ['username' => $customAdmin->getUsername()];
+        $this->userIndexPage->open();
+        $this->userIndexPage->getUserGrid()->searchAndOpen($filter);
+        // Edit user with wrong password
+        for ($i = 0; $i < $attempts; $i++) {
+            $this->userEditPage->getUserForm()->fill($user);
+            $this->userEditPage->getPageActions()->save();
+        }
+        // Reload
+        $this->adminAuthLogin->open();
+        $this->adminAuthLogin->getLoginBlock()->fill($customAdmin);
+        $this->adminAuthLogin->getLoginBlock()->submit();
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1ec2f79ce6b5d306e694c9d2ae8e8adea0d3387
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenEditingUserTest" summary="Lock admin user after entering incorrect password while editing existing user">
+        <variation name="LockAdminUserWhenEditingUseruserTestVariation1">
+            <data name="configData" xsi:type="string">user_lockout_failures</data>
+            <data name="tag" xsi:type="string">severity:S2</data>
+            <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data>
+            <data name="user/data/username" xsi:type="string">AdminUser%isolation%</data>
+            <data name="user/data/firstname" xsi:type="string">FirstName%isolation%</data>
+            <data name="user/data/lastname" xsi:type="string">LastName%isolation%</data>
+            <data name="user/data/email" xsi:type="string">email%isolation%@example.com</data>
+            <data name="user/data/password" xsi:type="string">123123qq</data>
+            <data name="user/data/password_confirmation" xsi:type="string">123123qq</data>
+            <data name="user/data/current_password" xsi:type="string">incorrect password</data>
+            <data name="attempts" xsi:type="string">4</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" />
+        </variation>
+    </testCase>
+</config>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
index 80df7e6f8c631722fb314525b2d6733e2ac605ad..95240b5dba0644d7f10d80447399d516a4742ac2 100644
--- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
@@ -165,7 +165,7 @@ class DataGrid extends Grid
      */
     protected function waitFilterToLoad()
     {
-        $this->getTemplateBlock()->waitForElementNotVisible($this->loader);
+        $this->getTemplateBlock()->waitLoader();
         $browser = $this->_rootElement;
         $selector = $this->filterButton . ', ' . $this->resetButton;
         $browser->waitUntil(
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist/Items/Product.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist/Items/Product.php
index 076739590e1f19b86fee7bc105221f51efda34cb..683ff71e8ff7212e4e9604d581d04b4cf9b0f238 100644
--- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist/Items/Product.php
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist/Items/Product.php
@@ -164,6 +164,18 @@ class Product extends Form
         $this->_rootElement->find($this->price)->hover();
     }
 
+    /**
+     * Returns product price
+     *
+     * @param string $currency
+     * @return string
+     */
+    public function getPrice($currency = '$')
+    {
+        $price = $this->_rootElement->find($this->price)->getText();
+        return str_replace($currency, '', $price);
+    }
+
     /**
      * Get Wish List data for the Product.
      *
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductPriceIsNotZero.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductPriceIsNotZero.php
new file mode 100644
index 0000000000000000000000000000000000000000..24f6222dac09eb34cf3c3d6c5a063341b2acc2ef
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductPriceIsNotZero.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Wishlist\Test\Constraint;
+
+class AssertProductPriceIsNotZero extends \Magento\Mtf\Constraint\AbstractConstraint
+{
+    /**
+     * Assert that product price is not zero in default wishlist.
+     *
+     * @param \Magento\Cms\Test\Page\CmsIndex $cmsIndex
+     * @param \Magento\Customer\Test\Page\CustomerAccountIndex $customerAccountIndex
+     * @param \Magento\Wishlist\Test\Page\WishlistIndex $wishlistIndex
+     * @param \Magento\Mtf\Fixture\InjectableFixture $product
+     *
+     * @return void
+     */
+    public function processAssert(
+        \Magento\Cms\Test\Page\CmsIndex $cmsIndex,
+        \Magento\Customer\Test\Page\CustomerAccountIndex $customerAccountIndex,
+        \Magento\Wishlist\Test\Page\WishlistIndex $wishlistIndex,
+        \Magento\Mtf\Fixture\InjectableFixture $product
+    ) {
+        $cmsIndex->getLinksBlock()->openLink('My Account');
+        $customerAccountIndex->getAccountMenuBlock()->openMenuItem('My Wish List');
+        $wishlistItem = $wishlistIndex->getWishlistBlock()->getProductItemsBlock()->getItemProduct($product);
+
+        \PHPUnit_Framework_Assert::assertNotEquals(
+            '0.00',
+            $wishlistItem->getPrice(),
+            $product->getName() . ' has zero price on Wish List page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product price is not zero in default Wish List.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php
index 9959796828df23943db8fc3f6dfdce4b6387e1ac..bd922feee99d0315b5f7f16ee13b60eb101b626e 100644
--- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php
@@ -48,15 +48,16 @@ class AddProductToWishlistEntityTest extends AbstractWishlistTest
      *
      * @param Customer $customer
      * @param string $product
+     * @param bool $configure
      * @return array
      */
-    public function test(Customer $customer, $product)
+    public function test(Customer $customer, $product, $configure = true)
     {
         $product = $this->createProducts($product)[0];
 
         // Steps:
         $this->loginCustomer($customer);
-        $this->addToWishlist([$product], true);
+        $this->addToWishlist([$product], $configure);
 
         return ['product' => $product];
     }
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
index 0557fa298ce985313593216b561b181175719a70..550cffa488130e16f73a9d89b9bc4344a57a2291 100644
--- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
@@ -49,5 +49,12 @@
             <constraint name="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist" />
             <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" />
         </variation>
+        <variation name="AddProductToWishlistEntityTestVariation8">
+            <data name="product/0" xsi:type="string">configurableProduct::default</data>
+            <data name="configure" xsi:type="boolean">false</data>
+            <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" />
+            <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInWishlist" />
+            <constraint name="Magento\Wishlist\Test\Constraint\AssertProductPriceIsNotZero" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce5ed9cb663a759edf057291f11ccc6a75fe6266
--- /dev/null
+++ b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
+    <module name="Magento_TestModuleDirectoryZipCodes" setup_version="0.0.1" active="true">
+        <sequence>
+            <module name="Magento_Directory"/>
+        </sequence>
+    </module>
+</config>
diff --git a/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/zip_codes.xml b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/zip_codes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d4f121c60daeb8c44f327f8149f0148051c252ff
--- /dev/null
+++ b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/zip_codes.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Directory:etc/zip_codes.xsd">
+    <zip countryCode="NL">
+        <codes>
+            <code id="pattern_1" active="true" example="test1">^[0-9]{4}\s[a-zA-Z]{2}$</code>
+            <code id="pattern_2" active="true" example="test2">^[0-5]{4}[a-z]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="NL_NEW">
+        <codes>
+            <code id="pattern_1" active="true" example="test1">^[0-2]{4}[A-Z]{2}$</code>
+        </codes>
+    </zip>
+</config>
diff --git a/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/registration.php b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/registration.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ed368ecf3b23a4bd4db86357f6cbbca0bfc55de
--- /dev/null
+++ b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/registration.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Framework\Component\ComponentRegistrar;
+
+$registrar = new ComponentRegistrar();
+if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleDirectoryZipCodes') === null) {
+    ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleDirectoryZipCodes', __DIR__);
+}
diff --git a/dev/tests/integration/_files/Magento/TestModuleSample/composer.json b/dev/tests/integration/_files/Magento/TestModuleSample/composer.json
index 4d6383045d27f2123e84146eae970ec74ae77797..3e8e5650b85a77f75c079ae0ad9211a8d4d0764a 100644
--- a/dev/tests/integration/_files/Magento/TestModuleSample/composer.json
+++ b/dev/tests/integration/_files/Magento/TestModuleSample/composer.json
@@ -2,7 +2,7 @@
   "name": "magento/module-sample-test",
   "description": "test sample module",
   "require": {
-    "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+    "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
     "magento/framework": "100.1.*",
     "magento/module-integration": "100.1.*"
   },
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index 0bbf2613febcfe533b5523a8b5a86dabae349076..8775eb7d54d0fd59c8c09aeaf000149a24f3d2bf 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -1432,4 +1432,113 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase
         $this->assertEquals(implode(',', [$multiselectOptions[1]->getValue(), $multiselectOptions[2]->getValue()]),
             $product2->getData('multiselect_attribute'));
     }
+
+    /**
+     * @param array $row
+     * @param string|null $behavior
+     * @param bool $expectedResult
+     * @magentoAppArea adminhtml
+     * @magentoAppIsolation enabled
+     * @magentoDbIsolation enabled
+     * @magentoDataFixture Magento/Catalog/Model/ResourceModel/_files/product_simple.php
+     * @dataProvider validateRowDataProvider
+     */
+    public function testValidateRow(array $row, $behavior, $expectedResult)
+    {
+        $this->_model->setParameters(['behavior' => $behavior, 'entity' => 'catalog_product']);
+        $this->assertSame($expectedResult, $this->_model->validateRow($row, 1));
+    }
+
+    /**
+     * @return array
+     */
+    public function validateRowDataProvider()
+    {
+        return [
+            [
+                'row' => ['sku' => 'simple products'],
+                'behavior' => null,
+                'expectedResult' => true,
+            ],
+            [
+                'row' => ['sku' => 'simple products absent'],
+                'behavior' => null,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => [
+                    'sku' => 'simple products absent',
+                    'name' => 'Test',
+                    'product_type' => 'simple',
+                    '_attribute_set' => 'Default',
+                    'price' => 10.20,
+                ],
+                'behavior' => null,
+                'expectedResult' => true,
+            ],
+            [
+                'row' => ['sku' => 'simple products'],
+                'behavior' => Import::BEHAVIOR_ADD_UPDATE,
+                'expectedResult' => true,
+            ],
+            [
+                'row' => ['sku' => 'simple products absent'],
+                'behavior' => Import::BEHAVIOR_ADD_UPDATE,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => [
+                    'sku' => 'simple products absent',
+                    'name' => 'Test',
+                    'product_type' => 'simple',
+                    '_attribute_set' => 'Default',
+                    'price' => 10.20,
+                ],
+                'behavior' => Import::BEHAVIOR_ADD_UPDATE,
+                'expectedResult' => true,
+            ],
+            [
+                'row' => ['sku' => 'simple products'],
+                'behavior' => Import::BEHAVIOR_DELETE,
+                'expectedResult' => true,
+            ],
+            [
+                'row' => ['sku' => 'simple products absent'],
+                'behavior' => Import::BEHAVIOR_DELETE,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => ['sku' => 'simple products'],
+                'behavior' => Import::BEHAVIOR_REPLACE,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => ['sku' => 'simple products absent'],
+                'behavior' => Import::BEHAVIOR_REPLACE,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => [
+                    'sku' => 'simple products absent',
+                    'name' => 'Test',
+                    'product_type' => 'simple',
+                    '_attribute_set' => 'Default',
+                    'price' => 10.20,
+                ],
+                'behavior' => Import::BEHAVIOR_REPLACE,
+                'expectedResult' => false,
+            ],
+            [
+                'row' => [
+                    'sku' => 'simple products',
+                    'name' => 'Test',
+                    'product_type' => 'simple',
+                    '_attribute_set' => 'Default',
+                    'price' => 10.20,
+                ],
+                'behavior' => Import::BEHAVIOR_REPLACE,
+                'expectedResult' => true,
+            ],
+        ];
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Controller/CartTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Controller/CartTest.php
index 34a484f749b7807a7096e22fc24c21b8b6e6c5dd..54a068dad5d0a26f1564d662eb962eca64527110 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/Controller/CartTest.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/Controller/CartTest.php
@@ -229,4 +229,51 @@ class CartTest extends \Magento\TestFramework\TestCase\AbstractController
         }
         return null;
     }
+
+    /**
+     * Test for \Magento\Checkout\Controller\Cart::execute() with simple product
+     *
+     * @param string $area
+     * @param string $expectedPrice
+     * @magentoDataFixture Magento/Catalog/_files/products.php
+     * @magentoAppIsolation enabled
+     * @dataProvider addAddProductDataProvider
+     */
+    public function testAddToCartSimpleProduct($area, $expectedPrice)
+    {
+        $formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class);
+        $postData = [
+            'qty' => '1',
+            'product' => '1',
+            'custom_price' => 1,
+            'form_key' => $formKey->getFormKey(),
+            'isAjax' => 1
+        ];
+        \Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea($area);
+        $this->getRequest()->setPostValue($postData);
+
+        $quote =  $this->_objectManager->create(\Magento\Checkout\Model\Cart::class);
+        /** @var \Magento\Checkout\Controller\Cart\Add $controller */
+        $controller = $this->_objectManager->create(\Magento\Checkout\Controller\Cart\Add::class, [$quote]);
+        $controller->execute();
+
+        $this->assertContains(json_encode([]), $this->getResponse()->getBody());
+        $items = $quote->getItems()->getItems();
+        $this->assertTrue(is_array($items), 'Quote doesn\'t have any items');
+        $this->assertCount(1, $items, 'Expected quote items not equal to 1');
+        $item = reset($items);
+        $this->assertEquals(1, $item->getProductId(), 'Quote has more than one product');
+        $this->assertEquals($expectedPrice, $item->getPrice(), 'Expected product price failed');
+    }
+
+    /**
+     * Data provider for testAddToCartSimpleProduct
+     */
+    public function addAddProductDataProvider()
+    {
+        return [
+            'frontend' => ['frontend', 'expected_price' => 10],
+            'adminhtml' => ['adminhtml', 'expected_price' => 1]
+        ];
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Config/Model/Config/Backend/BaseurlTest.php b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Backend/BaseurlTest.php
index 0ce30e5b2984120c7e325a151d96c0ef044affa6..5a2db8ccb22fa0484ab71c04f8a6bbc4cbc7b0e6 100644
--- a/dev/tests/integration/testsuite/Magento/Config/Model/Config/Backend/BaseurlTest.php
+++ b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Backend/BaseurlTest.php
@@ -95,33 +95,44 @@ class BaseurlTest extends \PHPUnit_Framework_TestCase
         $unsecurePlaceholder = '{{unsecure_base_url}}';
         $unsecureSuffix = '{{unsecure_base_url}}test/';
         $unsecureWrongSuffix = '{{unsecure_base_url}}test';
+        $unsecureWrongDomainName = 'http://example.com_test/';
         $securePlaceholder = '{{secure_base_url}}';
         $secureSuffix = '{{secure_base_url}}test/';
         $secureWrongSuffix = '{{secure_base_url}}test';
+        $secureWrongDomainName = 'https://example.com_test/';
 
         return [
             ['', 'not a valid URL'],
             ['', 'example.com'],
             ['', 'http://example.com'],
             ['', 'http://example.com/uri'],
+            ['', $unsecureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_URL, ''],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_URL, $baseSuffix],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_URL, $unsecureSuffix],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_URL, $unsecurePlaceholder],
+            [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_URL, $unsecureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_LINK_URL, ''],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_LINK_URL, $baseSuffix],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_LINK_URL, $unsecureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_LINK_URL, $unsecureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_MEDIA_URL, $unsecureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_MEDIA_URL, $unsecureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_STATIC_URL, $unsecureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_UNSECURE_BASE_STATIC_URL, $unsecureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL, ''],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL, $baseSuffix],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL, $secureSuffix],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL, $securePlaceholder],
+            [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL, $secureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_LINK_URL, ''],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_LINK_URL, $baseSuffix],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_LINK_URL, $secureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_LINK_URL, $secureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_MEDIA_URL, $secureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_MEDIA_URL, $secureWrongDomainName],
             [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_STATIC_URL, $secureWrongSuffix],
+            [\Magento\Store\Model\Store::XML_PATH_SECURE_BASE_STATIC_URL, $secureWrongDomainName],
         ];
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5db97cc36614924ae915b7b924b2c7a1f575e344
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Indexer\Price;
+
+use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\Catalog\Model\Product\Attribute\Source\Status;
+use Magento\Catalog\Model\ResourceModel\Product\Collection;
+use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
+use Magento\Store\Model\Store;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * @magentoAppArea adminhtml
+ */
+class ConfigurableTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
+
+    /**
+     * @var ProductRepositoryInterface
+     */
+    private $productRepository;
+
+    protected function setUp()
+    {
+        $this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class);
+        $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
+    }
+
+    /**
+     * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testGetProductFinalPriceIfOneOfChildIsDisabled()
+    {
+        /** @var Collection $collection */
+        $collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
+            ->create();
+        $configurableProduct = $collection
+            ->addIdFilter([1])
+            ->addMinimalPrice()
+            ->load()
+            ->getFirstItem();
+        $this->assertEquals(10, $configurableProduct->getMinimalPrice());
+
+        $childProduct = $this->productRepository->getById(10, false, null, true);
+        $childProduct->setStatus(Status::STATUS_DISABLED);
+        // update in global scope
+        $currentStoreId = $this->storeManager->getStore()->getId();
+        $this->storeManager->setCurrentStore(Store::ADMIN_CODE);
+        $this->productRepository->save($childProduct);
+        $this->storeManager->setCurrentStore($currentStoreId);
+
+        /** @var Collection $collection */
+        $collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
+            ->create();
+        $configurableProduct = $collection
+            ->addIdFilter([1])
+            ->addMinimalPrice()
+            ->load()
+            ->getFirstItem();
+        $this->assertEquals(20, $configurableProduct->getMinimalPrice());
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php
index ff08056e4b18def3f520d2a5d9f2090b168d5ec8..0d8361b4751e38a96ae4dbb7aadb86510dad92dc 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php
@@ -1,5 +1,7 @@
 <?php
 /**
+ * Creates a simple product to be used for test cases.
+ *
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
@@ -72,7 +74,8 @@ $product->setTypeId(Type::TYPE_SIMPLE)
             'is_in_stock'               => 1,
         ]
     )->setCanSaveCustomOptions(true)
-    ->setHasOptions(true);
+    ->setHasOptions(true)
+    ->setCustomAttribute('test_configurable', 42);
 
 $oldOptions = [
     [
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
index 1576ff90cb38ee4cd89b68766395fa0746d071d6..5f9b9e928b3178f3ae06a8d5a885022cc8e954cc 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
@@ -313,6 +313,8 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
         $this->assertEquals(2, count($addresses));
         $updatedAddress = $this->addressRepository->getById(1);
         $this->assertEquals('update firstname', $updatedAddress->getFirstname());
+        $this->assertTrue($updatedAddress->isDefaultBilling());
+        $this->assertEquals($updatedAddress->getId(), $customer->getDefaultBilling());
         $newAddress = $this->accountManagement->getDefaultShippingAddress($customerId);
         $this->assertEquals('new firstname', $newAddress->getFirstname());
 
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c44e320e64f4d0cfe1646f97642a2080e604ed74
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Controller\Section;
+
+class LoadTest extends \Magento\TestFramework\TestCase\AbstractController
+{
+    public function testLoadInvalidSection()
+    {
+        $expected = [
+            'message' => '&quot;section&lt;invalid&quot; section source is not supported',
+        ];
+        $this->dispatch('/customer/section/load/?sections=section<invalid&update_section_id=false&_=147066166394');
+        self::assertEquals(json_encode($expected), $this->getResponse()->getBody());
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/Config/ReaderTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/Config/ReaderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b57fcb43a1a4326fc80dadcbc8211f6ed35b623
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/Config/ReaderTest.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Directory\Model\Country\Postcode\Config;
+
+class ReaderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Directory\Model\Country\Postcode\Config\Reader
+     */
+    private $reader;
+
+    protected function setUp()
+    {
+        $this->reader = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            \Magento\Directory\Model\Country\Postcode\Config\Reader::class
+        );
+    }
+
+    public function testRead()
+    {
+        $result = $this->reader->read();
+
+        $this->assertArrayHasKey('NL', $result);
+        $this->assertArrayHasKey('pattern_1', $result['NL']);
+        $this->assertArrayHasKey('pattern_2', $result['NL']);
+
+        $this->assertEquals('test1', $result['NL']['pattern_1']['example']);
+        $this->assertEquals('^[0-9]{4}\s[a-zA-Z]{2}$', $result['NL']['pattern_1']['pattern']);
+
+        $this->assertEquals('test2', $result['NL']['pattern_2']['example']);
+        $this->assertEquals('^[0-5]{4}[a-z]{2}$', $result['NL']['pattern_2']['pattern']);
+
+        $this->assertArrayHasKey('NL_NEW', $result);
+        $this->assertArrayHasKey('pattern_1', $result['NL_NEW']);
+
+        $this->assertEquals('test1', $result['NL_NEW']['pattern_1']['example']);
+        $this->assertEquals('^[0-2]{4}[A-Z]{2}$', $result['NL_NEW']['pattern_1']['pattern']);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/DB/Adapter/Pdo/MysqlTest.php b/dev/tests/integration/testsuite/Magento/Framework/DB/Adapter/Pdo/MysqlTest.php
index 8a566a0d4efe55e856716c095f5a3a7e14896af1..14118414859f0d9bced34e393bfb699f22251edf 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/DB/Adapter/Pdo/MysqlTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/DB/Adapter/Pdo/MysqlTest.php
@@ -12,6 +12,7 @@
 namespace Magento\Framework\DB\Adapter\Pdo;
 
 use Magento\Framework\App\ResourceConnection;
+use Zend_Db_Statement_Exception;
 
 class MysqlTest extends \PHPUnit_Framework_TestCase
 {
@@ -32,6 +33,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase
         restore_error_handler();
     }
 
+
     /**
      * Test lost connection re-initializing
      *
@@ -125,9 +127,9 @@ class MysqlTest extends \PHPUnit_Framework_TestCase
     protected function _getConnection()
     {
         if (is_null($this->_connection)) {
-            /** @var $coreResource \Magento\Framework\App\ResourceConnection */
+            /** @var $coreResource ResourceConnection */
             $coreResource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-                ->get(\Magento\Framework\App\ResourceConnection::class);
+                ->get(ResourceConnection::class);
             $this->_connection = $coreResource->getConnection();
         }
         return $this->_connection;
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
index 9acfa6f1caab150b0a0db2d54e87358adf88cf5b..67a6e416973493887912e2e62674108b1694c315 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
@@ -414,6 +414,37 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expectedRecordsCount, $queryResponse->count());
     }
 
+    /**
+     * @magentoDataFixture Magento/Framework/Search/_files/product_configurable.php
+     * @magentoConfigFixture current_store catalog/search/engine mysql
+     */
+    public function testAdvancedSearchCompositeProductWithOutOfStockOption()
+    {
+        /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
+        $attribute = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
+            ->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'test_configurable');
+        /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection $selectOptions */
+        $selectOptions = $this->objectManager
+            ->create(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class)
+            ->setAttributeFilter($attribute->getId());
+
+        $firstOption = $selectOptions->getFirstItem();
+        $firstOptionId = $firstOption->getId();
+        $this->requestBuilder->bind('test_configurable', $firstOptionId);
+        $this->requestBuilder->setRequestName('filter_out_of_stock_child');
+
+        $queryResponse = $this->executeQuery();
+        $this->assertEquals(0, $queryResponse->count());
+
+        $secondOption = $selectOptions->getLastItem();
+        $secondOptionId = $secondOption->getId();
+        $this->requestBuilder->bind('test_configurable', $secondOptionId);
+        $this->requestBuilder->setRequestName('filter_out_of_stock_child');
+
+        $queryResponse = $this->executeQuery();
+        $this->assertEquals(1, $queryResponse->count());
+    }
+
     public function dateDataProvider()
     {
         return [
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..030e0250c3ec7fed4747aed4e168413207c7daf7
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Eav\Api\AttributeRepositoryInterface;
+
+$eavConfig = Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class);
+$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable');
+
+$eavConfig->clear();
+
+/** @var $installer \Magento\Catalog\Setup\CategorySetup */
+$installer = Bootstrap::getObjectManager()->create(\Magento\Catalog\Setup\CategorySetup::class);
+
+if (!$attribute->getId()) {
+
+    /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
+    $attribute = Bootstrap::getObjectManager()->create(
+        \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class
+    );
+
+    /** @var AttributeRepositoryInterface $attributeRepository */
+    $attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepositoryInterface::class);
+
+    $attribute->setData(
+        [
+            'attribute_code' => 'test_configurable',
+            'entity_type_id' => $installer->getEntityTypeId('catalog_product'),
+            'is_global' => 1,
+            'is_user_defined' => 1,
+            'frontend_input' => 'select',
+            'is_unique' => 0,
+            'is_required' => 0,
+            'is_searchable' => 1,
+            'is_visible_in_advanced_search' => 1,
+            'is_comparable' => 0,
+            'is_filterable' => 1,
+            'is_filterable_in_search' => 1,
+            'is_used_for_promo_rules' => 0,
+            'is_html_allowed_on_front' => 1,
+            'is_visible_on_front' => 0,
+            'used_in_product_listing' => 0,
+            'used_for_sort_by' => 0,
+            'frontend_label' => ['Test Configurable'],
+            'backend_type' => 'int',
+            'option' => [
+                'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']],
+                'order' => ['option_0' => 1, 'option_1' => 2],
+            ],
+        ]
+    );
+
+    $attributeRepository->save($attribute);
+}
+
+/* Assign attribute to attribute set */
+$installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId());
+$eavConfig->clear();
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd18100f6d97b4b9b56c9743e8064e0723fdc6c8
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/configurable_attribute_rollback.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+$productCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->get(\Magento\Catalog\Model\ResourceModel\Product\Collection::class);
+foreach ($productCollection as $product) {
+    $product->delete();
+}
+
+$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class);
+$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable');
+if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+    && $attribute->getId()
+) {
+    $attribute->delete();
+}
+$eavConfig->clear();
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php
new file mode 100644
index 0000000000000000000000000000000000000000..590f3c8041c6d819fafa14ef7ddc4d1f2ebccbeb
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\Product\Attribute\Source\Status;
+use Magento\Catalog\Model\Product\Type;
+use Magento\Catalog\Model\Product\Visibility;
+use Magento\Catalog\Setup\CategorySetup;
+use Magento\ConfigurableProduct\Helper\Product\Options\Factory;
+use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
+use Magento\Eav\Api\Data\AttributeOptionInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize();
+
+require __DIR__ . '/configurable_attribute.php';
+
+/** @var ProductRepositoryInterface $productRepository */
+$productRepository = Bootstrap::getObjectManager()
+    ->create(ProductRepositoryInterface::class);
+
+/** @var $installer CategorySetup */
+$installer = Bootstrap::getObjectManager()->create(CategorySetup::class);
+
+/* Create simple products per each option value*/
+/** @var AttributeOptionInterface[] $options */
+$options = $attribute->getOptions();
+
+$attributeValues = [];
+$attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
+$associatedProductIds = [];
+$productIds = [10, 20];
+array_shift($options); //remove the first option which is empty
+
+$isFirstOption = true;
+foreach ($options as $option) {
+    /** @var $product Product */
+    $product = Bootstrap::getObjectManager()->create(Product::class);
+    $productId = array_shift($productIds);
+    $product->setTypeId(Type::TYPE_SIMPLE)
+        ->setId($productId)
+        ->setAttributeSetId($attributeSetId)
+        ->setWebsiteIds([1])
+        ->setName('Configurable Option' . $option->getLabel())
+        ->setSku('simple_' . $productId)
+        ->setPrice($productId)
+        ->setTestConfigurable($option->getValue())
+        ->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE)
+        ->setStatus(Status::STATUS_ENABLED)
+        ->setStockData(
+            [
+                'use_config_manage_stock' => 1,
+                'qty' => 100,
+                'is_qty_decimal' => 0,
+                'is_in_stock' => (int)!$isFirstOption,
+            ]
+        );
+
+    $product = $productRepository->save($product);
+
+    /** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */
+    $stockItem = Bootstrap::getObjectManager()->create(\Magento\CatalogInventory\Model\Stock\Item::class);
+    $stockItem->load($productId, 'product_id');
+
+    if (!$stockItem->getProductId()) {
+        $stockItem->setProductId($productId);
+    }
+    $stockItem->setUseConfigManageStock(1);
+    $stockItem->setQty(1000);
+    $stockItem->setIsQtyDecimal(0);
+    $stockItem->setIsInStock((int)!$isFirstOption);
+    $stockItem->save();
+
+    $attributeValues[] = [
+        'label' => 'test',
+        'attribute_id' => $attribute->getId(),
+        'value_index' => $option->getValue(),
+    ];
+    $associatedProductIds[] = $product->getId();
+    $isFirstOption = false;
+}
+
+/** @var $product Product */
+$product = Bootstrap::getObjectManager()->create(Product::class);
+
+/** @var Factory $optionsFactory */
+$optionsFactory = Bootstrap::getObjectManager()->create(Factory::class);
+
+$configurableAttributesData = [
+    [
+        'attribute_id' => $attribute->getId(),
+        'code' => $attribute->getAttributeCode(),
+        'label' => $attribute->getStoreLabel(),
+        'position' => '0',
+        'values' => $attributeValues,
+    ],
+];
+
+$configurableOptions = $optionsFactory->create($configurableAttributesData);
+
+$extensionConfigurableAttributes = $product->getExtensionAttributes();
+$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions);
+$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds);
+
+$product->setExtensionAttributes($extensionConfigurableAttributes);
+
+// Remove any previously created product with the same id.
+/** @var \Magento\Framework\Registry $registry */
+$registry = Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+try {
+    $productToDelete = $productRepository->getById(1);
+    $productRepository->delete($productToDelete);
+
+    /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */
+    $itemResource = Bootstrap::getObjectManager()->get(\Magento\Quote\Model\ResourceModel\Quote\Item::class);
+    $itemResource->getConnection()->delete(
+        $itemResource->getMainTable(),
+        'product_id = ' . $productToDelete->getId()
+    );
+} catch (\Exception $e) {
+    // Nothing to remove
+}
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
+
+$product->setTypeId(Configurable::TYPE_CODE)
+    ->setId(1)
+    ->setAttributeSetId($attributeSetId)
+    ->setWebsiteIds([1])
+    ->setName('Configurable Product')
+    ->setSku('configurable')
+    ->setVisibility(Visibility::VISIBILITY_BOTH)
+    ->setStatus(Status::STATUS_ENABLED)
+    ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);
+
+$productRepository->save($product);
+//
+///** @var \Magento\Catalog\Model\Indexer\Product\Eav\Processor $eavIndexer */
+//$eavIndexer = Bootstrap::getObjectManager()
+//    ->get(\Magento\Catalog\Model\Indexer\Product\Eav\Processor::class);
+//$eavIndexer->reindexAll();
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ba4e3abe21cc14a75a66270d22ea262dffeb788
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = $objectManager->get(\Magento\Framework\Registry::class);
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
+$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+
+foreach (['simple_10', 'simple_20', 'configurable'] as $sku) {
+    try {
+        $product = $productRepository->get($sku, false, null, true);
+
+        $stockStatus = $objectManager->create(\Magento\CatalogInventory\Model\Stock\Status::class);
+        $stockStatus->load($product->getEntityId(), 'product_id');
+        $stockStatus->delete();
+
+        $productRepository->delete($product);
+    } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+        //Product already removed
+    }
+}
+
+require __DIR__ . '/configurable_attribute_rollback.php';
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml
index 0cdfa11c3b6b5744abbd911e063553cd23039cc5..4cdc9a93e1f1f0ee093b8e0fd8e555a157fce851 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml
@@ -387,4 +387,24 @@
         <from>0</from>
         <size>10</size>
     </request>
+    <request query="filter_out_of_stock_child" index="catalogsearch_fulltext">
+        <dimensions>
+            <dimension name="scope" value="default"/>
+        </dimensions>
+        <queries>
+            <query xsi:type="boolQuery" name="filter_out_of_stock_child" boost="1">
+                <queryReference clause="must" ref="test_configurable"/>
+            </query>
+            <query xsi:type="filteredQuery" name="test_configurable">
+                <filterReference clause="must" ref="test_configurable_filter"/>
+            </query>
+        </queries>
+        <filters>
+            <filter xsi:type="termFilter" name="test_configurable_filter" field="test_configurable" value="$test_configurable$"/>
+        </filters>
+        <aggregations/>
+        <from>0</from>
+        <size>10</size>
+    </request>
+
 </requests>
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
index f9f8f1ffba91a55536c9d2221b68dc85b702e7f0..19feb33748c840b6c87f506ffd450897e2ace286 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
@@ -593,7 +593,8 @@
                         <label>Express Checkout</label>
                         <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded</frontend_model>
                         <field id="business_account" translate="label comment tooltip" showInDefault="1" showInWebsite="1" sortOrder="5">
-                            <label>Email Associated with PayPal Merchant Account</label>
+                            <label>Email Associated with PayPal Merchant Account (Optional)</label>
+                            <frontend_class>not-required</frontend_class>
                             <comment>
                                 <![CDATA[<a href="http://www.magentocommerce.com/paypal">Start accepting payments via PayPal!</a>]]>
                             </comment>
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/composer.json b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/composer.json
index 222e5ff822b043185e44719804e0af75d8809c6e..a004d3a86b5b9d0c68ec096ab8beff48fa1e51c5 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/composer.json
+++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/composer.json
@@ -1,7 +1,7 @@
 {
     "name": "magento/module-a",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "0.1",
         "magento/module-b": "0.1"
     },
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/composer.json b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/composer.json
index 57944758267fd668f541b34586a8eb9f7acd9c98..0626cc6a84d055757c32d9192cc7f2682696912f 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/composer.json
+++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/composer.json
@@ -1,7 +1,7 @@
 {
     "name": "magento/module-b",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "0.74.0-beta6",
         "magento/module-a": "0.1"
     },
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Controller/UrlCheckTest.php b/dev/tests/integration/testsuite/Magento/Setup/Controller/UrlCheckTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6fe9ec2ee3ea13ef4b2b5881e4970f7aa99e9447
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Setup/Controller/UrlCheckTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Setup\Controller;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Zend\Stdlib\RequestInterface as Request;
+use Zend\View\Model\JsonModel;
+
+class UrlCheckTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var UrlCheck
+     */
+    private $controller;
+
+    protected function setUp()
+    {
+        $this->controller = Bootstrap::getObjectManager()->create(UrlCheck::class);
+    }
+
+    /**
+     * @param array $requestContent
+     * @param bool $successUrl
+     * @param bool $successSecureUrl
+     * @return void
+     * @dataProvider indexActionDataProvider
+     */
+    public function testIndexAction($requestContent, $successUrl, $successSecureUrl)
+    {
+        $requestMock = $this->getMockBuilder(Request::class)
+            ->getMockForAbstractClass();
+        $requestMock->expects($this->once())
+            ->method('getContent')
+            ->willReturn(json_encode($requestContent));
+
+        $requestProperty = new \ReflectionProperty(get_class($this->controller), 'request');
+        $requestProperty->setAccessible(true);
+        $requestProperty->setValue($this->controller, $requestMock);
+
+        $resultModel = new JsonModel(['successUrl' => $successUrl, 'successSecureUrl' => $successSecureUrl]);
+
+        $this->assertEquals($resultModel, $this->controller->indexAction());
+    }
+
+    /**
+     * @return array
+     */
+    public function indexActionDataProvider()
+    {
+        return [
+            [
+                'requestContent' => [
+                    'address' => [
+                        'actual_base_url' => 'http://example.com/'
+                    ],
+                    'https' => [
+                        'text' => 'https://example.com/',
+                        'admin' => true,
+                        'front' => false
+                    ],
+                ],
+                'successUrl' => true,
+                'successSecureUrl' => true
+            ],
+            [
+                'requestContent' => [
+                    'address' => [
+                        'actual_base_url' => 'http://example.com/folder/'
+                    ],
+                    'https' => [
+                        'text' => 'https://example.com/folder_name/',
+                        'admin' => false,
+                        'front' => true
+                    ],
+                ],
+                'successUrl' => true,
+                'successSecureUrl' => true
+            ],
+            [
+                'requestContent' => [
+                    'address' => [
+                        'actual_base_url' => 'ftp://example.com/'
+                    ],
+                    'https' => [
+                        'text' => 'https://example.com_test/',
+                        'admin' => true,
+                        'front' => true
+                    ],
+                ],
+                'successUrl' => false,
+                'successSecureUrl' => false
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/composer.json b/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/composer.json
index 920dc1289b0cfa00cd696b35fb495434830850f6..47f9eb415d7badb00345e5436e2c10bd64532c2f 100644
--- a/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/composer.json
+++ b/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/admin-Magento_Catalog",
     "description": "N/A",
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "magento/framework": "0.1.0-alpha103"
     },
     "type": "magento2-theme",
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
index 52244463a535693746eddf8f4e0d07b05cf9de08..ff12618b399639fb8c4f56a422828cbb7c0c1e67 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
@@ -100,7 +100,7 @@ Element 'filterReference': The attribute 'clause' is required but missing.
 Element 'filterReference': The attribute 'ref' is required but missing.
 Element 'filter': The attribute 'field' is required but missing.
 Element 'metric', attribute 'type': [facet 'enumeration'] " .
-                "The value 'sumasdasd' is not an element of the set {'sum', 'count', 'min', 'max'}.
+                "The value 'sumasdasd' is not an element of the set {'sum', 'count', 'min', 'max', 'avg'}.
 Element 'metric', attribute 'type': 'sumasdasd' is not a valid value of the local atomic type.
 Element 'bucket': Missing child element(s). Expected is one of ( metrics, ranges ).
 Element 'request': Missing child element(s). Expected is ( from )."
diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
index cfbeb4f54c9e29d2f7b320b57c51ae7a7b31a676..9af29ab2c458d8a8b09a73e570695d133bd7a123 100644
--- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
+++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
@@ -341,6 +341,9 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
     /**
      * Creates a PDO object and connects to the database.
      *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     *
      * @return void
      * @throws \Zend_Db_Adapter_Exception
      */
@@ -371,6 +374,10 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
             list($this->_config['host'], $this->_config['port']) = explode(':', $this->_config['host']);
         }
 
+        if (!isset($this->_config['driver_options'][\PDO::MYSQL_ATTR_MULTI_STATEMENTS])) {
+            $this->_config['driver_options'][\PDO::MYSQL_ATTR_MULTI_STATEMENTS] = false;
+        }
+
         $this->logger->startTimer();
         parent::_connect();
         $this->logger->logStats(LoggerInterface::TYPE_CONNECT, '');
@@ -562,6 +569,7 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
      * @throws \Zend_Db_Adapter_Exception To re-throw \PDOException.
      * @throws LocalizedException In case multiple queries are attempted at once, to protect from SQL injection
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @deprecated
      */
     public function multiQuery($sql, $bind = [])
     {
@@ -728,6 +736,8 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
      * @return array
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
+
+     * @deprecated
      */
     protected function _splitMultiQuery($sql)
     {
diff --git a/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php b/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
index 10f1289b90c1841c7e5c9c014b3943132ab8e5f3..ad4746a36513c4dd028b1c81d27dbbcec70148eb 100644
--- a/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
+++ b/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
@@ -31,7 +31,7 @@ class MaliciousCode implements \Zend_Filter_Interface
         //js attributes
         '/(ondblclick|onclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onload|onunload|onerror)=[^<]*(?=\/*\>)/Uis',
         //tags
-        '/<\/?(script|meta|link|frame|iframe).*>/Uis',
+        '/<\/?(script|meta|link|frame|iframe|object).*>/Uis',
         //base64 usage
         '/src=[^<]*base64[^<]*(?=\/*\>)/Uis',
     ];
diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/Input/MaliciousCodeTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/Input/MaliciousCodeTest.php
index 512d8e89750bc24c666e58237668ad63f7e440b8..93de72e3c57c5610882aece936c9346be40dea64 100644
--- a/lib/internal/Magento/Framework/Filter/Test/Unit/Input/MaliciousCodeTest.php
+++ b/lib/internal/Magento/Framework/Filter/Test/Unit/Input/MaliciousCodeTest.php
@@ -89,6 +89,7 @@ class MaliciousCodeTest extends \PHPUnit_Framework_TestCase
                     'Tag is removed <link>SomeLink</link>',
                     'Tag is removed <frame>SomeFrame</frame>',
                     'Tag is removed <iframe>SomeIFrame</iframe>',
+                    'Tag is removed <object>SomeObject</object>',
                 ],
                 [
                     'Tag is removed SomeScript',
@@ -96,6 +97,7 @@ class MaliciousCodeTest extends \PHPUnit_Framework_TestCase
                     'Tag is removed SomeLink',
                     'Tag is removed SomeFrame',
                     'Tag is removed SomeIFrame',
+                    'Tag is removed SomeObject',
                 ],
             ],
             'Base64' => [
diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
index fb00e9f59c83097b13274e47e7b0a7a52634ecc2..181783c7b2115d8a216c681077e116e98344d15c 100644
--- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
+++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
@@ -20,7 +20,15 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
      *
      * @var array
      */
-    protected $_config = [];
+    protected $_config = [
+        'protocols' => (CURLPROTO_HTTP
+            | CURLPROTO_HTTPS
+            | CURLPROTO_FTP
+            | CURLPROTO_FTPS
+        ),
+        'verifypeer' => true,
+        'verifyhost' => 2,
+    ];
 
     /**
      * Curl handle
@@ -41,7 +49,10 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
         'ssl_cert'     => CURLOPT_SSLCERT,
         'userpwd'      => CURLOPT_USERPWD,
         'useragent'    => CURLOPT_USERAGENT,
-        'referer'      => CURLOPT_REFERER
+        'referer'      => CURLOPT_REFERER,
+        'protocols'    => CURLOPT_PROTOCOLS,
+        'verifypeer'   => CURLOPT_SSL_VERIFYPEER,
+        'verifyhost'   => CURLOPT_SSL_VERIFYHOST,
     ];
 
     /**
@@ -55,8 +66,6 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
      * Apply current configuration array to transport resource
      *
      * @return \Magento\Framework\HTTP\Adapter\Curl
-     * @SuppressWarnings(PHPMD.NPathComplexity)
-     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
      */
     protected function _applyConfig()
     {
@@ -65,22 +74,28 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
             curl_setopt($this->_getResource(), $option, $value);
         }
 
-        if (empty($this->_config)) {
-            return $this;
+        // apply config options
+        foreach ($this->getDefaultConfig() as $option => $value) {
+            curl_setopt($this->_getResource(), $option, $value);
         }
 
-        $verifyPeer = isset($this->_config['verifypeer']) ? $this->_config['verifypeer'] : true;
-        curl_setopt($this->_getResource(), CURLOPT_SSL_VERIFYPEER, $verifyPeer);
-
-        $verifyHost = isset($this->_config['verifyhost']) ? $this->_config['verifyhost'] : 2;
-        curl_setopt($this->_getResource(), CURLOPT_SSL_VERIFYHOST, $verifyHost);
+        return $this;
+    }
 
-        foreach ($this->_config as $param => $curlOption) {
+    /**
+     * Get default options
+     *
+     * @return array
+     */
+    private function getDefaultConfig()
+    {
+        $config = [];
+        foreach (array_keys($this->_config) as $param) {
             if (array_key_exists($param, $this->_allowedParams)) {
-                curl_setopt($this->_getResource(), $this->_allowedParams[$param], $this->_config[$param]);
+                $config[$this->_allowedParams[$param]] = $this->_config[$param];
             }
         }
-        return $this;
+        return $config;
     }
 
     /**
@@ -116,7 +131,9 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
      */
     public function setConfig($config = [])
     {
-        $this->_config = $config;
+        foreach ($config as $key => $value) {
+            $this->_config[$key] = $value;
+        }
         return $this;
     }
 
@@ -268,6 +285,13 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
 
         $multihandle = curl_multi_init();
 
+        // add default parameters
+        foreach ($this->getDefaultConfig() as $defaultOption => $defaultValue) {
+            if (!isset($options[$defaultOption])) {
+                $options[$defaultOption] = $defaultValue;
+            }
+        }
+
         foreach ($urls as $key => $url) {
             $handles[$key] = curl_init();
             curl_setopt($handles[$key], CURLOPT_URL, $url);
diff --git a/lib/internal/Magento/Framework/HTTP/Test/Unit/Adapter/CurlTest.php b/lib/internal/Magento/Framework/HTTP/Test/Unit/Adapter/CurlTest.php
index 255be0a5596a622151e9e1091841d4f5ff8bf58b..37cd33d18683062ab48d16ae8aae2733def7a75e 100644
--- a/lib/internal/Magento/Framework/HTTP/Test/Unit/Adapter/CurlTest.php
+++ b/lib/internal/Magento/Framework/HTTP/Test/Unit/Adapter/CurlTest.php
@@ -10,10 +10,14 @@ use \Magento\Framework\HTTP\Adapter\Curl;
 
 class CurlTest extends \PHPUnit_Framework_TestCase
 {
-    /** @var Curl */
+    /**
+     * @var Curl
+     */
     protected $model;
 
-    /** @var \Closure */
+    /**
+     * @var \Closure
+     */
     public static $curlExectClosure;
 
     protected function setUp()
@@ -42,4 +46,3 @@ class CurlTest extends \PHPUnit_Framework_TestCase
         ];
     }
 }
-
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
index 8ddb6255b9b862a37dea1aaefd742a4c03923d24..3d280f1224b8f3bb2e9082436fa7524308730387 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
@@ -71,6 +71,7 @@ class Adapter implements AdapterInterface
 
     /**
      * {@inheritdoc}
+     * @throws \LogicException
      */
     public function query(RequestInterface $request)
     {
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder/Metrics.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder/Metrics.php
index 5860591eaf702494614ec89a90e816e159ffeb12..cf544eb126e1195096603979bd7378e08f44730d 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder/Metrics.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder/Metrics.php
@@ -14,7 +14,7 @@ class Metrics
      *
      * @var string[]
      */
-    private $mapMetrics = ['count', 'sum', 'min', 'max', 'avg'];
+    private $allowedMetrics = ['count', 'sum', 'min', 'max', 'avg'];
 
     /**
      * Build metrics for Select->columns
@@ -30,7 +30,7 @@ class Metrics
 
         foreach ($metrics as $metric) {
             $metricType = $metric->getType();
-            if (in_array($metricType, $this->mapMetrics)) {
+            if (in_array($metricType, $this->allowedMetrics, true)) {
                 $selectAggregations[$metricType] = "$metricType(main_table.value)";
             }
         }
diff --git a/lib/internal/Magento/Framework/Search/etc/requests.xsd b/lib/internal/Magento/Framework/Search/etc/requests.xsd
index f185699c5a5e890757850fa8985b2e0400c56c35..294232513b7d2ec1938e243423a3113e151fd0c0 100644
--- a/lib/internal/Magento/Framework/Search/etc/requests.xsd
+++ b/lib/internal/Magento/Framework/Search/etc/requests.xsd
@@ -263,6 +263,7 @@
               <xs:enumeration value="count" />
               <xs:enumeration value="min" />
               <xs:enumeration value="max" />
+              <xs:enumeration value="avg" />
             </xs:restriction>
           </xs:simpleType>
         </xs:attribute>
diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php
index e8013b024f4384e2c9b2261daed97a2ccbfb7f03..a517f1fd0b0b744cd44bad6b78ddd9c687a1fab5 100644
--- a/lib/internal/Magento/Framework/Session/SessionManager.php
+++ b/lib/internal/Magento/Framework/Session/SessionManager.php
@@ -298,6 +298,7 @@ class SessionManager implements SessionManagerInterface
             return;
         }
 
+        session_regenerate_id(true);
         session_destroy();
         if ($options['send_expire_cookie']) {
             $this->expireSessionCookie();
diff --git a/lib/internal/Magento/Framework/Validator/AllowedProtocols.php b/lib/internal/Magento/Framework/Validator/AllowedProtocols.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c7bbb3d997236aae0e7cc91994505af78620957
--- /dev/null
+++ b/lib/internal/Magento/Framework/Validator/AllowedProtocols.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Protocol validator
+ *
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Validator;
+
+use \Zend\Uri\Uri;
+
+/**
+ * Check is URI starts from allowed protocol
+ *
+ * Class AllowedProtocols
+ * @package Magento\Framework\Validator
+ */
+class AllowedProtocols extends AbstractValidator
+{
+    /**
+     * List of supported protocols
+     *
+     * @var array
+     */
+    private $listOfProtocols = [
+        'http',
+        'https',
+    ];
+
+    /**
+     * Constructor.
+     * @param array $listOfProtocols
+     */
+    public function __construct($listOfProtocols = [])
+    {
+        if (count($listOfProtocols)) {
+            $this->listOfProtocols = $listOfProtocols;
+        }
+    }
+
+    /**
+     * Validate URI
+     *
+     * @param string $value
+     * @return bool
+     */
+    public function isValid($value)
+    {
+        $uri = new Uri($value);
+        $isValid = in_array(
+            strtolower($uri->getScheme()),
+            $this->listOfProtocols
+        );
+        if (!$isValid) {
+            $this->_addMessages(["Protocol isn't allowed"]);
+        }
+        return $isValid;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Validator/Test/Unit/UrlTest.php b/lib/internal/Magento/Framework/Validator/Test/Unit/UrlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d66f84289424920d3d8aca1e5b39e76fa1ad1503
--- /dev/null
+++ b/lib/internal/Magento/Framework/Validator/Test/Unit/UrlTest.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Validator\Test\Unit;
+
+use Magento\Framework\Validator\Url as UrlValidator;
+
+class UrlTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var UrlValidator
+     */
+    private $validator;
+
+    protected function setUp()
+    {
+        $this->validator = new UrlValidator();
+    }
+
+    /**
+     * @param array $allowedSchemes
+     * @param string $url
+     * @param bool $expectedResult
+     * @dataProvider isValidDataProvider
+     */
+    public function testIsValid(array $allowedSchemes, $url, $expectedResult)
+    {
+        $this->assertSame($expectedResult, $this->validator->isValid($url, $allowedSchemes));
+    }
+
+    /**
+     * @return array
+     */
+    public function isValidDataProvider()
+    {
+        return [
+            [
+                'allowedSchemes' => [],
+                'url' => 'http://example.com',
+                'expectedResult' => true,
+            ],
+            [
+                'allowedSchemes' => ['http'],
+                'url' => 'http://example.com',
+                'expectedResult' => true,
+            ],
+            [
+                'allowedSchemes' => [],
+                'url' => 'https://example.com',
+                'expectedResult' => true,
+            ],
+            [
+                'allowedSchemes' => ['https'],
+                'url' => 'https://example.com',
+                'expectedResult' => true,
+            ],
+            [
+                'allowedSchemes' => [],
+                'url' => 'http://example.com_test',
+                'expectedResult' => false,
+            ],
+            [
+                'allowedSchemes' => [],
+                'url' => 'ftp://example.com',
+                'expectedResult' => true,
+            ],
+            [
+                'allowedSchemes' => ['ftp'],
+                'url' => 'ftp://example.com',
+                'expectedResult' => true,
+            ],
+        ];
+    }
+}
diff --git a/lib/internal/Magento/Framework/Validator/Url.php b/lib/internal/Magento/Framework/Validator/Url.php
new file mode 100644
index 0000000000000000000000000000000000000000..27262009b2d200bc354947208bfd075898a3ac0e
--- /dev/null
+++ b/lib/internal/Magento/Framework/Validator/Url.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Validator;
+
+/**
+ * Class Url validates URL and checks that it has allowed scheme
+ */
+class Url
+{
+    /**
+     * Validate URL and check that it has allowed scheme
+     *
+     * @param string $value
+     * @param array $allowedSchemes
+     * @return bool
+     */
+    public function isValid($value, array $allowedSchemes = [])
+    {
+        $isValid = true;
+
+        if (!filter_var($value, FILTER_VALIDATE_URL)) {
+            $isValid = false;
+        }
+
+        if ($isValid && !empty($allowedSchemes)) {
+            $url = parse_url($value);
+            if (empty($url['scheme']) || !in_array($url['scheme'], $allowedSchemes)) {
+                $isValid = false;
+            }
+        }
+
+        return $isValid;
+    }
+}
diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json
index 98338ed4b099d202ce7d8e482b2bda9e3a675068..926d4cc54c140efb315921432b8afc5ebd237cf7 100644
--- a/lib/internal/Magento/Framework/composer.json
+++ b/lib/internal/Magento/Framework/composer.json
@@ -8,7 +8,7 @@
         "AFL-3.0"
     ],
     "require": {
-        "php": "~5.6.0|7.0.2|7.0.4|~7.0.6",
+        "php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
         "ext-spl": "*",
         "ext-dom": "*",
         "ext-simplexml": "*",
diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js
index 3041a177185cf1dfa5bda6e233a2c58a0282d0de..eed9c676b4c90ce1a944d9e7c5ce88a815af08cf 100644
--- a/lib/web/mage/validation.js
+++ b/lib/web/mage/validation.js
@@ -1441,17 +1441,19 @@
      * Validate single element.
      *
      * @param {Element} element
+     * @param {Object} config
      * @returns {*}
      */
-    $.validator.validateSingleElement = function (element) {
+    $.validator.validateSingleElement = function (element, config) {
         var errors = {},
             valid = true,
             validateConfig = {
                 errorElement: 'label',
                 ignore: '.ignore-validate'
             },
-            form, validator, classes;
+            form, validator, classes, elementValue;
 
+        $.extend(validateConfig, config);
         element = $(element).not(validateConfig.ignore);
 
         if (!element.length) {
@@ -1475,7 +1477,11 @@
         validator.toShow = validator.toHide = $([]);
 
         $.each(classes, $.proxy(function (i, className) {
-            if (this.methods[className] && !this.methods[className](element.val(), element.get(0))) {
+            elementValue = element.val();
+            if (element.is(':checkbox') || element.is(':radio')) {
+                elementValue = element.is(':checked') || null;
+            }
+            if (this.methods[className] && !this.methods[className](elementValue, element.get(0))) {
                 valid = false;
                 errors[element.get(0).name] = this.messages[className];
                 validator.invalid[element.get(0).name] = true;
diff --git a/setup/config/di.config.php b/setup/config/di.config.php
index 804f18462065aa3af62cbba93d1fa5339b548f7e..b0dcb452ccd4030cf9736e6ab4a521199d1a899f 100644
--- a/setup/config/di.config.php
+++ b/setup/config/di.config.php
@@ -21,6 +21,7 @@ return [
             \Magento\Setup\Controller\Environment::class,
             \Magento\Setup\Controller\DependencyCheck::class,
             \Magento\Setup\Controller\DatabaseCheck::class,
+            \Magento\Setup\Controller\UrlCheck::class,
             \Magento\Setup\Controller\ValidateAdminCredentials::class,
             \Magento\Setup\Controller\AddDatabase::class,
             \Magento\Setup\Controller\WebConfiguration::class,
diff --git a/setup/pub/magento/setup/web-configuration.js b/setup/pub/magento/setup/web-configuration.js
index 03a0fc7845dda90225d3be867f4bf9ddd1621f63..47458056b33b52f8913017a5f6f7c6317fd98347 100644
--- a/setup/pub/magento/setup/web-configuration.js
+++ b/setup/pub/magento/setup/web-configuration.js
@@ -5,7 +5,7 @@
 
 'use strict';
 angular.module('web-configuration', ['ngStorage'])
-    .controller('webConfigurationController', ['$scope', '$state', '$localStorage', function ($scope, $state, $localStorage) {
+    .controller('webConfigurationController', ['$scope', '$state', '$localStorage', '$http', function ($scope, $state, $localStorage, $http) {
         $scope.config = {
             address: {
                 base_url: '',
@@ -119,4 +119,28 @@ angular.module('web-configuration', ['ngStorage'])
                 $scope.webconfig.submitted = false;
             }
         });
+
+        // Validate URL
+        $scope.validateUrl = function () {
+            if (!$scope.webconfig.submitted) {
+                $http.post('index.php/url-check', $scope.config)
+                    .success(function (data) {
+                        $scope.validateUrl.result = data;
+                        if ($scope.validateUrl.result.successUrl && $scope.validateUrl.result.successSecureUrl) {
+                            $scope.nextState();
+                        }
+                        if (!$scope.validateUrl.result.successUrl) {
+                            $scope.webconfig.submitted = true;
+                            $scope.webconfig.base_url.$setValidity('url', false);
+                        }
+                        if (!$scope.validateUrl.result.successSecureUrl) {
+                            $scope.webconfig.submitted = true;
+                            $scope.webconfig.https.$setValidity('url', false);
+                        }
+                    })
+                    .error(function (data) {
+                        $scope.validateUrl.failed = data;
+                    });
+            }
+        };
     }]);
diff --git a/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php b/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php
index 928fe1e3d4b8d32f7bc4656bf6c00ac500972234..f1098af2db00916e328f515a2a88696553603f78 100644
--- a/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php
@@ -16,11 +16,10 @@ use Magento\Setup\Model\StoreConfigurationDataMapper;
 use Magento\Setup\Model\ObjectManagerProvider;
 use Magento\Framework\ObjectManagerInterface;
 use Magento\Framework\Exception\LocalizedException;
-use Magento\Store\Model\Store;
-use Magento\Framework\Validator\Locale;
-use Magento\Framework\Validator\Timezone;
-use Magento\Framework\Validator\Currency;
-use Magento\Framework\Url\Validator;
+use Magento\Framework\Validator\Locale as LocaleValidator;
+use Magento\Framework\Validator\Timezone as TimezoneValidator;
+use Magento\Framework\Validator\Currency as CurrencyValidator;
+use Magento\Framework\Validator\Url as UrlValidator;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -43,24 +42,57 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand
      * Object Manager
      *
      * @var ObjectManagerInterface
+     * @deprecated
      */
     private $objectManager;
 
+    /**
+     * @var LocaleValidator
+     */
+    private $localeValidator;
+
+    /**
+     * @var TimezoneValidator
+     */
+    private $timezoneValidator;
+
+    /**
+     * @var CurrencyValidator
+     */
+    private $currencyValidator;
+
+    /**
+     * @var UrlValidator
+     */
+    private $urlValidator;
+
     /**
      * Inject dependencies
      *
      * @param InstallerFactory $installerFactory
      * @param DeploymentConfig $deploymentConfig
      * @param ObjectManagerProvider $objectManagerProvider
+     * @param LocaleValidator $localeValidator,
+     * @param TimezoneValidator $timezoneValidator,
+     * @param CurrencyValidator $currencyValidator,
+     * @param UrlValidator $urlValidator
      */
     public function __construct(
         InstallerFactory $installerFactory,
         DeploymentConfig $deploymentConfig,
-        ObjectManagerProvider $objectManagerProvider
+        ObjectManagerProvider $objectManagerProvider,
+        LocaleValidator $localeValidator,
+        TimezoneValidator $timezoneValidator,
+        CurrencyValidator $currencyValidator,
+        UrlValidator $urlValidator
     ) {
         $this->installerFactory = $installerFactory;
         $this->deploymentConfig = $deploymentConfig;
         $this->objectManager = $objectManagerProvider->get();
+        $this->localeValidator = $localeValidator;
+        $this->timezoneValidator = $timezoneValidator;
+        $this->currencyValidator = $currencyValidator;
+        $this->urlValidator = $urlValidator;
         parent::__construct();
     }
 
@@ -173,6 +205,7 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand
     public function validate(InputInterface $input)
     {
         $errors = [];
+        $errorMsg = '';
         $options = $input->getOptions();
         foreach ($options as $key => $value) {
             if (!$value) {
@@ -180,99 +213,69 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand
             }
             switch ($key) {
                 case StoreConfigurationDataMapper::KEY_BASE_URL:
-                    /** @var Validator $url */
                     if (strcmp($value, '{{base_url}}') == 0) {
                         break;
                     }
-                    $url = $this->objectManager->get(\Magento\Framework\Url\Validator::class);
-                    if (!$url->isValid($value)) {
-                        $errorMsgs = $url->getMessages();
-                        $errors[] = '<error>' . 'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL
-                            . '\': ' . $errorMsgs[Validator::INVALID_URL] .'</error>';
-                    }
+                    $errorMsg = $this->validateUrl(
+                        $value,
+                        StoreConfigurationDataMapper::KEY_BASE_URL,
+                        ['http', 'https']
+                    );
+
                     break;
                 case StoreConfigurationDataMapper::KEY_LANGUAGE:
-                    /** @var Locale $lists */
-                    $lists = $this->objectManager->get(\Magento\Framework\Validator\Locale::class);
-                    $errorMsg = $this->validateCodes($lists, $value, StoreConfigurationDataMapper::KEY_LANGUAGE);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
+                    $errorMsg = $this->validateCodes(
+                        $this->localeValidator,
+                        $value,
+                        StoreConfigurationDataMapper::KEY_LANGUAGE
+                    );
                     break;
                 case StoreConfigurationDataMapper::KEY_TIMEZONE:
-                    /** @var Timezone $lists */
-                    $lists = $this->objectManager->get(\Magento\Framework\Validator\Timezone::class);
-                    $errorMsg = $this->validateCodes($lists, $value, StoreConfigurationDataMapper::KEY_TIMEZONE);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
+                    $errorMsg = $this->validateCodes(
+                        $this->timezoneValidator,
+                        $value,
+                        StoreConfigurationDataMapper::KEY_TIMEZONE
+                    );
                     break;
                 case StoreConfigurationDataMapper::KEY_CURRENCY:
-                    /** @var Currency $lists */
-                    $lists = $this->objectManager->get(\Magento\Framework\Validator\Currency::class);
-                    $errorMsg = $this->validateCodes($lists, $value, StoreConfigurationDataMapper::KEY_CURRENCY);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
+                    $errorMsg = $this->validateCodes(
+                        $this->currencyValidator,
+                        $value,
+                        StoreConfigurationDataMapper::KEY_CURRENCY
+                    );
                     break;
                 case StoreConfigurationDataMapper::KEY_USE_SEF_URL:
                     $errorMsg = $this->validateBinaryValue($value, StoreConfigurationDataMapper::KEY_USE_SEF_URL);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
                     break;
                 case StoreConfigurationDataMapper::KEY_IS_SECURE:
                     $errorMsg = $this->validateBinaryValue($value, StoreConfigurationDataMapper::KEY_IS_SECURE);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
                     break;
                 case StoreConfigurationDataMapper::KEY_BASE_URL_SECURE:
-                    try {
-                        /** @var Validator $url */
-                        $url = $this->objectManager->get(\Magento\Framework\Url\Validator::class);
-                        $errorMsgs = '';
-                        if (!$url->isValid($value)) {
-                            $errorMsgs = $url->getMessages();
-                            if (!empty($errorMsgs)) {
-                                $errors[] = '<error>' . 'Command option \''
-                                    . StoreConfigurationDataMapper::KEY_BASE_URL_SECURE
-                                    . '\': ' . $errorMsgs[Validator::INVALID_URL] .'</error>';
-                            }
-                        }
-                        if (empty($errorMsgs) && strpos($value, 'https:') === false) {
-                            throw new LocalizedException(new \Magento\Framework\Phrase("Invalid secure URL."));
-                        }
-                    } catch (LocalizedException $e) {
-                        $errors[] = '<error>' . 'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL_SECURE
-                            . '\': ' . $e->getLogMessage() .'</error>';
-                    }
+                    $errorMsg = $this->validateUrl(
+                        $value,
+                        StoreConfigurationDataMapper::KEY_BASE_URL_SECURE,
+                        ['https']
+                    );
                     break;
                 case StoreConfigurationDataMapper::KEY_IS_SECURE_ADMIN:
                     $errorMsg = $this->validateBinaryValue($value, StoreConfigurationDataMapper::KEY_IS_SECURE_ADMIN);
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
                     break;
                 case StoreConfigurationDataMapper::KEY_ADMIN_USE_SECURITY_KEY:
                     $errorMsg = $this->validateBinaryValue(
                         $value,
                         StoreConfigurationDataMapper::KEY_ADMIN_USE_SECURITY_KEY
                     );
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
                     break;
                 case StoreConfigurationDataMapper::KEY_JS_LOGGING:
                     $errorMsg = $this->validateBinaryValue(
                         $value,
                         StoreConfigurationDataMapper::KEY_JS_LOGGING
                     );
-                    if ($errorMsg !== '') {
-                        $errors[] = $errorMsg;
-                    }
                     break;
             }
+            if ($errorMsg !== '') {
+                $errors[] = $errorMsg;
+            }
         }
         return $errors;
     }
@@ -296,7 +299,7 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand
     /**
      * Validate codes for languages, currencies or timezones
      *
-     * @param Locale|Timezone|Currency  $lists
+     * @param LocaleValidator|TimezoneValidator|CurrencyValidator  $lists
      * @param string  $code
      * @param string  $type
      * @return string
@@ -310,4 +313,31 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand
         }
         return $errorMsg;
     }
+
+    /**
+     * Validate URL
+     *
+     * @param string $url
+     * @param string $option
+     * @param array $allowedSchemes
+     * @return string
+     */
+    private function validateUrl($url, $option, array $allowedSchemes)
+    {
+        $errorMsg = '';
+
+        if (!$this->urlValidator->isValid($url, $allowedSchemes)) {
+            $errorTemplate = '<error>Command option \'%s\': Invalid URL \'%s\'.'
+                . ' Domain Name should contain only letters, digits and hyphen.'
+                . ' And you should use only following schemes: \'%s\'.</error>';
+            $errorMsg = sprintf(
+                $errorTemplate,
+                $option,
+                $url,
+                implode(', ', $allowedSchemes)
+            );
+        }
+
+        return $errorMsg;
+    }
 }
diff --git a/setup/src/Magento/Setup/Controller/UrlCheck.php b/setup/src/Magento/Setup/Controller/UrlCheck.php
new file mode 100644
index 0000000000000000000000000000000000000000..08a0d50404c0a2e457a2646a30860d1f958f14d3
--- /dev/null
+++ b/setup/src/Magento/Setup/Controller/UrlCheck.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Setup\Controller;
+
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\View\Model\JsonModel;
+use Zend\Json\Json;
+use Magento\Framework\Validator\Url as UrlValidator;
+
+class UrlCheck extends AbstractActionController
+{
+    /**
+     * @var UrlValidator
+     */
+    private $urlValidator;
+
+    /**
+     * @param UrlValidator $urlValidator
+     */
+    public function __construct(UrlValidator $urlValidator)
+    {
+        $this->urlValidator = $urlValidator;
+    }
+
+    /**
+     * Validate URL
+     *
+     * @return JsonModel
+     */
+    public function indexAction()
+    {
+        $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY);
+        $result = ['successUrl' => false, 'successSecureUrl' => true];
+
+        $hasBaseUrl = isset($params['address']['actual_base_url']);
+        $hasSecureBaseUrl = isset($params['https']['text']);
+        $hasSecureAdminUrl = !empty($params['https']['admin']);
+        $hasSecureFrontUrl = !empty($params['https']['front']);
+        $schemes = ['http', 'https'];
+
+        // Validating of Base URL
+        if ($hasBaseUrl && $this->urlValidator->isValid($params['address']['actual_base_url'], $schemes)) {
+            $result['successUrl'] = true;
+        }
+
+        // Validating of Secure Base URL
+        if ($hasSecureAdminUrl || $hasSecureFrontUrl) {
+            if (!($hasSecureBaseUrl && $this->urlValidator->isValid($params['https']['text'], $schemes))) {
+                $result['successSecureUrl'] = false;
+            }
+        }
+
+        return new JsonModel($result);
+    }
+}
diff --git a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
index 6a4b3a72b372c8ff611bcc7e535c99cbef4bb404..935f395a5e219f0546daf7967dbcc0726c695055 100644
--- a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
+++ b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
@@ -99,10 +99,10 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface
     }
 
     /**
-     * Check if user login
+     * Check if user logged-in and has permissions
      *
      * @param \Zend\Mvc\MvcEvent $event
-     * @return bool
+     * @return false|\Zend\Http\Response
      * @throws \Magento\Framework\Exception\LocalizedException
      */
     public function authPreDispatch($event)
@@ -115,6 +115,7 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface
             /** @var Application $application */
             $application = $event->getApplication();
             $serviceManager = $application->getServiceManager();
+
             if ($serviceManager->get(\Magento\Framework\App\DeploymentConfig::class)->isAvailable()) {
                 /** @var \Magento\Setup\Model\ObjectManagerProvider $objectManagerProvider */
                 $objectManagerProvider = $serviceManager->get(\Magento\Setup\Model\ObjectManagerProvider::class);
@@ -135,17 +136,26 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface
                         'appState' => $adminAppState
                     ]
                 );
-                if (!$objectManager->get(\Magento\Backend\Model\Auth::class)->isLoggedIn()) {
+                /** @var \Magento\Backend\Model\Auth $auth */
+                $authentication = $objectManager->get(\Magento\Backend\Model\Auth::class);
+
+                if (
+                    !$authentication->isLoggedIn() ||
+                    !$adminSession->isAllowed('Magento_Backend::setup_wizard')
+                ) {
                     $adminSession->destroy();
+                    /** @var \Zend\Http\Response $response */
                     $response = $event->getResponse();
                     $baseUrl = Http::getDistroBaseUrlPath($_SERVER);
                     $response->getHeaders()->addHeaderLine('Location', $baseUrl . 'index.php/session/unlogin');
                     $response->setStatusCode(302);
                     $event->stopPropagation();
+
                     return $response;
                 }
             }
         }
+
         return false;
     }
 
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallStoreConfigurationCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallStoreConfigurationCommandTest.php
index 6f5ab3a5a64c537751cc8964229e35869b06c8e5..c3494b389aa5ecb2a2ab2465b5d848627a5d8e7a 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallStoreConfigurationCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallStoreConfigurationCommandTest.php
@@ -11,8 +11,14 @@ use Symfony\Component\Console\Tester\CommandTester;
 use Magento\Setup\Model\Installer;
 use Magento\Framework\ObjectManagerInterface;
 use Magento\Setup\Model\StoreConfigurationDataMapper;
-use Magento\Framework\Url\Validator;
+use Magento\Framework\Validator\Url as UrlValidator;
+use Magento\Framework\Validator\Locale as LocaleValidator;
+use Magento\Framework\Validator\Timezone as TimezoneValidator;
+use Magento\Framework\Validator\Currency as CurrencyValidator;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -35,6 +41,26 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
      */
     private $objectManager;
 
+    /**
+     * @var LocaleValidator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $localeValidatorMock;
+
+    /**
+     * @var TimezoneValidator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $timezoneValidatorMock;
+
+    /**
+     * @var CurrencyValidator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $currencyValidatorMock;
+
+    /**
+     * @var UrlValidator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $urlValidatorMock;
+
     /**
      * @var InstallStoreConfigurationCommand
      */
@@ -42,6 +68,11 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
+        $this->urlValidatorMock = $this->getMock(UrlValidator::class, [], [], '', false);
+        $this->localeValidatorMock = $this->getMock(LocaleValidator::class, [], [], '', false);
+        $this->timezoneValidatorMock = $this->getMock(TimezoneValidator::class, [], [], '', false);
+        $this->currencyValidatorMock = $this->getMock(CurrencyValidator::class, [], [], '', false);
+
         $this->installerFactory = $this->getMock(\Magento\Setup\Model\InstallerFactory::class, [], [], '', false);
         $this->deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false);
         $this->installer = $this->getMock(\Magento\Setup\Model\Installer::class, [], [], '', false);
@@ -62,7 +93,11 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
         $this->command = new InstallStoreConfigurationCommand(
             $this->installerFactory,
             $this->deploymentConfig,
-            $objectManagerProvider
+            $objectManagerProvider,
+            $this->localeValidatorMock,
+            $this->timezoneValidatorMock,
+            $this->currencyValidatorMock,
+            $this->urlValidatorMock
         );
     }
 
@@ -102,41 +137,11 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
      */
     public function testExecuteInvalidData(array $option, $error)
     {
-        $url= $this->getMock(\Magento\Framework\Url\Validator::class, [], [], '', false);
-        $url->expects($this->any())->method('isValid')->will($this->returnValue(false));
-        if (!isset($option['--' . StoreConfigurationDataMapper::KEY_BASE_URL_SECURE])) {
-            $url->expects($this->any())->method('getMessages')->will($this->returnValue([
-                Validator::INVALID_URL => 'Invalid URL.'
-            ]));
-        }
-        $localeLists= $this->getMock(\Magento\Framework\Validator\Locale::class, [], [], '', false);
-        $localeLists->expects($this->any())->method('isValid')->will($this->returnValue(false));
-        $timezoneLists= $this->getMock(\Magento\Framework\Validator\Timezone::class, [], [], '', false);
-        $timezoneLists->expects($this->any())->method('isValid')->will($this->returnValue(false));
-        $currencyLists= $this->getMock(\Magento\Framework\Validator\Currency::class, [], [], '', false);
-        $currencyLists->expects($this->any())->method('isValid')->will($this->returnValue(false));
-
-        $returnValueMapOM = [
-            [
-                \Magento\Framework\Url\Validator::class,
-                $url
-            ],
-            [
-                \Magento\Framework\Validator\Locale::class,
-                $localeLists
-            ],
-            [
-                \Magento\Framework\Validator\Timezone::class,
-                $timezoneLists
-            ],
-            [
-                \Magento\Framework\Validator\Currency::class,
-                $currencyLists
-            ],
-        ];
-        $this->objectManager->expects($this->any())
-            ->method('get')
-            ->will($this->returnValueMap($returnValueMapOM));
+        $this->localeValidatorMock->expects($this->any())->method('isValid')->willReturn(false);
+        $this->timezoneValidatorMock->expects($this->any())->method('isValid')->willReturn(false);
+        $this->currencyValidatorMock->expects($this->any())->method('isValid')->willReturn(false);
+        $this->urlValidatorMock->expects($this->any())->method('isValid')->willReturn(false);
+
         $this->deploymentConfig->expects($this->once())
             ->method('isAvailable')
             ->will($this->returnValue(true));
@@ -144,7 +149,7 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
             ->method('create');
         $commandTester = new CommandTester($this->command);
         $commandTester->execute($option);
-        $this->assertEquals($error . PHP_EOL, $commandTester->getDisplay());
+        $this->assertContains($error, $commandTester->getDisplay());
     }
 
     /**
@@ -155,48 +160,54 @@ class InstallStoreConfigurationCommandTest extends \PHPUnit_Framework_TestCase
         return [
             [
                 ['--' . StoreConfigurationDataMapper::KEY_BASE_URL => 'sampleUrl'],
-                'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL . '\': Invalid URL.'
+                'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL . '\': Invalid URL \'sampleUrl\'.'
+            ],
+            [
+                ['--' . StoreConfigurationDataMapper::KEY_BASE_URL => 'http://example.com_test'],
+                'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL
+                    . '\': Invalid URL \'http://example.com_test\'.'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_LANGUAGE => 'sampleLanguage'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_LANGUAGE
-                . '\': Invalid value. To see possible values, run command \'bin/magento info:language:list\'.'
+                    . '\': Invalid value. To see possible values, run command \'bin/magento info:language:list\'.'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_TIMEZONE => 'sampleTimezone'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_TIMEZONE
-                . '\': Invalid value. To see possible values, run command \'bin/magento info:timezone:list\'.'
+                    . '\': Invalid value. To see possible values, run command \'bin/magento info:timezone:list\'.'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_CURRENCY => 'sampleLanguage'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_CURRENCY
-                . '\': Invalid value. To see possible values, run command \'bin/magento info:currency:list\'.'
+                    . '\': Invalid value. To see possible values, run command \'bin/magento info:currency:list\'.'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_USE_SEF_URL => 'invalidValue'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_USE_SEF_URL
-                . '\': Invalid value. Possible values (0|1).'
+                    . '\': Invalid value. Possible values (0|1).'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_IS_SECURE => 'invalidValue'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_IS_SECURE
-                . '\': Invalid value. Possible values (0|1).'
+                    . '\': Invalid value. Possible values (0|1).'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_BASE_URL_SECURE => 'http://www.sample.com'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_BASE_URL_SECURE
-                . '\': Invalid secure URL.'
+                    . '\': Invalid URL \'http://www.sample.com\'.'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_IS_SECURE_ADMIN => 'invalidValue'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_IS_SECURE_ADMIN
-                . '\': Invalid value. Possible values (0|1).'
+                    . '\': Invalid value. Possible values (0|1).'
             ],
             [
                 ['--' . StoreConfigurationDataMapper::KEY_ADMIN_USE_SECURITY_KEY => 'invalidValue'],
                 'Command option \'' . StoreConfigurationDataMapper::KEY_ADMIN_USE_SECURITY_KEY
-                . '\': Invalid value. Possible values (0|1).'
+                    . '\': Invalid value. Possible values (0|1).'
             ],
+
         ];
     }
 }
diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/UrlCheckTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/UrlCheckTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b44887b586d5c69b6c56a1e19a4b9d68ae96bfe
--- /dev/null
+++ b/setup/src/Magento/Setup/Test/Unit/Controller/UrlCheckTest.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Setup\Test\Unit\Controller;
+
+use Magento\Setup\Controller\UrlCheck;
+use Zend\Stdlib\RequestInterface;
+use Zend\View\Model\JsonModel;
+use Magento\Framework\Validator\Url as UrlValidator;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+class UrlCheckTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @param array $requestJson
+     * @param array $expectedResult
+     * @dataProvider indexActionDataProvider
+     */
+    public function testIndexAction($requestJson, $expectedResult)
+    {
+        /** @var ObjectManagerHelper $objectManagerHelper */
+        $objectManagerHelper = new ObjectManagerHelper($this);
+
+        $allowedSchemes = ['http', 'https'];
+        $returnMap = [];
+        if (isset($requestJson['address']['actual_base_url'])) {
+            $returnMap[] = [
+                $requestJson['address']['actual_base_url'],
+                $allowedSchemes,
+                $expectedResult['successUrl'],
+            ];
+        }
+        if (isset($requestJson['https']['text'])) {
+            $returnMap[] = [
+                $requestJson['https']['text'],
+                $allowedSchemes,
+                $expectedResult['successSecureUrl'],
+            ];
+        }
+
+        /** @var UrlValidator|\PHPUnit_Framework_MockObject_MockObject $validator */
+        $validator = $this->getMockBuilder(UrlValidator::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $validator->expects($this->any())
+            ->method('isValid')
+            ->willReturnMap($returnMap);
+
+        /** @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject $requestMock */
+        $requestMock = $this->getMockBuilder(RequestInterface::class)
+            ->getMockForAbstractClass();
+        $requestMock->expects($this->once())
+            ->method('getContent')
+            ->willReturn(json_encode($requestJson));
+
+        $controller = $objectManagerHelper->getObject(
+            UrlCheck::class,
+            ['urlValidator' => $validator]
+        );
+        $objectManagerHelper->setBackwardCompatibleProperty($controller, 'request', $requestMock);
+
+        $this->assertEquals(new JsonModel($expectedResult), $controller->indexAction());
+    }
+
+    /**
+     * @return array
+     */
+    public function indexActionDataProvider()
+    {
+        return [
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost'
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => true, 'successSecureUrl' => true]
+            ],
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost.com_test'
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => false, 'successSecureUrl' => true]
+            ],
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost.com_test'
+                    ],
+                    'https' => [
+                        'admin' => false,
+                        'front' => false,
+                        'text' => ''
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => false, 'successSecureUrl' => true]
+            ],
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost.com:8080'
+                    ],
+                    'https' => [
+                        'admin' => true,
+                        'front' => false,
+                        'text' => 'https://example.com.ua/'
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => true, 'successSecureUrl' => true]
+            ],
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost.com:8080/folder_name/'
+                    ],
+                    'https' => [
+                        'admin' => false,
+                        'front' => true,
+                        'text' => 'https://example.com.ua/'
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => true, 'successSecureUrl' => true]
+            ],
+            [
+                'requestJson' => [
+                    'address' => [
+                        'actual_base_url' => 'http://localhost.com:8080/folder_name/'
+                    ],
+                    'https' => [
+                        'admin' => true,
+                        'front' => true,
+                        'text' => 'https://example.com.ua:8090/folder_name/'
+                    ]
+                ],
+                'expectedResult' => ['successUrl' => true, 'successSecureUrl' => true]
+            ],
+        ];
+    }
+}
diff --git a/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php b/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php
index 558533afe92429582cbfa79e5fcd691b200ecef8..1ace3f452c4f917181c43a86744f2b4db39b9439 100644
--- a/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php
@@ -3,7 +3,6 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\Setup\Test\Unit\Mvc\Bootstrap;
 
 use \Magento\Setup\Mvc\Bootstrap\InitParamListener;
@@ -59,11 +58,11 @@ class InitParamListenerTest extends \PHPUnit_Framework_TestCase
             ->withConsecutive(
                 [
                     \Magento\Framework\App\Filesystem\DirectoryList::class,
-                    $this->isInstanceOf(\Magento\Framework\App\Filesystem\DirectoryList::class)
+                    $this->isInstanceOf(\Magento\Framework\App\Filesystem\DirectoryList::class),
                 ],
                 [
                     \Magento\Framework\Filesystem::class,
-                    $this->isInstanceOf(\Magento\Framework\Filesystem::class)
+                    $this->isInstanceOf(\Magento\Framework\Filesystem::class),
                 ]
             );
         $mvcApplication->expects($this->any())->method('getServiceManager')->willReturn($serviceManager);
@@ -130,10 +129,10 @@ class InitParamListenerTest extends \PHPUnit_Framework_TestCase
         $request->expects($this->any())
             ->method('getContent')
             ->willReturn(
-                $cliParam ? ['install', '--magento-init-params=' . $cliParam ] : ['install']
+                $cliParam ? ['install', '--magento-init-params=' . $cliParam] : ['install']
             );
         $mvcApplication->expects($this->any())->method('getConfig')->willReturn(
-            $zfAppConfig ? [InitParamListener::BOOTSTRAP_PARAM => $zfAppConfig]:[]
+            $zfAppConfig ? [InitParamListener::BOOTSTRAP_PARAM => $zfAppConfig] : []
         );
 
         $mvcApplication->expects($this->any())->method('getRequest')->willReturn($request);
@@ -150,41 +149,55 @@ class InitParamListenerTest extends \PHPUnit_Framework_TestCase
             'mage_mode App' => [['MAGE_MODE' => 'developer'], [], '', ['MAGE_MODE' => 'developer']],
             'mage_mode Env' => [[], ['MAGE_MODE' => 'developer'], '', ['MAGE_MODE' => 'developer']],
             'mage_mode CLI' => [[], [], 'MAGE_MODE=developer', ['MAGE_MODE' => 'developer']],
-            'one MAGE_DIRS CLI' => [[], [], 'MAGE_MODE=developer&MAGE_DIRS[base][path]=/var/www/magento2',
-                       ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2']], 'MAGE_MODE' => 'developer']],
+            'one MAGE_DIRS CLI' => [
+                [],
+                [],
+                'MAGE_MODE=developer&MAGE_DIRS[base][path]=/var/www/magento2',
+                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2']], 'MAGE_MODE' => 'developer'],
+            ],
             'two MAGE_DIRS CLI' => [
                 [],
                 [],
                 'MAGE_MODE=developer&MAGE_DIRS[base][path]=/var/www/magento2&MAGE_DIRS[cache][path]=/tmp/cache',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2'], 'cache' => ['path' => '/tmp/cache']],
-                 'MAGE_MODE' => 'developer']],
+                [
+                    'MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2'], 'cache' => ['path' => '/tmp/cache']],
+                    'MAGE_MODE' => 'developer',
+                ],
+            ],
             'mage_mode only' => [[], [], 'MAGE_MODE=developer', ['MAGE_MODE' => 'developer']],
             'MAGE_DIRS Env' => [
                 [],
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2']], 'MAGE_MODE' => 'developer'],
                 '',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2']], 'MAGE_MODE' => 'developer']],
+                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2']], 'MAGE_MODE' => 'developer'],
+            ],
             'two MAGE_DIRS' => [
                 [],
                 [],
                 'MAGE_MODE=developer&MAGE_DIRS[base][path]=/var/www/magento2&MAGE_DIRS[cache][path]=/tmp/cache',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2'], 'cache' => ['path' => '/tmp/cache']],
-                 'MAGE_MODE' => 'developer']],
+                [
+                    'MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2'], 'cache' => ['path' => '/tmp/cache']],
+                    'MAGE_MODE' => 'developer',
+                ],
+            ],
             'Env overwrites App' => [
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/App']], 'MAGE_MODE' => 'developer'],
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/Env']], 'MAGE_MODE' => 'developer'],
                 '',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/Env']], 'MAGE_MODE' => 'developer']],
+                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/Env']], 'MAGE_MODE' => 'developer'],
+            ],
             'CLI overwrites Env' => [
                 ['MAGE_MODE' => 'developerApp'],
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/Env']]],
                 'MAGE_DIRS[base][path]=/var/www/magento2/CLI',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/CLI']], 'MAGE_MODE' => 'developerApp']],
+                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/CLI']], 'MAGE_MODE' => 'developerApp'],
+            ],
             'CLI overwrites All' => [
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/App']], 'MAGE_MODE' => 'production'],
                 ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/Env']]],
                 'MAGE_DIRS[base][path]=/var/www/magento2/CLI',
-                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/CLI']], 'MAGE_MODE' => 'production']],
+                ['MAGE_DIRS' => ['base' => ['path' => '/var/www/magento2/CLI']], 'MAGE_MODE' => 'production'],
+            ],
         ];
     }
 
@@ -226,6 +239,168 @@ class InitParamListenerTest extends \PHPUnit_Framework_TestCase
             [$this->listener, 'onBootstrap']
         )->willReturn($this->callbackHandler);
         $eventManager->expects($this->once())->method('getSharedManager')->willReturn($sharedManager);
+
         return $eventManager;
     }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testAuthPreDispatch()
+    {
+        $eventMock = $this->getMockBuilder(\Zend\Mvc\MvcEvent::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $routeMatchMock = $this->getMockBuilder(\Zend\Mvc\Router\Http\RouteMatch::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $applicationMock = $this->getMockBuilder(\Zend\Mvc\Application::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $serviceManagerMock = $this->getMockBuilder(\Zend\ServiceManager\ServiceManager::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $deploymentConfigMock = $this->getMockBuilder(\Magento\Framework\App\DeploymentConfig::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $deploymentConfigMock->expects($this->once())
+            ->method('isAvailable')
+            ->willReturn(true);
+        $omProvider = $this->getMockBuilder(\Magento\Setup\Model\ObjectManagerProvider::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $objectManagerMock = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class);
+        $adminAppStateMock = $this->getMockBuilder(\Magento\Framework\App\State::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $sessionConfigMock = $this->getMockBuilder(\Magento\Backend\Model\Session\AdminConfig::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $backendAppListMock = $this->getMockBuilder(\Magento\Backend\App\BackendAppList::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $backendAppMock = $this->getMockBuilder(\Magento\Backend\App\BackendApp::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $backendUrlFactoryMock = $this->getMockBuilder(\Magento\Backend\Model\UrlFactory::class)
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $backendUrlMock = $this->getMockBuilder(\Magento\Backend\Model\Url::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $authenticationMock = $this->getMockBuilder(\Magento\Backend\Model\Auth::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adminSessionMock = $this->getMockBuilder(\Magento\Backend\Model\Auth\Session::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $responseMock = $this->getMockBuilder(\Zend\Http\Response::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $headersMock = $this->getMockBuilder(\Zend\Http\Headers::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $routeMatchMock->expects($this->once())
+            ->method('getParam')
+            ->with('controller')
+            ->willReturn('testController');
+        $eventMock->expects($this->once())
+            ->method('getRouteMatch')
+            ->willReturn($routeMatchMock);
+        $eventMock->expects($this->once())
+            ->method('getApplication')
+            ->willReturn($applicationMock);
+        $serviceManagerMock->expects($this->any())
+            ->method('get')
+            ->willReturnMap(
+                [
+                    [
+                        \Magento\Framework\App\DeploymentConfig::class,
+                        true,
+                        $deploymentConfigMock,
+                    ],
+                    [
+                        \Magento\Setup\Model\ObjectManagerProvider::class,
+                        true,
+                        $omProvider,
+                    ],
+                ]
+            );
+        $objectManagerMock->expects($this->any())
+            ->method('get')
+            ->willReturnMap(
+                [
+                    [
+                        \Magento\Framework\App\State::class,
+                        $adminAppStateMock,
+                    ],
+                    [
+                        \Magento\Backend\Model\Session\AdminConfig::class,
+                        $sessionConfigMock,
+                    ],
+                    [
+                        \Magento\Backend\App\BackendAppList::class,
+                        $backendAppListMock,
+                    ],
+                    [
+                        \Magento\Backend\Model\UrlFactory::class,
+                        $backendUrlFactoryMock,
+                    ],
+                    [
+                        \Magento\Backend\Model\Auth::class,
+                        $authenticationMock,
+                    ],
+                ]
+            );
+        $objectManagerMock->expects($this->any())
+            ->method('create')
+            ->willReturn($adminSessionMock);
+        $omProvider->expects($this->once())
+            ->method('get')
+            ->willReturn($objectManagerMock);
+        $adminAppStateMock->expects($this->once())
+            ->method('setAreaCode')
+            ->with(\Magento\Framework\App\Area::AREA_ADMINHTML);
+        $applicationMock->expects($this->once())
+            ->method('getServiceManager')
+            ->willReturn($serviceManagerMock);
+        $backendAppMock->expects($this->once())
+            ->method('getCookiePath')
+            ->willReturn('');
+        $backendUrlFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($backendUrlMock);
+        $backendAppListMock->expects($this->once())
+            ->method('getBackendApp')
+            ->willReturn($backendAppMock);
+        $authenticationMock->expects($this->once())
+            ->method('isLoggedIn')
+            ->willReturn(true);
+        $adminSessionMock->expects($this->once())
+            ->method('isAllowed')
+            ->with('Magento_Backend::setup_wizard', null)
+            ->willReturn(false);
+        $adminSessionMock->expects($this->once())
+            ->method('destroy');
+        $eventMock->expects($this->once())
+            ->method('getResponse')
+            ->willReturn($responseMock);
+        $responseMock->expects($this->once())
+            ->method('getHeaders')
+            ->willReturn($headersMock);
+        $headersMock->expects($this->once())
+            ->method('addHeaderLine');
+        $responseMock->expects($this->once())
+            ->method('setStatusCode')
+            ->with(302);
+        $eventMock->expects($this->once())
+            ->method('stopPropagation');
+
+        $this->assertSame(
+            $this->listener->authPreDispatch($eventMock),
+            $responseMock
+        );
+    }
 }
diff --git a/setup/view/magento/setup/web-configuration.phtml b/setup/view/magento/setup/web-configuration.phtml
index 35aa19484ed53f39bf37ae0e90e7b76c7f5efe87..ab2a00342b715b05f215d1d3e12010b0fc4993cc 100644
--- a/setup/view/magento/setup/web-configuration.phtml
+++ b/setup/view/magento/setup/web-configuration.phtml
@@ -30,7 +30,7 @@ $hints = [
 <div class="nav-bar-outer-actions">
     <div class="outer-actions-inner-wrap">
         <div class="btn-wrap btn-wrap-triangle-right btn-wrap-next">
-            <button type="button" class="btn btn-prime" ng-click="nextState()" dis>Next</button>
+            <button type="button" class="btn btn-prime" ng-click="validateUrl()" dis>Next</button>
         </div>
         <div class="btn-wrap btn-wrap-triangle-left btn-wrap-prev">
             <button type="button" class="btn" ng-click="previousState()">Back</button>
@@ -40,6 +40,13 @@ $hints = [
 
 <h2 class="page-sub-title">{{$state.current.header}}</h2>
 
+<div
+    class="message message-error"
+    ng-show="validateUrl.failed !== undefined"
+>
+    <span class="message-text">{{validateUrl.failed}}</span>
+</div>
+
 <form
     name="webconfig"
     role="form"