diff --git a/.htaccess b/.htaccess
index e7a6c2e218cb76bff2b480ccd8b5ddf97a47b25e..f824f0b7bbc59db5990b61922244909f84162738 100644
--- a/.htaccess
+++ b/.htaccess
@@ -203,76 +203,166 @@
     RedirectMatch 403 /\.git
 
     <Files composer.json>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files composer.lock>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .gitignore>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .htaccess>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .htaccess.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .php_cs.dist>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .travis.yml>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files CHANGELOG.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files CONTRIBUTING.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files COPYING.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files Gruntfile.js>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files LICENSE.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files LICENSE_AFL.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files nginx.conf.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files package.json>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files php.ini.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files README.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files magento_umask>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
 
 # For 404s and 403s that aren't handled by the application, show plain 404 response
diff --git a/.htaccess.sample b/.htaccess.sample
index 91a0372ef7f165feef4a41bc223c6bf8e73b70d0..f3a4474aec9492825323904d0df393b71945848f 100644
--- a/.htaccess.sample
+++ b/.htaccess.sample
@@ -180,76 +180,166 @@
     RedirectMatch 403 /\.git
 
     <Files composer.json>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files composer.lock>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .gitignore>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .htaccess>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .htaccess.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .php_cs.dist>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files .travis.yml>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files CHANGELOG.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files CONTRIBUTING.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files COPYING.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files Gruntfile.js>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files LICENSE.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files LICENSE_AFL.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files nginx.conf.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files package.json>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files php.ini.sample>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files README.md>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
     <Files magento_umask>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
 
 # For 404s and 403s that aren't handled by the application, show plain 404 response
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef841ec0337f223ee17e95e6a08917ff5e479ca1..8270f8908a3c70f9235183c6667922dfab28a129 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,693 @@
+2.2.1
+=============
+* GitHub issues:
+    * [#4248](https://github.com/magento/magento2/issues/4248) -- Validations not working on customer registration on DOB field.  (fixed in [#11067](https://github.com/magento/magento2/pull/11067))
+    * [#6350](https://github.com/magento/magento2/issues/6350) -- Frontend: Datepicker/calendar control does not use the store locale (fixed in [#11067](https://github.com/magento/magento2/pull/11067))
+    * [#6858](https://github.com/magento/magento2/issues/6858) -- DatePicker date format does not reflect user's locale (fixed in [#11067](https://github.com/magento/magento2/pull/11067))
+    * [#6831](https://github.com/magento/magento2/issues/6831) -- Magento 2.1.1 Invalid input date format 'Invalid date' (fixed in [#11067](https://github.com/magento/magento2/pull/11067))
+    * [#9743](https://github.com/magento/magento2/issues/9743) -- Invalid date when customer validate with French locale (fixed in [#11067](https://github.com/magento/magento2/pull/11067))
+    * [#6712](https://github.com/magento/magento2/issues/6712) -- Footer Links Widget CSS Issue (fixed in [#11063](https://github.com/magento/magento2/pull/11063))
+    * [#9008](https://github.com/magento/magento2/issues/9008) -- Error Message Is Confusing When Code Base Is Behind Database Module Version (fixed in [#11064](https://github.com/magento/magento2/pull/11064))
+    * [#9981](https://github.com/magento/magento2/issues/9981) -- M2 suggests running setup:upgrade if version number of module is higher than expected (fixed in [#11064](https://github.com/magento/magento2/pull/11064))
+    * [#10824](https://github.com/magento/magento2/issues/10824) -- Cannot add new columns to item grid in admin sales_order_view layout (fixed in [#11076](https://github.com/magento/magento2/pull/11076))
+    * [#10417](https://github.com/magento/magento2/issues/10417) -- Wysywig editor shows broken image icons (fixed in [#11048](https://github.com/magento/magento2/pull/11048))
+    * [#10697](https://github.com/magento/magento2/issues/10697) -- Product Import: Additional data: Invalid URL key (fixed in [#11049](https://github.com/magento/magento2/pull/11049))
+    * [#10474](https://github.com/magento/magento2/issues/10474) -- Error message in product review form not being translated (fixed in [#11069](https://github.com/magento/magento2/pull/11069))
+    * [#9877](https://github.com/magento/magento2/issues/9877) -- getCacheTags for price issue (fixed in [#11154](https://github.com/magento/magento2/pull/11154))
+    * [#10738](https://github.com/magento/magento2/issues/10738) -- Empty attribute label is displayed on product page when other language used. (fixed in [#11168](https://github.com/magento/magento2/pull/11168))
+    * [#9900](https://github.com/magento/magento2/issues/9900) -- Cms module collections missing event prefix (fixed in [#11223](https://github.com/magento/magento2/pull/11223))
+    * [#11044](https://github.com/magento/magento2/issues/11044) -- magento setup:upgrade prompts to run compilation, even in developer mode (fixed in [#11050](https://github.com/magento/magento2/pull/11050))
+    * [#10775](https://github.com/magento/magento2/issues/10775) -- 404 Forbidden sounds not right (fixed in [#11134](https://github.com/magento/magento2/pull/11134))
+    * [#11231](https://github.com/magento/magento2/issues/11231) -- Can't close mobile search bar once typed (fixed in [#11246](https://github.com/magento/magento2/pull/11246))
+    * [#10317](https://github.com/magento/magento2/issues/10317) -- Region is being overridden when changing from a required-state country to one that is not required (fixed in [#11254](https://github.com/magento/magento2/pull/11254))
+    * [#11089](https://github.com/magento/magento2/issues/11089) -- setup:config:set --key append instead of replace (fixed in [#11155](https://github.com/magento/magento2/pull/11155))
+    * [#7582](https://github.com/magento/magento2/issues/7582) -- Payment methods in payments title in wrong language (fixed in [#11165](https://github.com/magento/magento2/pull/11165))
+    * [#5105](https://github.com/magento/magento2/issues/5105) -- Error While send Invoice with Grouped Products (fixed in [#11297](https://github.com/magento/magento2/pull/11297))
+    * [#11163](https://github.com/magento/magento2/issues/11163) -- Magento 2.2.0 Pages showing error: Data key is missing: code-entity (fixed in [#11205](https://github.com/magento/magento2/pull/11205))
+    * [#11329](https://github.com/magento/magento2/issues/11329) -- Unable to proceed massaction "Update attributes" with required multiple select attribute  (fixed in [#11349](https://github.com/magento/magento2/pull/11349))
+    * [#8958](https://github.com/magento/magento2/issues/8958) -- Hint mistake in english language (fixed in [#11390](https://github.com/magento/magento2/pull/11390))
+* GitHub pull requests:
+    * [#11067](https://github.com/magento/magento2/pull/11067) -- Fix dob date validation on custom locale (by @joachimVT)
+    * [#11054](https://github.com/magento/magento2/pull/11054) -- Add dev:tests:run parameter to pass arguments to phpunit (by @schmengler)
+    * [#11056](https://github.com/magento/magento2/pull/11056) -- Do not disable maintenance mode after running a backup. (by @stevenvdp)
+    * [#11058](https://github.com/magento/magento2/pull/11058) -- Escape html before replace new line with break (by @Quinten)
+    * [#11063](https://github.com/magento/magento2/pull/11063) -- 6712 Remove additional margin for footer links widget; prevents layou… (by @fragdochkarl)
+    * [#11064](https://github.com/magento/magento2/pull/11064) -- Show different message if DB module version is higher than code modul… (by @schmengler)
+    * [#11076](https://github.com/magento/magento2/pull/11076) -- Backport to 2.2 of #10824: add name for order items grid default renderer block (by @gsomoza)
+    * [#11048](https://github.com/magento/magento2/pull/11048) -- Fix #10417 (by @PieterCappelle)
+    * [#11049](https://github.com/magento/magento2/pull/11049) -- Vague error message for invalid url_key for category (by @avdb)
+    * [#11069](https://github.com/magento/magento2/pull/11069) -- Error message in product review form not being translated (by @Echron)
+    * [#11127](https://github.com/magento/magento2/pull/11127) -- Add missing return statements in setters (by @niccifor)
+    * [#11138](https://github.com/magento/magento2/pull/11138) -- Added template as argument to the store address renderer to allow custom formatting (by @jokeputs)
+    * [#11147](https://github.com/magento/magento2/pull/11147) -- Fix the correct removal of the images and the removal of all images in the catalog (by @raumatbel)
+    * [#11154](https://github.com/magento/magento2/pull/11154) -- Issue #9877: Backport of: getCacheTags for price issue #10930 (by @denysbabenko)
+    * [#11160](https://github.com/magento/magento2/pull/11160) -- Ported Down changes from PR#10919 (by @strell)
+    * [#11200](https://github.com/magento/magento2/pull/11200) -- Delete CallExit function for After plugin logic execution 2.2-develop [BackPort] (by @osrecio)
+    * [#11168](https://github.com/magento/magento2/pull/11168) -- Fixed issue #10738: Don't display attribute label if defined as "none" in layout (by @maksek)
+    * [#11223](https://github.com/magento/magento2/pull/11223) -- Cms page/block eventprefix fix issue 9900 (by @convenient)
+    * [#11229](https://github.com/magento/magento2/pull/11229) -- Disable secret key validation on admin noroute to fix redirect loop (by @convenient)
+    * [#11050](https://github.com/magento/magento2/pull/11050) -- Only prompt for deploy command in production mode (by @schmengler)
+    * [#11134](https://github.com/magento/magento2/pull/11134) -- Fix 404 status header (by @Zifius)
+    * [#11084](https://github.com/magento/magento2/pull/11084) -- Fix in stripped min length validation when value has special characters (by @rubenRP)
+    * [#11246](https://github.com/magento/magento2/pull/11246) -- Can't close mobile search bar (by @crissanclick)
+    * [#11254](https://github.com/magento/magento2/pull/11254) -- Fix for #10317 Disable region list when switching to a region optional country. (by @romainruaud)
+    * [#11155](https://github.com/magento/magento2/pull/11155) -- Refactor ConfigGenerator to replace/set crypt key instead of append (by @renttek)
+    * [#11291](https://github.com/magento/magento2/pull/11291) -- Fix #9243 - Upgrade ZF components. Zend_Service (by @dverkade)
+    * [#11165](https://github.com/magento/magento2/pull/11165) -- #7582: use setStoreId after custom load method to give storeId precedence (by @bka)
+    * [#11297](https://github.com/magento/magento2/pull/11297) -- Fix for issue #5105 - Error While send Invoice with Grouped Products (by @michielgerritsen)
+    * [#11327](https://github.com/magento/magento2/pull/11327) -- Fix #10812: htaccess Options override (by @dverkade)
+    * [#11081](https://github.com/magento/magento2/pull/11081) -- Text updated. (by @RakeshJesadiya)
+    * [#11183](https://github.com/magento/magento2/pull/11183) -- FIX for #11166 Index Handling Fatal Error (by @larsroettig)
+    * [#11205](https://github.com/magento/magento2/pull/11205) -- Fixes #11163 missing data key code-entity in CMS page edit form (by @Tomasz-Silpion)
+    * [#11219](https://github.com/magento/magento2/pull/11219) -- Fix typo in sessionStorage polyfill (by @mszydlo)
+    * [#11249](https://github.com/magento/magento2/pull/11249) -- Add a payload extender to the default shipping-save-processor (Backport to 2.2) (by @navarr)
+    * [#11345](https://github.com/magento/magento2/pull/11345) -- Use US English spelling for "Optimization". (by @davidangel)
+    * [#11349](https://github.com/magento/magento2/pull/11349) -- Bug fix update attributes (by @manuelson)
+    * [#11390](https://github.com/magento/magento2/pull/11390) -- Fix typo in design rule hint message (by @jahvi)
+
+2.2.0
+=============
+* GitHub issues:
+    * [#8287](https://github.com/magento/magento2/issues/8287) -- InputException while updating cart with Minimum order amount enabled (fixed in [#8474](https://github.com/magento/magento2/pull/8474))
+    * [#8315](https://github.com/magento/magento2/issues/8315) -- Error with StdoTest (fixed in [#8487](https://github.com/magento/magento2/pull/8487))
+    * [#5808](https://github.com/magento/magento2/issues/5808) -- [2.1.0] Problem on mobile when catalog gallery allowfullscreen is false (fixed in [#8434](https://github.com/magento/magento2/pull/8434))
+    * [#8392](https://github.com/magento/magento2/issues/8392) -- Initial loading of the related-products sorting fails in Edge-Mode (fixed in [#8467](https://github.com/magento/magento2/pull/8467))
+    * [#8076](https://github.com/magento/magento2/issues/8076) -- Currency Setup in admin throws in_array error when a single value is selected (fixed in [#8077](https://github.com/magento/magento2/pull/8077))
+    * [#8277](https://github.com/magento/magento2/issues/8277) -- CatalogImportExport uploader can't handle HTTPS images (fixed in [#8278](https://github.com/magento/magento2/pull/8278))
+    * [#7353](https://github.com/magento/magento2/issues/7353) -- Crosssells are never shown when using product/list/items.phtml template (fixed in [#8602](https://github.com/magento/magento2/pull/8602))
+    * [#8632](https://github.com/magento/magento2/issues/8632) -- Location of wishlist.js file is incorrect (fixed in [#8633](https://github.com/magento/magento2/pull/8633))
+    * [#6634](https://github.com/magento/magento2/issues/6634) -- Yes/No attribute value is not shown on a product details page (fixed in [#8623](https://github.com/magento/magento2/pull/8623))
+    * [#8566](https://github.com/magento/magento2/issues/8566) -- Setting 'show_out_of_stock' to 'No' has no effect (fixed in [#8736](https://github.com/magento/magento2/pull/8736))
+    * [#6706](https://github.com/magento/magento2/issues/6706) -- Notice undefined index when changes swatch attribute (fixed in [#6707](https://github.com/magento/magento2/pull/6707))
+    * [#6855](https://github.com/magento/magento2/issues/6855) -- Create order via backend doesn't work after using NL translation for order-header (fixed in [#6856](https://github.com/magento/magento2/pull/6856))
+    * [#8515](https://github.com/magento/magento2/issues/8515) -- Downloadable product is available for download even if order state is set canceled. (fixed in [#8917](https://github.com/magento/magento2/pull/8917))
+    * [#8871](https://github.com/magento/magento2/issues/8871) -- Typo in Pull Request Template (fixed in [#8908](https://github.com/magento/magento2/pull/8908))
+    * [#3791](https://github.com/magento/magento2/issues/3791) -- Error review when customer is not logged (fixed in [#9001](https://github.com/magento/magento2/pull/9001))
+    * [#9017](https://github.com/magento/magento2/issues/9017) -- Duplicate call to $this->getLinkField(); (fixed in [#9057](https://github.com/magento/magento2/pull/9057))
+    * [#7498](https://github.com/magento/magento2/issues/7498) -- Grammar Mistake: You don't subscribe to our newsletter. (fixed in [#9080](https://github.com/magento/magento2/pull/9080))
+    * [#9078](https://github.com/magento/magento2/issues/9078) -- Does not translate "Track All Shipments" in My Account, view order (fixed in [#9095](https://github.com/magento/magento2/pull/9095))
+    * [#5731](https://github.com/magento/magento2/issues/5731) -- FPT label not translatable in the totals on the cart page. (fixed in [#9204](https://github.com/magento/magento2/pull/9204))
+    * [#5040](https://github.com/magento/magento2/issues/5040) -- Change 'select' to 'query' in AbstractSearchResult (fixed in [#5043](https://github.com/magento/magento2/pull/5043))
+    * [#8761](https://github.com/magento/magento2/issues/8761) -- Popup-Modal not closing on Safari/Windows (fixed in [#8824](https://github.com/magento/magento2/pull/8824))
+    * [#7549](https://github.com/magento/magento2/issues/7549) -- Google API Tracking code missing single quote after account number (fixed in [#9084](https://github.com/magento/magento2/pull/9084))
+    * [#1146](https://github.com/magento/magento2/issues/1146) -- A few issues when you use /pub as DocumentRoot (fixed in [#9094](https://github.com/magento/magento2/pull/9094))
+    * [#2802](https://github.com/magento/magento2/issues/2802) -- Sitemap generation in wrong folder when vhost is connected to pub folder (fixed in [#9094](https://github.com/magento/magento2/pull/9094))
+    * [#9200](https://github.com/magento/magento2/issues/9200) -- Create new CLI command: Enable DB logging (fixed in [#9264](https://github.com/magento/magento2/pull/9264))
+    * [#9199](https://github.com/magento/magento2/issues/9199) -- Create New CLI command: Generate Varnish VCL file (fixed in [#9286](https://github.com/magento/magento2/pull/9286))
+    * [#6822](https://github.com/magento/magento2/issues/6822) -- CSS Minify Option Breaks inline SVG XML (fixed in [#9027](https://github.com/magento/magento2/pull/9027))
+    * [#8552](https://github.com/magento/magento2/issues/8552) -- CSS Minifying not compatible with CSS3 calc() function (fixed in [#9027](https://github.com/magento/magento2/pull/9027))
+    * [#9236](https://github.com/magento/magento2/issues/9236) -- Upgrade ZF components. Zend_Json (fixed in [#9262](https://github.com/magento/magento2/pull/9262) and [#9261](https://github.com/magento/magento2/pull/9261) and [#9344](https://github.com/magento/magento2/pull/9344) and [#9753](https://github.com/magento/magento2/pull/9753) and [#9754](https://github.com/magento/magento2/pull/9754))
+    * [#7523](https://github.com/magento/magento2/issues/7523) -- Zend_Db_Statement_Exception after refreshing browser with empty category (fixed in [#9400](https://github.com/magento/magento2/pull/9400))
+    * [#9237](https://github.com/magento/magento2/issues/9237) -- Upgrade ZF components. Zend_Log (fixed in [#9285](https://github.com/magento/magento2/pull/9285))
+    * [#9518](https://github.com/magento/magento2/issues/9518) -- Chrome version 58 causes problems with selections in the tinymce editor (fixed in [#9540](https://github.com/magento/magento2/pull/9540))
+    * [#9241](https://github.com/magento/magento2/issues/9241) -- Upgrade ZF components. Zend_Wildfire (fixed in [#9622](https://github.com/magento/magento2/pull/9622))
+    * [#9239](https://github.com/magento/magento2/issues/9239) -- Upgrade ZF components. Zend_Controller (fixed in [#9622](https://github.com/magento/magento2/pull/9622))
+    * [#6455](https://github.com/magento/magento2/issues/6455) -- Cookie Restriction Mode Overlay is cached by Varnish (fixed in [#9711](https://github.com/magento/magento2/pull/9711))
+    * [#5596](https://github.com/magento/magento2/issues/5596) -- Google Universal Analytics does not track when Cookie Restriction is enabled  (fixed in [#9713](https://github.com/magento/magento2/pull/9713))
+    * [#6441](https://github.com/magento/magento2/issues/6441) -- Google Analytics Tracking Code cached by Varnish if Cookie Restriction Settings are active (fixed in [#9713](https://github.com/magento/magento2/pull/9713))
+    * [#9242](https://github.com/magento/magento2/issues/9242) -- Upgrade ZF components. Zend_Session (fixed in [#9348](https://github.com/magento/magento2/pull/9348))
+    * [#7279](https://github.com/magento/magento2/issues/7279) -- Bill-to Name and Ship-to Name trancated to 20 characters in backend (fixed in [#9654](https://github.com/magento/magento2/pull/9654))
+    * [#6151](https://github.com/magento/magento2/issues/6151) -- Can't delete last item in cart if Minimum Order is Enable  (fixed in [#9714](https://github.com/magento/magento2/pull/9714))
+    * [#4272](https://github.com/magento/magento2/issues/4272) -- v2.0.4 Credit memos with adjustment fees cannot be fully refunded with a second credit memo (fixed in [#9715](https://github.com/magento/magento2/pull/9715))
+    * [#6207](https://github.com/magento/magento2/issues/6207) -- Checkbox IDs for Terms and Conditions should be unique in Checkout (fixed in [#9717](https://github.com/magento/magento2/pull/9717))
+    * [#7844](https://github.com/magento/magento2/issues/7844) -- Customer with unique attribute can't be saved (fixed in [#9712](https://github.com/magento/magento2/pull/9712))
+    * [#6244](https://github.com/magento/magento2/issues/6244) -- Promo code label not used (fixed in [#9721](https://github.com/magento/magento2/pull/9721))
+    * [#9771](https://github.com/magento/magento2/issues/9771) -- XML instruction referenceBlock does not allow template= or does it? (fixed in [#9772](https://github.com/magento/magento2/pull/9772))
+    * [#8221](https://github.com/magento/magento2/issues/8221) -- Javascript "mixins" doesn't works if 'urlArgs' is in requirejs-config.js (fixed in [#9665](https://github.com/magento/magento2/pull/9665))
+    * [#9278](https://github.com/magento/magento2/issues/9278) -- Create new CLI command: Enable Template Hints (fixed in [#9778](https://github.com/magento/magento2/pull/9778))
+    * [#9819](https://github.com/magento/magento2/issues/9819) -- Authentication_lock settings cannot be edited in the Backend (fixed in [#9820](https://github.com/magento/magento2/pull/9820))
+    * [#9216](https://github.com/magento/magento2/issues/9216) -- Coupon codes not showing in invoice print out (fixed in [#9780](https://github.com/magento/magento2/pull/9780))
+    * [#9679](https://github.com/magento/magento2/issues/9679) -- Translation for layered navigation attribute option not working (fixed in [#9873](https://github.com/magento/magento2/pull/9873))
+    * [#3060](https://github.com/magento/magento2/issues/3060) -- setup:static-content:deploy, setup:di:compile and deploy:mode:set will not return a non-zero exit code if any error occurs (fixed in [#7780](https://github.com/magento/magento2/pull/7780))
+    * [#9421](https://github.com/magento/magento2/issues/9421) -- Inconsistent Gift Options checkbox labels (fixed in [#9525](https://github.com/magento/magento2/pull/9525))
+    * [#9805](https://github.com/magento/magento2/issues/9805) -- Static tests in Windows fail due to file path mismatches (fixed in [#9902](https://github.com/magento/magento2/pull/9902))
+    * [#9924](https://github.com/magento/magento2/issues/9924) -- Prefix and suffix are not prefilled in the quote shipping address (fixed in [#9925](https://github.com/magento/magento2/pull/9925))
+    * [#4237](https://github.com/magento/magento2/issues/4237) -- Cron times in the database have a double timezone correction (fixed in [#9943](https://github.com/magento/magento2/pull/9943))
+    * [#9426](https://github.com/magento/magento2/issues/9426) -- Incorrect order date in Orders grid (fixed in [#9941](https://github.com/magento/magento2/pull/9941))
+    * [#3380](https://github.com/magento/magento2/issues/3380) -- Remove scheduled jobs after changing cron settings (fixed in [#9957](https://github.com/magento/magento2/pull/9957))
+    * [#7504](https://github.com/magento/magento2/issues/7504) -- sitemap image URLs do not match with those on product pages (fixed in [#9082](https://github.com/magento/magento2/pull/9082))
+    * [#8732](https://github.com/magento/magento2/issues/8732) -- The country drop-down list display incorrect after upgrade to 2.1.4 in Admin (fixed in [#9429](https://github.com/magento/magento2/pull/9429))
+    * [#9680](https://github.com/magento/magento2/issues/9680) -- Adding product configurations uses sku based name (fixed in [#9681](https://github.com/magento/magento2/pull/9681))
+    * [#10017](https://github.com/magento/magento2/issues/10017) -- Customer Backend: Confirmation Flag is being overwritten by save of the Customer (fixed in [#9681](https://github.com/magento/magento2/pull/9681))
+    * [#2266](https://github.com/magento/magento2/issues/2266) -- Action column menu does not stay over the action column (fixed in [#10082](https://github.com/magento/magento2/pull/10082))
+    * [#5381](https://github.com/magento/magento2/issues/5381) -- Cannot create a `etc/view.xml` file with an `images` tag with an attribute `module` other than `Magento_Catalog` (fixed in [#10052](https://github.com/magento/magento2/pull/10052))
+    * [#6337](https://github.com/magento/magento2/issues/6337) -- Not able to translate page layout head titles (fixed in [#9992](https://github.com/magento/magento2/pull/9992))
+    * [#3872](https://github.com/magento/magento2/issues/3872) -- Slash as category URL suffix gives 404 error on all category pages (fixed in [#10043](https://github.com/magento/magento2/pull/10043))
+    * [#4660](https://github.com/magento/magento2/issues/4660) -- Multiple URLs causes duplicated content (fixed in [#10043](https://github.com/magento/magento2/pull/10043))
+    * [#4876](https://github.com/magento/magento2/issues/4876) -- Product URL Suffix "/" results in 404 error (fixed in [#10043](https://github.com/magento/magento2/pull/10043))
+    * [#8264](https://github.com/magento/magento2/issues/8264) -- Custom URL Rewrite where the request path ends with a forward slash is not matched (fixed in [#10043](https://github.com/magento/magento2/pull/10043))
+    * [#6396](https://github.com/magento/magento2/issues/6396) -- Cart Price Rules: Category selection UI for Conditions do not come up. (fixed in [#10094](https://github.com/magento/magento2/pull/10094))
+    * [#10124](https://github.com/magento/magento2/issues/10124) -- Wrong order of "width" x "height" when uploading image to admin under Content>Design Config (fixed in [#10126](https://github.com/magento/magento2/pull/10126))
+    * [#6594](https://github.com/magento/magento2/issues/6594) -- Magento 2.1 EE: simplexml_load_string() error in custom widget (fixed in [#10151](https://github.com/magento/magento2/pull/10151))
+    * [#10148](https://github.com/magento/magento2/issues/10148) -- Developer ACL incorrect (fixed in [#10149](https://github.com/magento/magento2/pull/10149))
+    * [#9445](https://github.com/magento/magento2/issues/9445) -- Cart 860 does not contain item 1204 (fixed in [#10059](https://github.com/magento/magento2/pull/10059))
+* GitHub pull requests:
+    * [#4078](https://github.com/magento/magento2/pull/4078) -- Add logo folder to list of allowed resources (by @thaiphan)
+    * [#4355](https://github.com/magento/magento2/pull/4355) -- Enforce password and password-confirm as strings (by @nevvermind)
+    * [#4175](https://github.com/magento/magento2/pull/4175) -- PHP 7 (by @rafaelstz)
+    * [#4669](https://github.com/magento/magento2/pull/4669) -- Php 5.5 support was removed (by @fooman)
+    * [#4766](https://github.com/magento/magento2/pull/4766) -- The time has come for splat operator (by @orlangur)
+    * [#4867](https://github.com/magento/magento2/pull/4867) -- Fix commandExecutor interface mismatch (by @wexo-team)
+    * [#3705](https://github.com/magento/magento2/pull/3705) -- fix issue #3704 regarding integer attribute values being cast to decimal (by @digitalpianism)
+    * [#3750](https://github.com/magento/magento2/pull/3750) -- Add ability to show custom error message on Authorizenet place order (by @ytorbyk)
+    * [#3859](https://github.com/magento/magento2/pull/3859) -- Fixes _toHtml method of Checkout/Block/Cart/Link class (by @ddonnini)
+    * [#4017](https://github.com/magento/magento2/pull/4017) -- Add the $t to translate the message (by @mamzellejuu)
+    * [#4239](https://github.com/magento/magento2/pull/4239) -- Attribute Model specifiable in Propertymapper (by @liolemaire)
+    * [#4583](https://github.com/magento/magento2/pull/4583) -- Fix desktop spelling in lib/web/css #4557 (by @BenSpace48)
+    * [#2735](https://github.com/magento/magento2/pull/2735) -- Add database port to Magento Setup Model Installer (by @tkn98)
+    * [#4275](https://github.com/magento/magento2/pull/4275) -- Database port missing in Magento\TestFramework\Db\Mysql #3529 (by @gordonknoppe)
+    * [#4372](https://github.com/magento/magento2/pull/4372) -- Remove unused property + use ::class (by @nevvermind)
+    * [#2274](https://github.com/magento/magento2/pull/2274) -- TypeError: this.trigger is not a function (by @daim2k5)
+    * [#3050](https://github.com/magento/magento2/pull/3050) -- Replace PrototypeJS (by @srenon)
+    * [#3436](https://github.com/magento/magento2/pull/3436) -- Fix stripped-min-length check (by @avoelkl)
+    * [#3638](https://github.com/magento/magento2/pull/3638) -- Fix #3637 Add missing catalogsearch layout for swatches. (by @romainruaud)
+    * [#3633](https://github.com/magento/magento2/pull/3633) -- #768 - fix Missing acl.xml for the Magento_Checkout module (by @tzyganu)
+    * [#3708](https://github.com/magento/magento2/pull/3708) -- Add 'yyyy' to nomalizedDate method map for adminhtml i18n (by @Amakata)
+    * [#3973](https://github.com/magento/magento2/pull/3973) -- fix bug on newsletter subscription action when user use an existing email already subscribed (by @manfrinm)
+    * [#3932](https://github.com/magento/magento2/pull/3932) -- Update Date.php (by @Maddesto)
+    * [#3907](https://github.com/magento/magento2/pull/3907) -- Update Layout.php (by @Maddesto)
+    * [#4051](https://github.com/magento/magento2/pull/4051) -- Fix "minimum-length" option of the "validate-length" JS validation (by @adragus-inviqa)
+    * [#4269](https://github.com/magento/magento2/pull/4269) -- ConfigurableProduct validator, first check if array item exists (by @BlackIkeEagle)
+    * [#4496](https://github.com/magento/magento2/pull/4496) -- Access element through jQuery (by @sikker)
+    * [#4631](https://github.com/magento/magento2/pull/4631) -- Previous is spelt incorrectly (by @BenSpace48)
+    * [#4882](https://github.com/magento/magento2/pull/4882) -- Fix handling is_region_required key as optional (by @komsitr)
+    * [#5028](https://github.com/magento/magento2/pull/5028) -- Load jquery using requirejs to print page (by @Bartlomiejsz)
+    * [#1957](https://github.com/magento/magento2/pull/1957) -- Add required interface implementation (by @udovicic)
+    * [#2492](https://github.com/magento/magento2/pull/2492) -- No translation from "Orders and Returns" footer links (by @mageho)
+    * [#3749](https://github.com/magento/magento2/pull/3749) -- Stop screen loader on payment error (by @ytorbyk)
+    * [#4901](https://github.com/magento/magento2/pull/4901) -- Fix XML validation value type of post-code to "boolean" (by @adragus-inviqa)
+    * [#5066](https://github.com/magento/magento2/pull/5066) -- Add underscore as dependency to quote.js (by @Bartlomiejsz)
+    * [#5116](https://github.com/magento/magento2/pull/5116) -- Fixes invalid json objects in the order email templates. (by @hostep)
+    * [#5095](https://github.com/magento/magento2/pull/5095) -- Fix integration test expectation to match count of countries in the database (by @Vinai)
+    * [#5200](https://github.com/magento/magento2/pull/5200) -- Adminhtml sales view - Escape remoteIp (by @convenient)
+    * [#4294](https://github.com/magento/magento2/pull/4294) -- Static deploy flags (by @denisristic)
+    * [#3137](https://github.com/magento/magento2/pull/3137) -- Update nginx.conf.sample (by @thaiphan)
+    * [#3746](https://github.com/magento/magento2/pull/3746) -- Add HttpInterface methods and add up-casts for type safety (by @Vinai)
+    * [#4354](https://github.com/magento/magento2/pull/4354) -- Adds test for getDataUsingMethod using digits (by @fooman)
+    * [#4396](https://github.com/magento/magento2/pull/4396) -- Don't hardcode the Magento_Backend::admin index (by @annybs)
+    * [#4491](https://github.com/magento/magento2/pull/4491) -- Correction: variable naming for user roles & role id (by @MagePsycho)
+    * [#4519](https://github.com/magento/magento2/pull/4519) -- Create auth.json.sample (by @rafaelstz)
+    * [#3688](https://github.com/magento/magento2/pull/3688) -- added partial fix for issue #2617.  (by @whizkid79)
+    * [#3770](https://github.com/magento/magento2/pull/3770) -- Bugfix: Unable to activate search form on phone (by @vovayatsyuk)
+    * [#4011](https://github.com/magento/magento2/pull/4011) -- Fixed post var name for update attributes (by @Corefix)
+    * [#2791](https://github.com/magento/magento2/pull/2791) -- Update Template.php (by @liam-wiltshire)
+    * [#5496](https://github.com/magento/magento2/pull/5496) -- Fixes #5495 (Mobile navigation submenus need two clicks to open) (by @ajpevers)
+    * [#5725](https://github.com/magento/magento2/pull/5725) -- Fix/translation in validation files (by @dvynograd)
+    * [#5915](https://github.com/magento/magento2/pull/5915) -- Added missing translation to range grid filter (by @maqlec)
+    * [#5884](https://github.com/magento/magento2/pull/5884) -- Use alias already defined in requirejs-config.js (by @kassner)
+    * [#4388](https://github.com/magento/magento2/pull/4388) -- Fixed column description for "website_id" column (by @ikk0)
+    * [#1628](https://github.com/magento/magento2/pull/1628) -- Add cache of configuration files list (by @otakarmare)
+    * [#4791](https://github.com/magento/magento2/pull/4791) -- Replace fabpot/php-cs-fixer with friendsofphp/php-cs-fixer (by @GordonLesti)
+    * [#5983](https://github.com/magento/magento2/pull/5983) -- Fix 'Track your order' i18n. (by @peec)
+    * [#1988](https://github.com/magento/magento2/pull/1988) -- Use inline elements for inline links (by @chicgeek)
+    * [#6283](https://github.com/magento/magento2/pull/6283) -- Update elements.xsd (by @aholovan)
+    * [#1935](https://github.com/magento/magento2/pull/1935) -- Added 'target' attribute to the allowed attributes array for link block (by @fcapua-summa)
+    * [#4733](https://github.com/magento/magento2/pull/4733) -- Escape Js Quote for layout updates (by @bchatard)
+    * [#4565](https://github.com/magento/magento2/pull/4565) -- Update Container.php (by @Maddesto)
+    * [#4845](https://github.com/magento/magento2/pull/4845) -- Set return code for SetModeCommand (by @mc388)
+    * [#2037](https://github.com/magento/magento2/pull/2037) -- Correct the error message when creating wrong object for block (by @hiephm)
+    * [#3779](https://github.com/magento/magento2/pull/3779) -- Add dispatching of view_block_abstract_to_html_after event (by @aleron75)
+    * [#5741](https://github.com/magento/magento2/pull/5741) -- Update AbstractTemplate.php (by @vivek201)
+    * [#5145](https://github.com/magento/magento2/pull/5145) -- \Magento\CatalogInventory\Model\Stock\Status->getStockId() to return correct value (by @fe-lix-)
+    * [#6009](https://github.com/magento/magento2/pull/6009) -- Update README.md (by @fooman)
+    * [#6280](https://github.com/magento/magento2/pull/6280) -- Fixed layout for customer authentication popup (by @rogyar)
+    * [#6549](https://github.com/magento/magento2/pull/6549) -- Remove obsolete comment in catalog_category_view.xml (by @pdanzinger)
+    * [#6804](https://github.com/magento/magento2/pull/6804) -- Fix nav not working in mobile (by @slackerzz)
+    * [#6801](https://github.com/magento/magento2/pull/6801) -- Fixed unclosed span tag in Review module (by @PingusPepan)
+    * [#5045](https://github.com/magento/magento2/pull/5045) -- Fix runner for JsTestDriver based tests on OS X (by @Vinai)
+    * [#4958](https://github.com/magento/magento2/pull/4958) -- block newsletter title (by @slackerzz)
+    * [#5548](https://github.com/magento/magento2/pull/5548) -- Fix error with the WYSIWYG and Greek characters (by @sakisplus)
+    * [#7256](https://github.com/magento/magento2/pull/7256) -- Fix incorrect table name during catalog product indexing (by @nagno)
+    * [#6972](https://github.com/magento/magento2/pull/6972) -- Fix issue #6968 since checkout success title is not displayed (by @AngelVazquezArroyo)
+    * [#4121](https://github.com/magento/magento2/pull/4121) -- Ensure composer.json exists (by @dank00)
+    * [#4134](https://github.com/magento/magento2/pull/4134) -- Added call to action to compile command error (by @sammarcus)
+    * [#6974](https://github.com/magento/magento2/pull/6974) -- Fixed calling non exists order address->getCountry to getCountryId (by @magexo)
+    * [#4088](https://github.com/magento/magento2/pull/4088) -- Fix newsletter queue subscribers adding performance (by @DariuszMaciejewski)
+    * [#6952](https://github.com/magento/magento2/pull/6952) -- Update AccountLock.php (by @klict)
+    * [#5465](https://github.com/magento/magento2/pull/5465) -- Fix Magento\Review\Model\ResourceModel\Rating\Option not instantiable in setup scripts (by @adragus-inviqa)
+    * [#7799](https://github.com/magento/magento2/pull/7799) -- Remove duplicate code from template file.  (by @dverkade)
+    * [#7919](https://github.com/magento/magento2/pull/7919) -- Using Dynamic Protocol Concatination (by @brobie)
+    * [#7921](https://github.com/magento/magento2/pull/7921) -- Removed un-used static version rewrite rule in nginx.conf.sample (by @careys7)
+    * [#8019](https://github.com/magento/magento2/pull/8019) -- added fr_CH to allowed locales list (by @annapivniak)
+    * [#8082](https://github.com/magento/magento2/pull/8082) -- issue 8080: Cron configuration loading from DB doesn't work (by @ytorbyk)
+    * [#8062](https://github.com/magento/magento2/pull/8062) -- Fix theme source model used in widget grid (by @Zefiryn)
+    * [#8232](https://github.com/magento/magento2/pull/8232) -- Fix notice during DI compilation (by @qrz-io)
+    * [#8306](https://github.com/magento/magento2/pull/8306) -- Remove warning from setup/src/Magento/Setup/Module/I18n/Dictionary/Writer/Csv.php (by @dmanners)
+    * [#8185](https://github.com/magento/magento2/pull/8185) -- Fix #7461 using the simplest approach for now (by @lazyguru)
+    * [#8183](https://github.com/magento/magento2/pull/8183) -- [BUGFIX] Fixed the credit memo guest email (by @nickgraz)
+    * [#8161](https://github.com/magento/magento2/pull/8161) -- Return focus to search input after closing autocomplete dropdown (by @evktalo)
+    * [#8155](https://github.com/magento/magento2/pull/8155) -- Correct php doc (by @angelomaragna)
+    * [#8341](https://github.com/magento/magento2/pull/8341) -- Use better function for 'Continue Shopping' url (by @dmatthew)
+    * [#8336](https://github.com/magento/magento2/pull/8336) -- fixing time format on admin sales order grid (by @magexo)
+    * [#8327](https://github.com/magento/magento2/pull/8327) -- Change order of parameters passed to LogicException in AbstractTemplate.php (by @bery)
+    * [#8307](https://github.com/magento/magento2/pull/8307) -- Allow digits in communication class type definition (by @cmuench)
+    * [#8354](https://github.com/magento/magento2/pull/8354) -- Display correctly "Add" button label for the block class \Magento\Con… (by @diglin)
+    * [#8246](https://github.com/magento/magento2/pull/8246) -- Fixes #7723 - saving multi select field in UI component form (by @Zefiryn)
+    * [#8353](https://github.com/magento/magento2/pull/8353) -- Replace into the layout adminhtml_order_shipment_new.xml block alias … (by @diglin)
+    * [#8395](https://github.com/magento/magento2/pull/8395) -- Added "editPost" action for customer sections.xml (by @rossluk)
+    * [#8383](https://github.com/magento/magento2/pull/8383) -- Issue/8382 (by @PascalBrouwers)
+    * [#8151](https://github.com/magento/magento2/pull/8151) -- Remove "<2.7" constraint on symfony/console (by @nicolas-grekas)
+    * [#8416](https://github.com/magento/magento2/pull/8416) -- Use configured product attributes in wishlist item collection (by @schmengler)
+    * [#8414](https://github.com/magento/magento2/pull/8414) -- Replace toGMTString with toUTCString (by @schmengler)
+    * [#8419](https://github.com/magento/magento2/pull/8419) -- Use page result instead of rendering layout directly in controllers (by @schmengler)
+    * [#8331](https://github.com/magento/magento2/pull/8331) -- Remove Zend1 Json from Magento Captcha module (by @dmanners)
+    * [#8252](https://github.com/magento/magento2/pull/8252) -- Customer account edit form: additional info block visible (by @Sylvco)
+    * [#8405](https://github.com/magento/magento2/pull/8405) -- Remove the unused Ajax/Serializer.php class (by @dmanners)
+    * [#8402](https://github.com/magento/magento2/pull/8402) -- Remove Zend1 db from captcha module (by @dmanners)
+    * [#8463](https://github.com/magento/magento2/pull/8463) -- Remove outdated comment (by @evktalo)
+    * [#8456](https://github.com/magento/magento2/pull/8456) -- Specifically ask for the Json Serializer object Mage Braintree (by @dmanners)
+    * [#8446](https://github.com/magento/magento2/pull/8446) -- Fix "each()" function call on potentially invalid data (by @giacmir)
+    * [#5928](https://github.com/magento/magento2/pull/5928) -- prevent double shipping method selection (by @danslo)
+    * [#8217](https://github.com/magento/magento2/pull/8217) -- Update DataProvider.php (by @redelschaap)
+    * [#8413](https://github.com/magento/magento2/pull/8413) -- Load translations for area, fixes #8412 (by @fooman)
+    * [#8356](https://github.com/magento/magento2/pull/8356) -- Remove Zend1 captcha from Magento2 Captcha module (by @dmanners)
+    * [#8474](https://github.com/magento/magento2/pull/8474) -- Fix for https://github.com/magento/magento2/issues/8287 (by @ericrisler)
+    * [#8487](https://github.com/magento/magento2/pull/8487) -- Mark the STDO test as skipped (by @dmanners)
+    * [#3155](https://github.com/magento/magento2/pull/3155) -- Remove unused variables in unit test (by @fooman)
+    * [#6049](https://github.com/magento/magento2/pull/6049) -- Added typo correction for table name comment (by @atishgoswami)
+    * [#4370](https://github.com/magento/magento2/pull/4370) -- update Catalog Helper (by @barbarich-p)
+    * [#4106](https://github.com/magento/magento2/pull/4106) -- Adds support for purging varnish cache based on an X-Pool header (by @davidalger)
+    * [#7982](https://github.com/magento/magento2/pull/7982) -- Add bin/magento commands to list store/website data (by @convenient)
+    * [#8434](https://github.com/magento/magento2/pull/8434) -- Problem on mobile when catalog gallery allowfullscreen is false #5808 (by @Crossmotion)
+    * [#8417](https://github.com/magento/magento2/pull/8417) -- add anonymize ip option for google analytics (by @thomas-villagers)
+    * [#8498](https://github.com/magento/magento2/pull/8498) -- Product->save() shouldn't be called directly (by @stansm)
+    * [#8581](https://github.com/magento/magento2/pull/8581) -- Fixed overly bold icons in Firefox Mac (by @TandyCorp)
+    * [#8481](https://github.com/magento/magento2/pull/8481) -- Remove zend json checkout (by @dmanners)
+    * [#8518](https://github.com/magento/magento2/pull/8518) -- Change link text from "Report Bugs" to "Report a Bug" (by @Zifius)
+    * [#8514](https://github.com/magento/magento2/pull/8514) -- Add missing name attributes to catalog_product_view layout xml (by @andrewnoble)
+    * [#8505](https://github.com/magento/magento2/pull/8505) -- Update the Adminhtml image tree JSON (by @dmanners)
+    * [#8467](https://github.com/magento/magento2/pull/8467) -- Fix for magento/magento2#8392 (by @kirashet666)
+    * [#8617](https://github.com/magento/magento2/pull/8617) -- Remove Zend_Json from Customer module (by @dmanners)
+    * [#8609](https://github.com/magento/magento2/pull/8609) -- [PHP 7.1 Compatibility] Void became a reserved word (by @orlangur)
+    * [#8611](https://github.com/magento/magento2/pull/8611) -- Fix #8308: test setup/src/Magento/Setup/Test/Unit/Model/Cron/JobSetCacheTest.php crashes in debug mode (by @orlangur)
+    * [#8610](https://github.com/magento/magento2/pull/8610) -- Fix #8315: test setup/src/Magento/Setup/Test/Unit/Module/I18n/Dictionary/Writer/Csv/StdoTest.php crashes in debug mode (by @orlangur)
+    * [#7339](https://github.com/magento/magento2/pull/7339) -- Fix/xml parser issue (by @dvynograd)
+    * [#7345](https://github.com/magento/magento2/pull/7345) -- Fix typo (by @mpchadwick)
+    * [#7406](https://github.com/magento/magento2/pull/7406) -- MAGETWO-60448 (by @vasilii-b)
+    * [#8000](https://github.com/magento/magento2/pull/8000) -- Set static html fragments as cacheable (by @paveq)
+    * [#8077](https://github.com/magento/magento2/pull/8077) -- Type cast  (by @deriknel)
+    * [#8278](https://github.com/magento/magento2/pull/8278) -- bug #8277 fixing bug with https downloading. (by @clementbeudot)
+    * [#8420](https://github.com/magento/magento2/pull/8420) -- Refactor contact module (by @schmengler)
+    * [#8519](https://github.com/magento/magento2/pull/8519) -- Make "is_required" and "is_visible" properties of telephone, company and fax attributes of addresses configurable (by @avstudnitz)
+    * [#8537](https://github.com/magento/magento2/pull/8537) -- Fixed missing echo statement in checkout cart coupon template (by @FrankRuis)
+    * [#8602](https://github.com/magento/magento2/pull/8602) -- Fixed crosssells count always null (by @koenner01)
+    * [#8593](https://github.com/magento/magento2/pull/8593) -- Fix #7371 (by @rossluk)
+    * [#8642](https://github.com/magento/magento2/pull/8642) -- Update Save.php (by @josefbehr)
+    * [#8633](https://github.com/magento/magento2/pull/8633) -- Fix #8632 (by @koenner01)
+    * [#8513](https://github.com/magento/magento2/pull/8513) -- Replace ext name spaces with dashes (as composer does when storing) (by @AydinHassan)
+    * [#8668](https://github.com/magento/magento2/pull/8668) -- Add correct return type in order service (by @cmuench)
+    * [#8677](https://github.com/magento/magento2/pull/8677) -- Fixed Doc Block for the dispatch method of the Rest Controller (by @vrann)
+    * [#3585](https://github.com/magento/magento2/pull/3585) -- Remove duplicate switchIsFilterable (by @GordonLesti)
+    * [#8132](https://github.com/magento/magento2/pull/8132) -- Fix incorrect schema definition for price (by @unfunco)
+    * [#2275](https://github.com/magento/magento2/pull/2275) -- Updated links to point to http://devdocs.magento.com/guides/v2.0 (by @wjarka)
+    * [#8683](https://github.com/magento/magento2/pull/8683) -- Fixed return type of OrderRepository::getList (by @clementbeudot)
+    * [#8682](https://github.com/magento/magento2/pull/8682) -- Remove unused argument (by @mfdj)
+    * [#2185](https://github.com/magento/magento2/pull/2185) -- unused variable (by @barbarich-p)
+    * [#7894](https://github.com/magento/magento2/pull/7894) -- Fix #7893 (by @andreaspenz)
+    * [#8623](https://github.com/magento/magento2/pull/8623) -- Fix check for boolean product attributes (by @TKlement)
+    * [#8678](https://github.com/magento/magento2/pull/8678) -- Fixed Issue #8425 (by @DavidLambauer)
+    * [#8711](https://github.com/magento/magento2/pull/8711) -- Remove Zend_Json from the persistent module remember me status observer (by @dmanners)
+    * [#8706](https://github.com/magento/magento2/pull/8706) -- Remove Zend_Json from the unit test in the CustomerImportExport module (by @dmanners)
+    * [#8723](https://github.com/magento/magento2/pull/8723) -- Add active class to search form wrapper for more theming flexibility (by @andrewkett)
+    * [#8768](https://github.com/magento/magento2/pull/8768) -- Fix issue #8709 (by @renatocason)
+    * [#8762](https://github.com/magento/magento2/pull/8762) -- Fix issue #2558 (by @renatocason)
+    * [#8759](https://github.com/magento/magento2/pull/8759) -- magento/magento2#8618: Apply coupon code button issue on Checkout (by @mcspronko)
+    * [#8776](https://github.com/magento/magento2/pull/8776) -- Range filter doesn't works with 0  values in admin #7103 (by @giacmir)
+    * [#7611](https://github.com/magento/magento2/pull/7611) -- Update catalog_rule_form.xml edit labels (by @fernandofauth)
+    * [#7650](https://github.com/magento/magento2/pull/7650) -- Add host header to varnish cache purge request (by @m0zziter)
+    * [#7914](https://github.com/magento/magento2/pull/7914) -- FPC JS - Fix for CORS issue (by @OZZlE)
+    * [#8013](https://github.com/magento/magento2/pull/8013) -- Update resets.html (by @ryantfowler)
+    * [#8041](https://github.com/magento/magento2/pull/8041) -- Fix USPS Priority Mail to Canada (by @jaywilliams)
+    * [#8014](https://github.com/magento/magento2/pull/8014) -- Update _resets.less (by @ryantfowler)
+    * [#8053](https://github.com/magento/magento2/pull/8053) -- Strict checking types during di compilation (by @michalderlatka)
+    * [#8048](https://github.com/magento/magento2/pull/8048) -- Consistent HTML tags and breaks (by @chickenland)
+    * [#8056](https://github.com/magento/magento2/pull/8056) -- update allowed container tags (by @steros)
+    * [#8158](https://github.com/magento/magento2/pull/8158) -- Fix OAuth request helper to support Authorization header value parsing with non-leading OAuth key (by @careys7)
+    * [#8589](https://github.com/magento/magento2/pull/8589) -- Set correct primary keys for temporary tables in product flat indexer (by @jarnooravainen)
+    * [#8736](https://github.com/magento/magento2/pull/8736) -- Update Stock.php (by @Corefix)
+    * [#8119](https://github.com/magento/magento2/pull/8119) -- Throw exception for invalid (missing) template in dev mode (by @convenient)
+    * [#8690](https://github.com/magento/magento2/pull/8690) -- Fix SALES_ORDER_TAX_ITEM_TAX_ID_ITEM_ID duplicates (by @mimarcel)
+    * [#8743](https://github.com/magento/magento2/pull/8743) -- Validate PHP classnames in di.xml files via schema (by @ktomk)
+    * [#8714](https://github.com/magento/magento2/pull/8714) -- Quote values in IN() predicate to avoid cast issues (by @xi-ao)
+    * [#8835](https://github.com/magento/magento2/pull/8835) -- Replace Zend_Json from the Magento Review module (by @dmanners)
+    * [#8832](https://github.com/magento/magento2/pull/8832) -- Replace Zend_Json from the Magento Quote module (by @dmanners)
+    * [#8839](https://github.com/magento/magento2/pull/8839) -- Rename to DataObjectTest (by @mfdj)
+    * [#2199](https://github.com/magento/magento2/pull/2199) -- Rename admin sidebar Products to Catalog #2060 (by @markoshust)
+    * [#5620](https://github.com/magento/magento2/pull/5620) -- Remove superfluous method call. (by @maksim-grib)
+    * [#6767](https://github.com/magento/magento2/pull/6767) -- Removed setting routerlist twice. (by @dverkade)
+    * [#6257](https://github.com/magento/magento2/pull/6257) -- Fix "none" is not meant to be translated in catalog_product_view layout file (by @azanelli)
+    * [#7645](https://github.com/magento/magento2/pull/7645) -- Storecode in url changed from default to all (by @bartlubbersen)
+    * [#7864](https://github.com/magento/magento2/pull/7864) -- Bugfix: Fix for not respected alternative headers in maintenance mode (by @cmuench)
+    * [#7794](https://github.com/magento/magento2/pull/7794) -- Check return value for getProduct() in getPrice(). (by @pbaylies)
+    * [#8052](https://github.com/magento/magento2/pull/8052) -- Update PurgeCache.php (by @bery)
+    * [#8130](https://github.com/magento/magento2/pull/8130) -- Update Options.php (by @redelschaap)
+    * [#8079](https://github.com/magento/magento2/pull/8079) -- FIX Backend mass delete Sql error (by @asubit)
+    * [#7234](https://github.com/magento/magento2/pull/7234) -- Lossless images optimalization (by @Igloczek)
+    * [#8685](https://github.com/magento/magento2/pull/8685) -- [PSR-2 Compliance] Fix #8612: Hundreds of PHPCS-based static tests violations in mainline (by @orlangur)
+    * [#7568](https://github.com/magento/magento2/pull/7568) -- Minor Update Mysql.php (by @WJdeBaas)
+    * [#7598](https://github.com/magento/magento2/pull/7598) -- Bugfix for _getProductCollection on a product page (by @evgk)
+    * [#8886](https://github.com/magento/magento2/pull/8886) -- Fix typo in app/code/Magento/Email/Test/Unit/Model/TemplateTest.php (by @orlangur)
+    * [#5029](https://github.com/magento/magento2/pull/5029) -- Add default swatch_image placeholder (by @Bartlomiejsz)
+    * [#6838](https://github.com/magento/magento2/pull/6838) -- Removed preference from di.xml (by @dverkade)
+    * [#7578](https://github.com/magento/magento2/pull/7578) -- Don't skip attribute options with a value of 0 from the layered navigation (by @dcabrejas)
+    * [#7615](https://github.com/magento/magento2/pull/7615) -- Fixes duplicate messages shown when adding items to cart (by @comdiler)
+    * [#7590](https://github.com/magento/magento2/pull/7590) -- Reset skippedRows array in clear method (by @ccasciotti)
+    * [#7701](https://github.com/magento/magento2/pull/7701) -- Allows you to have 0 as a option (by @Corefix)
+    * [#7748](https://github.com/magento/magento2/pull/7748) -- Remove _required class from ZIP field (by @dmitryshkolnikov)
+    * [#7743](https://github.com/magento/magento2/pull/7743) -- MAGETWO-61828: Text swatch "zero" not shown (by @oroskodias)
+    * [#8883](https://github.com/magento/magento2/pull/8883) -- Fix a typo (by @evgk)
+    * [#7541](https://github.com/magento/magento2/pull/7541) -- Added "Add / update" comment. Update was missing. (by @gastondisacco)
+    * [#8808](https://github.com/magento/magento2/pull/8808) -- Change link text from "Report a Bug" to "Report an Issue" (by @Zifius)
+    * [#8907](https://github.com/magento/magento2/pull/8907) -- Removed unused dependencys (by @ikrs)
+    * [#8910](https://github.com/magento/magento2/pull/8910) -- Prevent overwriting grunt config (by @Igloczek)
+    * [#7562](https://github.com/magento/magento2/pull/7562) -- Update AbstractCart.php (by @Corefix)
+    * [#8766](https://github.com/magento/magento2/pull/8766) -- fix $childrenWrapClass never used (by @slackerzz)
+    * [#8822](https://github.com/magento/magento2/pull/8822) -- Upgrade PHP CS Fixer to v2 (by @keradus)
+    * [#8901](https://github.com/magento/magento2/pull/8901) -- Update design_config_form.xml (by @WaPoNe)
+    * [#8896](https://github.com/magento/magento2/pull/8896) -- Fix all words without " (by @rafaelstz)
+    * [#8912](https://github.com/magento/magento2/pull/8912) -- magento/magento2#8590: M2.1.4 : ArrayBackend cannot save and Added country regions for Croatia (by @nkajic)
+    * [#8909](https://github.com/magento/magento2/pull/8909) -- magento/magento2#8863: Malta zipcode validation incomplete (by @mmacinko)
+    * [#2829](https://github.com/magento/magento2/pull/2829) -- Update final_price.phtml (by @liam-wiltshire)
+    * [#3869](https://github.com/magento/magento2/pull/3869) -- Optional PHP7.0 Socket Path (by @digimix)
+    * [#4854](https://github.com/magento/magento2/pull/4854) -- Fix admin menu bug (by @NikolasSumrak)
+    * [#6400](https://github.com/magento/magento2/pull/6400) -- Fix for Product Attribute's Conditions (by @NikolasSumrak)
+    * [#6677](https://github.com/magento/magento2/pull/6677) -- Update addCategoriesFilter to return $this (by @maciekpaprocki)
+    * [#6894](https://github.com/magento/magento2/pull/6894) -- Fixed phpseclib\Net\SFTP constants used in write() method (by @federivo)
+    * [#7117](https://github.com/magento/magento2/pull/7117) -- Add de_LU and fr_LU languages for Luxembourg (by @ajpevers)
+    * [#8915](https://github.com/magento/magento2/pull/8915) -- magento/magetno2#8676: I can not translate title attribute in xml fil… (by @DanijelPotocki)
+    * [#5446](https://github.com/magento/magento2/pull/5446) -- Fix Rest Api - GET /V1/configurable-products/{sku}/children not giving ID in response (by @k-andrew)
+    * [#6321](https://github.com/magento/magento2/pull/6321) -- Add missing return in resolveShippingRates (by @GordonLesti)
+    * [#6707](https://github.com/magento/magento2/pull/6707) -- Issue/6706 (by @PascalBrouwers)
+    * [#6794](https://github.com/magento/magento2/pull/6794) -- Move cache to instance of price box widget (by @JamesonNetworks)
+    * [#6856](https://github.com/magento/magento2/pull/6856) -- Issue/6855 (by @PascalBrouwers)
+    * [#6837](https://github.com/magento/magento2/pull/6837) -- Removed argument from di.xml (by @dverkade)
+    * [#6878](https://github.com/magento/magento2/pull/6878) -- Media attribute folder to be ignored (by @rafaelstz)
+    * [#6914](https://github.com/magento/magento2/pull/6914) -- Put the contants in the same docblock together (by @dverkade)
+    * [#6913](https://github.com/magento/magento2/pull/6913) -- Removed commented out line for ignoring coding standards (by @dverkade)
+    * [#7142](https://github.com/magento/magento2/pull/7142) -- [Framework][Translate] Changed translation order to allow language (by @JSchlarb)
+    * [#7352](https://github.com/magento/magento2/pull/7352) -- Product export duplicate rows for product with html special chars in data. Bugfix for #7350 (by @comdiler)
+    * [#8445](https://github.com/magento/magento2/pull/8445) -- Changed name of dispatched object in delete event (by @clementbeudot)
+    * [#8959](https://github.com/magento/magento2/pull/8959) -- Fixes #2461 (by @ajpevers)
+    * [#8950](https://github.com/magento/magento2/pull/8950) -- Remove deadcode (by @jipjop)
+    * [#3469](https://github.com/magento/magento2/pull/3469) -- respect depends declaration in system.xml for form element (by @phoenix-bjoern)
+    * [#5362](https://github.com/magento/magento2/pull/5362) -- Make CMS directive filtering error be more generic (by @erikhansen)
+    * [#6354](https://github.com/magento/magento2/pull/6354) -- Newsletter Email fix (by @inettman)
+    * [#6744](https://github.com/magento/magento2/pull/6744) -- add-product-image-label-bug (by @markpol)
+    * [#6773](https://github.com/magento/magento2/pull/6773) -- Allow to insert Persian characters for attributes! (by @sIiiS)
+    * [#6779](https://github.com/magento/magento2/pull/6779) -- Changed documentation of the cache variable (by @dverkade)
+    * [#6775](https://github.com/magento/magento2/pull/6775) -- Changed constructor to use interface instead of direct classname (by @dverkade)
+    * [#6971](https://github.com/magento/magento2/pull/6971) -- fix #6961 (by @razbakov)
+    * [#7097](https://github.com/magento/magento2/pull/7097) -- You -> Your (by @avitex)
+    * [#7414](https://github.com/magento/magento2/pull/7414) -- Fix typo (by @convenient)
+    * [#8005](https://github.com/magento/magento2/pull/8005) -- Prevent cross origin iframe content reading (by @Igloczek)
+    * [#8753](https://github.com/magento/magento2/pull/8753) -- Added Translation for required Data-Attribute (by @DavidLambauer)
+    * [#8778](https://github.com/magento/magento2/pull/8778) -- magento/magento2: #8765 (by @cavalier79)
+    * [#8914](https://github.com/magento/magento2/pull/8914) -- magento/magetno2#8529:Typo in error message "Table  is not exists" (by @bvrbanec)
+    * [#2448](https://github.com/magento/magento2/pull/2448) -- Fix Inconsistency (by @srenon)
+    * [#2093](https://github.com/magento/magento2/pull/2093) -- Remove call to load() in getChildrenCategories method (by @davidalger)
+    * [#4179](https://github.com/magento/magento2/pull/4179) -- fix typo in Magento_Catalog toolbar less source (by @gil--)
+    * [#5078](https://github.com/magento/magento2/pull/5078) -- Rename $websiteId to $scopeId (by @flancer64)
+    * [#5207](https://github.com/magento/magento2/pull/5207) -- Table name fix - rule_customer to salesrule_customer (by @Bartlomiejsz)
+    * [#5858](https://github.com/magento/magento2/pull/5858) -- Save shipping discount in $total (by @flancer64)
+    * [#6811](https://github.com/magento/magento2/pull/6811) -- Unable to save subscription checkbox on Admin customer save (by @rich1990)
+    * [#6839](https://github.com/magento/magento2/pull/6839) -- Changed constructor to use an interface (by @dverkade)
+    * [#6912](https://github.com/magento/magento2/pull/6912) -- Changed module readme text (by @dverkade)
+    * [#7262](https://github.com/magento/magento2/pull/7262) -- Replace boolean cast to be able to disable frame, aspect ratio, trans… (by @joost-florijn-kega)
+    * [#7762](https://github.com/magento/magento2/pull/7762) -- change getId() to getPaymentId() (by @HirokazuNishi)
+    * [#8769](https://github.com/magento/magento2/pull/8769) -- magento/magento2#7860: Invalid comment for the method __order in Mage… (by @mcspronko)
+    * [#8917](https://github.com/magento/magento2/pull/8917) -- imagento/magento2#8515: Downloadable product is available for downloa… (by @nazarpadalka)
+    * [#8908](https://github.com/magento/magento2/pull/8908) -- magento/magento2#8871: Typo in Pull Request Template (by @tomislavsantek)
+    * [#8989](https://github.com/magento/magento2/pull/8989) -- Remove redundant check in if-condition (by @FabianLauer)
+    * [#8953](https://github.com/magento/magento2/pull/8953) -- Log level for caught exception (by @flancer64)
+    * [#8994](https://github.com/magento/magento2/pull/8994) -- Syntax fix (by @rafaelstz)
+    * [#1895](https://github.com/magento/magento2/pull/1895) -- Fix relative template references in individual Magento modules (by @davidalger)
+    * [#4224](https://github.com/magento/magento2/pull/4224) -- Update get.php (by @thaiphan)
+    * [#6567](https://github.com/magento/magento2/pull/6567) -- Always skip hidden files (by @quickshiftin)
+    * [#6989](https://github.com/magento/magento2/pull/6989) -- Allow extending config variables (by @adragus-inviqa)
+    * [#7218](https://github.com/magento/magento2/pull/7218) -- Set store id on block only when empty (by @dank00)
+    * [#7161](https://github.com/magento/magento2/pull/7161) -- Fix a bug resulting in incorrect offsets with dynamic row drag-n-drop functionality (by @navarr)
+    * [#7664](https://github.com/magento/magento2/pull/7664) -- Fix for "Stock Status" field not disappearing in admin when "Manage Stock" = No (by @comdiler)
+    * [#8812](https://github.com/magento/magento2/pull/8812) -- Fix count SQL on products sold collection (by @jameshalsall)
+    * [#8991](https://github.com/magento/magento2/pull/8991) -- Update AbstractModel.php (by @redelschaap)
+    * [#9001](https://github.com/magento/magento2/pull/9001) -- Fix #3791 (by @quienti)
+    * [#8998](https://github.com/magento/magento2/pull/8998) -- Fixed empty submenu group in backend menu (by @vovayatsyuk)
+    * [#8928](https://github.com/magento/magento2/pull/8928) -- Stop $this->validColumnNames array from growing and growing (by @jalogut)
+    * [#4149](https://github.com/magento/magento2/pull/4149) -- Fix wording of downloadable Products (by @bh-ref)
+    * [#4674](https://github.com/magento/magento2/pull/4674) -- Refactor repeating logic (by @nevvermind)
+    * [#4501](https://github.com/magento/magento2/pull/4501) -- Add Crowdin badge - official translations (by @piotrekkaminski)
+    * [#6243](https://github.com/magento/magento2/pull/6243) -- Set getConnection() as public method  (by @flancer64)
+    * [#6250](https://github.com/magento/magento2/pull/6250) -- Return the same data on exit (by @flancer64)
+    * [#4844](https://github.com/magento/magento2/pull/4844) -- Fix typo (by @orlangur)
+    * [#4874](https://github.com/magento/magento2/pull/4874) -- Make NL zipcode pattern less strict (by @tdgroot)
+    * [#5400](https://github.com/magento/magento2/pull/5400) -- Privacy Policy translation (fixes Issue #2951) (by @MindConflicts)
+    * [#5671](https://github.com/magento/magento2/pull/5671) -- Fix small typo (by @adragus-inviqa)
+    * [#6132](https://github.com/magento/magento2/pull/6132) -- Remove an extra space while clearing indexed stock items. (by @nntoan)
+    * [#6840](https://github.com/magento/magento2/pull/6840) -- Removed unused variable $routerId (by @dverkade)
+    * [#6834](https://github.com/magento/magento2/pull/6834) -- Removed default values for title, meta description, better labels. (by @paales)
+    * [#7124](https://github.com/magento/magento2/pull/7124) -- Code documentation corrections (by @evktalo)
+    * [#7294](https://github.com/magento/magento2/pull/7294) -- Let less continue compilation if file is empty (by @timo-schmid)
+    * [#8648](https://github.com/magento/magento2/pull/8648) -- Remove the copyright year from file headers (by @jameshalsall)
+    * [#4897](https://github.com/magento/magento2/pull/4897) -- Schedule generation was broken (by @ajpevers)
+    * [#5503](https://github.com/magento/magento2/pull/5503) -- ACL titles are swapped (by @yireo)
+    * [#7344](https://github.com/magento/magento2/pull/7344) -- Fix checking active carrier against store (by @torreytsui)
+    * [#7221](https://github.com/magento/magento2/pull/7221) -- Typo fix (by @gastondisacco)
+    * [#8982](https://github.com/magento/magento2/pull/8982) -- Move blank theme dependencies out of Magento_Theme requirejs-config (by @mikeoloughlin)
+    * [#8930](https://github.com/magento/magento2/pull/8930) -- Improved check when CategoryProcessor attempts to create a new category (by @ccasciotti)
+    * [#8923](https://github.com/magento/magento2/pull/8923) -- Check of null result value in swatch-renderer.js (by @aholovan)
+    * [#9013](https://github.com/magento/magento2/pull/9013) -- Added JS Jasmine tests to Travis CI (by @Igloczek)
+    * [#9039](https://github.com/magento/magento2/pull/9039) -- Translation in adminhtml Import form (by @Nolwennig)
+    * [#9034](https://github.com/magento/magento2/pull/9034) -- Invalidate and refresh customer data sections on HTTP DELETE requests (by @Vinai)
+    * [#6322](https://github.com/magento/magento2/pull/6322) -- Admin product edit block getHeader is not used (by @kassner)
+    * [#7045](https://github.com/magento/magento2/pull/7045) -- In case something wrong with underlying products (by @Will-I4M)
+    * [#8568](https://github.com/magento/magento2/pull/8568) -- Fix quote's outdated shipping address overwriting PayPal Express shipping address (by @torreytsui)
+    * [#9057](https://github.com/magento/magento2/pull/9057) -- remove duplicate method call (#9017) (by @will-b)
+    * [#9080](https://github.com/magento/magento2/pull/9080) -- Fix grammar mistakes with subscriptions - fixes #7498 (by @sambolek)
+    * [#9076](https://github.com/magento/magento2/pull/9076) -- Fix typo (by @PieterCappelle)
+    * [#9061](https://github.com/magento/magento2/pull/9061) -- Empty resolvedScopeCodes when config cache is cleaned (by @andreas-wickberg-vaimo)
+    * [#9044](https://github.com/magento/magento2/pull/9044) -- Remove superfluous character in class (by @tkn98)
+    * [#9095](https://github.com/magento/magento2/pull/9095) -- Added translation to label argument xml. (by @mrkhoa99)
+    * [#9108](https://github.com/magento/magento2/pull/9108) -- Redundant expression */1 in crontab.xml (by @giacmir)
+    * [#9170](https://github.com/magento/magento2/pull/9170) -- Corrected class name in documentation. (by @dfelton)
+    * [#6778](https://github.com/magento/magento2/pull/6778) -- Changed locator class name for ObjectManager (by @dverkade)
+    * [#7556](https://github.com/magento/magento2/pull/7556) -- Fix merging nested  in view.xml (by @torreytsui)
+    * [#8903](https://github.com/magento/magento2/pull/8903) -- Include Reply-To name in contact form email header (by @josephmcdermott)
+    * [#9140](https://github.com/magento/magento2/pull/9140) -- remove duplicate calls to initObjectManager in bootstrap class (by @sivajik34)
+    * [#9133](https://github.com/magento/magento2/pull/9133) -- Favicon folder added on gitignore (by @rafaelstz)
+    * [#9204](https://github.com/magento/magento2/pull/9204) -- FPT label not translatable in the totals on the cart page.  (by @okorshenko)
+    * [#5043](https://github.com/magento/magento2/pull/5043) -- Change 'select' to 'query' in props (by @flancer64)
+    * [#5367](https://github.com/magento/magento2/pull/5367) -- Change pub/.htaccess MAGE_MODE comment (by @erikhansen)
+    * [#5742](https://github.com/magento/magento2/pull/5742) -- Collection walk method bug fix when specific callback function (by @jalogut)
+    * [#6385](https://github.com/magento/magento2/pull/6385) -- Replace EE License Placeholder text with filename (by @navarr)
+    * [#6443](https://github.com/magento/magento2/pull/6443) -- Refactor Option ResourceModel to allow price supporting types to be intercepted (by @navarr)
+    * [#6772](https://github.com/magento/magento2/pull/6772) -- Changed constructor to use an interface (by @dverkade)
+    * [#6910](https://github.com/magento/magento2/pull/6910) -- Good practice, license in readme file (by @rafaelstz)
+    * [#7506](https://github.com/magento/magento2/pull/7506) -- Add configurations for change email templates (by @kassner)
+    * [#7464](https://github.com/magento/magento2/pull/7464) -- Is Allowed Guest Checkout (by @hungvt)
+    * [#7900](https://github.com/magento/magento2/pull/7900) -- Setting proper resource name (by @ddattee)
+    * [#8462](https://github.com/magento/magento2/pull/8462) -- Fix product option files not copying to order dir. (by @evktalo)
+    * [#8824](https://github.com/magento/magento2/pull/8824) -- Popup-Modal not closing on Safari/Windows (by @Hansschouten)
+    * [#9062](https://github.com/magento/magento2/pull/9062) -- Upgrade JS dependencies (by @Igloczek)
+    * [#9084](https://github.com/magento/magento2/pull/9084) -- Fix Google Analytics typo in printing Account Number, fixes #7549 (by @sambolek)
+    * [#9112](https://github.com/magento/magento2/pull/9112) -- Fix attribute label on product page at different store views (by @tufahu)
+    * [#9103](https://github.com/magento/magento2/pull/9103) -- Cli info di (by @springerin)
+    * [#9165](https://github.com/magento/magento2/pull/9165) -- Improved text of exception message in case of error in module's composer.json (by @vovayatsyuk)
+    * [#9131](https://github.com/magento/magento2/pull/9131) -- Fix to allow Zend_Db_Expr as column default (by @scottsb)
+    * [#9221](https://github.com/magento/magento2/pull/9221) -- Avoid: Undefined index: value in app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php on line 157 in Ajax return (by @mhauri)
+    * [#9215](https://github.com/magento/magento2/pull/9215) -- Remove unused and invalid method (by @adragus-inviqa)
+    * [#9210](https://github.com/magento/magento2/pull/9210) -- Do not di:compile tests/ folder (by @kassner)
+    * [#5325](https://github.com/magento/magento2/pull/5325) -- update url guide to v2.0 (by @sIiiS)
+    * [#6452](https://github.com/magento/magento2/pull/6452) -- Fix Login Popup broken on iPad portrait (by @ihor-sviziev)
+    * [#9234](https://github.com/magento/magento2/pull/9234) -- Fix indentation in pub/.htaccess file (by @erikhansen)
+    * [#6266](https://github.com/magento/magento2/pull/6266) -- Change commit to rollBack on fail (by @flancer64)
+    * [#6792](https://github.com/magento/magento2/pull/6792) -- Make a hardcoded value in Customizable Options interceptable (by @navarr)
+    * [#9094](https://github.com/magento/magento2/pull/9094) -- Issue #2802, #1146: Fixing sitemap generation folder (by @JosephMaxwell)
+    * [#9124](https://github.com/magento/magento2/pull/9124) -- Solve issues with API (by @paales)
+    * [#9247](https://github.com/magento/magento2/pull/9247) -- Fixed layout handle for cms page (by @simpleadm)
+    * [#9257](https://github.com/magento/magento2/pull/9257) -- Fixed coding standard violations in the Framework\Message namespace (by @dverkade)
+    * [#9254](https://github.com/magento/magento2/pull/9254) -- Fixed coding standard violations in the Framework\Encryption namespace (by @dverkade)
+    * [#9253](https://github.com/magento/magento2/pull/9253) -- Fixed coding standard violations in the Framework\Event namespace (by @dverkade)
+    * [#9250](https://github.com/magento/magento2/pull/9250) -- Fixed coding standard violations in the Framework\Archive namespace (by @dverkade)
+    * [#9264](https://github.com/magento/magento2/pull/9264) -- Enable/Disable DB query logging commands (by @federivo)
+    * [#9260](https://github.com/magento/magento2/pull/9260) -- Fixed coding standard violations in Framework\HTTP namespace: (by @dverkade)
+    * [#9258](https://github.com/magento/magento2/pull/9258) -- Fixed coding standard violations in the Framework\Filesystem namespace (by @dverkade)
+    * [#9286](https://github.com/magento/magento2/pull/9286) -- [WIP] Varnish Vcl generator command (by @piotrkwiecinski)
+    * [#9282](https://github.com/magento/magento2/pull/9282) -- Fixed coding standard violations in the Framework\Filter namespace (by @dverkade)
+    * [#9281](https://github.com/magento/magento2/pull/9281) -- Fixed coding standard violations in Framework\Image namespace (by @dverkade)
+    * [#9298](https://github.com/magento/magento2/pull/9298) -- Remove php-5.6 environment from travis.yml (by @4quaternion)
+    * [#4816](https://github.com/magento/magento2/pull/4816) -- Fixed issue with grouped product name column renderer. It (by @wbyrnetx)
+    * [#5147](https://github.com/magento/magento2/pull/5147) -- Change value-assignment to a setValue call (by @wexo-team)
+    * [#5411](https://github.com/magento/magento2/pull/5411) -- #5236 fixes "The configuration parameter "componentType" is a required for "advanced_pricing_button" component" (by @Protazy21)
+    * [#7148](https://github.com/magento/magento2/pull/7148) -- Fix issue 7075 (by @rmsundar1)
+    * [#9027](https://github.com/magento/magento2/pull/9027) -- Make CSS minifying compatible with calc() CSS function (by @sambolek)
+    * [#9262](https://github.com/magento/magento2/pull/9262) -- Remove zend json from theme (by @dmanners)
+    * [#9261](https://github.com/magento/magento2/pull/9261) -- Remove zend json from weee (by @dmanners)
+    * [#9302](https://github.com/magento/magento2/pull/9302) -- Fixed coding standard violations in the Framework\Module namespace  (by @dverkade)
+    * [#9299](https://github.com/magento/magento2/pull/9299) -- Improved check for attribute codes in "additional_attributes" field (by @ccasciotti)
+    * [#9293](https://github.com/magento/magento2/pull/9293) -- Deprecate unused navigation-menu.js file in blank theme (by @mikeoloughlin)
+    * [#9308](https://github.com/magento/magento2/pull/9308) -- Remove unnecessary FQCN in ObserverInterface (by @jameshalsall)
+    * [#9304](https://github.com/magento/magento2/pull/9304) -- Fixed coding standard violations in all Factory classes located in app/code (by @dverkade)
+    * [#9303](https://github.com/magento/magento2/pull/9303) -- Fixed coding standard violations in the Framework namespace  (by @dverkade)
+    * [#9318](https://github.com/magento/magento2/pull/9318) -- Fixed coding standard violations in the Framework\Backup namespace (by @dverkade)
+    * [#9321](https://github.com/magento/magento2/pull/9321) -- Fixed coding standard violations in the Framework\Autoload, Framework\Session & Framework\Webapi namespaces (by @dverkade)
+    * [#9320](https://github.com/magento/magento2/pull/9320) -- Fixed coding standard violations in the Framework\Cache namespace (by @dverkade)
+    * [#9319](https://github.com/magento/magento2/pull/9319) -- Fixed coding standard violations in the Framework\Api namespace (by @dverkade)
+    * [#9334](https://github.com/magento/magento2/pull/9334) -- Fixed coding standard violations in the Framework\Controller, Framework\CSS, Framework\Phrase and Framework\Pricing namespace (by @dverkade)
+    * [#9330](https://github.com/magento/magento2/pull/9330) -- Fixed coding standard violations in the Framework\Data namespace (by @dverkade)
+    * [#9329](https://github.com/magento/magento2/pull/9329) -- Fixed coding standard violations in the Framework\Stdlib namespace (by @dverkade)
+    * [#9328](https://github.com/magento/magento2/pull/9328) -- Fixed coding standard violations in the Framework\Config namespace  (by @dverkade)
+    * [#5372](https://github.com/magento/magento2/pull/5372) -- Fix filesystem permission issues (by @BlackIkeEagle)
+    * [#9129](https://github.com/magento/magento2/pull/9129) -- Product Wizard: Use result type Layout instead of page layout (by @klein0r)
+    * [#9352](https://github.com/magento/magento2/pull/9352) -- Fixed coding standard violations in the Framework\File namespace (by @dverkade)
+    * [#9351](https://github.com/magento/magento2/pull/9351) -- Fixed coding standard violations in the Framework\Locale namespace (by @dverkade)
+    * [#9350](https://github.com/magento/magento2/pull/9350) -- Fixed coding standard violations in the Framework\App namespace (by @dverkade)
+    * [#9355](https://github.com/magento/magento2/pull/9355) -- Fixed coding standard violations in the Framework\Test namespace (by @dverkade)
+    * [#9354](https://github.com/magento/magento2/pull/9354) -- Fixed coding standard violations in the Framework\Translate namespace (by @dverkade)
+    * [#9353](https://github.com/magento/magento2/pull/9353) -- Fixed coding standard violations in the Framework\DB namespace (by @dverkade)
+    * [#8955](https://github.com/magento/magento2/pull/8955) -- Remove context aggregation validation (see Issue #6114) (by @Vinai)
+    * [#9343](https://github.com/magento/magento2/pull/9343) -- Add logging to contact us form (by @JamesonNetworks)
+    * [#9414](https://github.com/magento/magento2/pull/9414) -- Use loadPlayer requirejs mapping (by @ntoombs19)
+    * [#9400](https://github.com/magento/magento2/pull/9400) -- Fix addIdFilter method (by @adrian-martinez-interactiv4)
+    * [#9363](https://github.com/magento/magento2/pull/9363) -- Add ability to inject exception code in LocalizedException (by @adragus-inviqa)
+    * [#9446](https://github.com/magento/magento2/pull/9446) -- Fix data deletion using the multiple delete command (by @Kenboy)
+    * [#9539](https://github.com/magento/magento2/pull/9539) -- fix for "Class Magento\Framework\Console\CLI not found" in case sensitive scenarios (by @EObukhovsky)
+    * [#9514](https://github.com/magento/magento2/pull/9514) -- Fix breadcrumbs extra space (by @VincentMarmiesse)
+    * [#8409](https://github.com/magento/magento2/pull/8409) -- Allow X-Forwarded-For to have multiple values (by @kassner)
+    * [#9093](https://github.com/magento/magento2/pull/9093) -- JS Static tests added to CI (ESLint + JSCS) (by @Igloczek)
+    * [#9091](https://github.com/magento/magento2/pull/9091) -- ESLint errors fix (by @Igloczek)
+    * [#9285](https://github.com/magento/magento2/pull/9285) -- Replace Zend_Log with Psr\Log\LoggerInterface (by @tdgroot)
+    * [#9380](https://github.com/magento/magento2/pull/9380) -- Removed unnecessary code and namespaces from import validators (by @ccasciotti)
+    * [#9540](https://github.com/magento/magento2/pull/9540) -- Removed workaround for old Webkit bug in the TinyMCE editor for selec… (by @hostep)
+    * [#9549](https://github.com/magento/magento2/pull/9549) -- Selects correct stores value option (by @Corefix)
+    * [#9574](https://github.com/magento/magento2/pull/9574) -- no need to create customer once u got the quote object (by @sivajik34)
+    * [#9618](https://github.com/magento/magento2/pull/9618) -- Flip the property assignments for _logger and _fetchStrategy in __wakeup (by @cykirsch)
+    * [#9617](https://github.com/magento/magento2/pull/9617) -- Exclude unnecessarily duplicated Travis CI build jobs (by @Igloczek)
+    * [#9622](https://github.com/magento/magento2/pull/9622) -- Zend_Wildfire deprecated, Firephp outdated, magento/magento2#9239 and magento/magento2#9241 (by @SolsWebdesign)
+    * [#9625](https://github.com/magento/magento2/pull/9625) -- Remove unused plugin (by @elzekool)
+    * [#9637](https://github.com/magento/magento2/pull/9637) -- Change "wan't" to "want" (by @Leland)
+    * [#7020](https://github.com/magento/magento2/pull/7020) -- Fixes #7006, sales_order_status_label does not support version control (by @ajpevers)
+    * [#7456](https://github.com/magento/magento2/pull/7456) -- Remove unused entity_id foreign key (by @mattjbarlow)
+    * [#7755](https://github.com/magento/magento2/pull/7755) -- Remove redundant check and return early (by @AydinHassan)
+    * [#9657](https://github.com/magento/magento2/pull/9657) -- Fixes Typo (by @riconeitzel)
+    * [#4903](https://github.com/magento/magento2/pull/4903) -- Fix undefined offset notice when no order states are set (by @adragus-inviqa)
+    * [#6344](https://github.com/magento/magento2/pull/6344) -- Zend instead of regex in getGetterReturnType (by @flancer64)
+    * [#9686](https://github.com/magento/magento2/pull/9686) -- Update scripts.js (by @redelschaap)
+    * [#9701](https://github.com/magento/magento2/pull/9701) -- Add missing payment info template for PDF generation (by @cmuench)
+    * [#9697](https://github.com/magento/magento2/pull/9697) -- Configure Travis CI to run functional tests (by @okolesnyk)
+    * [#9711](https://github.com/magento/magento2/pull/9711) -- Cookie Restriction Mode Overlay should not be cached by Varnish #6455 (by @bka)
+    * [#9713](https://github.com/magento/magento2/pull/9713) -- stringify cookie value to fix Google Analyitcs Tracking and Cookie Overlay #5596 (by @bka)
+    * [#6503](https://github.com/magento/magento2/pull/6503) -- Remove breadcrumbs for multistore homepage (by @PingusPepan)
+    * [#7330](https://github.com/magento/magento2/pull/7330) -- Fix Framework\Data\Collection::each() method (by @Vinai)
+    * [#8484](https://github.com/magento/magento2/pull/8484) -- Fix swatch-renderer.js product id and isProductViewExist (by @mimarcel)
+    * [#9348](https://github.com/magento/magento2/pull/9348) -- Replace framework's Zend_Session interface usage with SessionHandlerInterface (by @tdgroot)
+    * [#9654](https://github.com/magento/magento2/pull/9654) -- magento/magento2#7279 bill-to name and ship-to name truncated to 20 chars (by @SolsWebdesign)
+    * [#9627](https://github.com/magento/magento2/pull/9627) -- Fix coding standard in Magento AdminNotification module (by @dverkade)
+    * [#9714](https://github.com/magento/magento2/pull/9714) -- Can't delete last item in cart if Minimum Order is Enable #6151 (by @storbahn)
+    * [#9717](https://github.com/magento/magento2/pull/9717) -- use payment method name to make checkbox of agreements more unique #6207 (by @bka)
+    * [#9715](https://github.com/magento/magento2/pull/9715) -- #4272: v2.0.4 Credit memos with adjustment fees cannot be fully refunded with a second credit memo (by @mcspronko)
+    * [#9344](https://github.com/magento/magento2/pull/9344) -- Explace the direct usage of Zend_Json with a call to the Json Help class (by @dmanners)
+    * [#9475](https://github.com/magento/magento2/pull/9475) -- Update select.js (by @redelschaap)
+    * [#9600](https://github.com/magento/magento2/pull/9600) -- Do not hardcode product link types (by @kassner)
+    * [#9712](https://github.com/magento/magento2/pull/9712) -- Customer with unique attribute can't be saved #7844 (by @storbahn)
+    * [#9723](https://github.com/magento/magento2/pull/9723) -- Patch to allow multiple filter_url_params to function (by @southerncomputer)
+    * [#9721](https://github.com/magento/magento2/pull/9721) -- [BUGFIX][6244] Fix Issue with code label display in cart checkout. (by @diglin)
+    * [#9753](https://github.com/magento/magento2/pull/9753) -- Replace Zend_Json in the configurable product block test (by @dmanners)
+    * [#9777](https://github.com/magento/magento2/pull/9777) -- Fix for #5897: getIdentities relies on uninitialized collection (by @kassner)
+    * [#9772](https://github.com/magento/magento2/pull/9772) -- Allow for referenceBlock to include template argument (by @jissereitsma)
+    * [#9797](https://github.com/magento/magento2/pull/9797) -- Adding logo in media folder (by @rafaelstz)
+    * [#9409](https://github.com/magento/magento2/pull/9409) -- Add a name to the Composite\Fieldset\Options block directive (by @navarr)
+    * [#9665](https://github.com/magento/magento2/pull/9665) -- Fix for javascript "mixins" when 'urlArgs' is set in requirejs - issue 8221 (by @thelettuce)
+    * [#9835](https://github.com/magento/magento2/pull/9835) -- Fixes Mage.Cookies poor performance (by @wujashek)
+    * [#9430](https://github.com/magento/magento2/pull/9430) -- Fix wrong store id filter (by @mimarcel)
+    * [#9670](https://github.com/magento/magento2/pull/9670) -- Allow injection of Magento\Catalog\Model\View\Asset\ImageFactory (by @rolftimmermans)
+    * [#9778](https://github.com/magento/magento2/pull/9778) -- new CLI command: Enable Template Hints (by @miguelbalparda)
+    * [#9820](https://github.com/magento/magento2/pull/9820) -- [oauth] Fixes #9819 (by @EliasKotlyar)
+    * [#9859](https://github.com/magento/magento2/pull/9859) -- Removed unused $_customerSession property (by @edenreich)
+    * [#4450](https://github.com/magento/magento2/pull/4450) -- Add ability to use tree-massactions ("sub-menus") on Sales > Orders grid (by @ikk0)
+    * [#9368](https://github.com/magento/magento2/pull/9368) -- Redis sess: fix path for persistent_identifier & compression_threshold (by @LukeHandle)
+    * [#9690](https://github.com/magento/magento2/pull/9690) -- Add froogaloop library as a dependency to load-player module (by @ntoombs19)
+    * [#9813](https://github.com/magento/magento2/pull/9813) -- Use static:: to support late static bindings in Invoice and Creditmemo (by @jokeputs)
+    * [#9780](https://github.com/magento/magento2/pull/9780) -- Coupon codes not showing in invoice print out #9216 (by @naouibelgacem)
+    * [#9872](https://github.com/magento/magento2/pull/9872) -- Fixed issue causing static test failure to report success on Travis (by @davidalger)
+    * [#9890](https://github.com/magento/magento2/pull/9890) -- Improved error logging when trying to save a product (by @woutersamaey)
+    * [#9892](https://github.com/magento/magento2/pull/9892) -- Added .DS_Store to .gitignore for Mac users (by @woutersamaey)
+    * [#9873](https://github.com/magento/magento2/pull/9873) -- Fixes layered navigation options being cached using the wrong store id. (by @hostep)
+    * [#7405](https://github.com/magento/magento2/pull/7405) -- Update Curl.php (by @redelschaap)
+    * [#7780](https://github.com/magento/magento2/pull/7780) -- setup:di:compile returns exit code 0 if errors are found (by @pivulic)
+    * [#9157](https://github.com/magento/magento2/pull/9157) -- Return array of blocks as items instead of array of arrays (by @tkotosz)
+    * [#9810](https://github.com/magento/magento2/pull/9810) -- Fix bug linked product position not updated if product link already exists (by @jalogut)
+    * [#9824](https://github.com/magento/magento2/pull/9824) -- Email to a Friend feature (by @WaPoNe)
+    * [#9823](https://github.com/magento/magento2/pull/9823) -- Return array of pages as items instead of array of arrays (by @tkotosz)
+    * [#9922](https://github.com/magento/magento2/pull/9922) -- Fixes small backwards incompatibility issue created in MAGETWO-69728 (by @hostep)
+    * [#4891](https://github.com/magento/magento2/pull/4891) -- Remove faulty index subscription (by @ajpevers)
+    * [#7758](https://github.com/magento/magento2/pull/7758) -- Throw exception when attribute doesn't exitst (by @AydinHassan)
+    * [#8879](https://github.com/magento/magento2/pull/8879) -- add middle name to checkout address html templates #8878 (by @ajpevers)
+    * [#9251](https://github.com/magento/magento2/pull/9251) -- Fixed coding standard violations in the Framework\Validator namespace (by @dverkade)
+    * [#9525](https://github.com/magento/magento2/pull/9525) -- Fixed the Inconsistent Gift Options checkbox labels #9421 (by @vpiyappan)
+    * [#9905](https://github.com/magento/magento2/pull/9905) -- Fix composer validation (by @barbazul)
+    * [#9932](https://github.com/magento/magento2/pull/9932) -- Fix typo in comment (by @avoelkl)
+    * [#9306](https://github.com/magento/magento2/pull/9306) -- Fix PaymentTokenFactory interface to have the "Interface" at the end of the name. (by @dverkade)
+    * [#9391](https://github.com/magento/magento2/pull/9391) -- Fix depends per group in system.xml (by @osrecio)
+    * [#9902](https://github.com/magento/magento2/pull/9902) -- Fix static integrity classes tests in Windows (by @barbazul)
+    * [#9915](https://github.com/magento/magento2/pull/9915) -- suggestion from #9338: add some command/option to the deploy command to refresh the version (by @ajpevers)
+    * [#9925](https://github.com/magento/magento2/pull/9925) -- Fix #9924, prefill prefix and suffix in checkout shipping address (by @ajpevers)
+    * [#9941](https://github.com/magento/magento2/pull/9941) -- By default, show times in admin grids in the store timezone. (by @ajpevers)
+    * [#9943](https://github.com/magento/magento2/pull/9943) -- Cron uses the wrong timestamp method (by @ajpevers)
+    * [#9964](https://github.com/magento/magento2/pull/9964) -- Add target attribute to Magento_Ui grid (by @thelettuce)
+    * [#9973](https://github.com/magento/magento2/pull/9973) -- Fixed coding standard violations in the Magento\Wishlist namespace  (by @dverkade)
+    * [#9974](https://github.com/magento/magento2/pull/9974) -- Fixed coding standard violations in the Magento\Backend namespace  (by @dverkade)
+    * [#9975](https://github.com/magento/magento2/pull/9975) -- Fixed coding standard violations in the Magento\Cms namespace  (by @dverkade)
+    * [#9978](https://github.com/magento/magento2/pull/9978) -- Fixed coding standard violations in the Magento\Authorization Magento\Backup Magento\Captcha Magento\CurrencySymbol and Magento\Dhl namespace (by @dverkade)
+    * [#8965](https://github.com/magento/magento2/pull/8965) -- Reduce calls to SplFileInfo::realpath() in the Magento\Setup\Module\Di\Code\Reader\ClassesScanner class (by @kschroeder)
+    * [#9996](https://github.com/magento/magento2/pull/9996) -- Ubuntu Trusty 14.04 images update (by @miguelbalparda)
+    * [#8784](https://github.com/magento/magento2/pull/8784) -- magento/magento2: #8616 (by @cavalier79)
+    * [#9939](https://github.com/magento/magento2/pull/9939) -- Retrieve taxes from the correct object (by @fooman)
+    * [#9957](https://github.com/magento/magento2/pull/9957) -- Instantly apply configuration changes in the cron schedule (by @ajpevers)
+    * [#9994](https://github.com/magento/magento2/pull/9994) -- Fix mini-cart not emptied for logged out users checking out with PayPal Express (by @driskell)
+    * [#9082](https://github.com/magento/magento2/pull/9082) -- Get sitemap product images from image cache, if available (by @sambolek)
+    * [#9786](https://github.com/magento/magento2/pull/9786) -- [#7291] Change the default contact form email template to HTML (by @VincentMarmiesse)
+    * [#9361](https://github.com/magento/magento2/pull/9361) -- Fixed coding standard violations in the Framework\Model namespace (by @dverkade)
+    * [#9359](https://github.com/magento/magento2/pull/9359) -- Fixed coding standard violations in the Framework\Interception namespace (by @dverkade)
+    * [#9358](https://github.com/magento/magento2/pull/9358) -- Fixed coding standard violations in the Framework\Code namespace (by @dverkade)
+    * [#9429](https://github.com/magento/magento2/pull/9429) -- Fix not detecting current store using store code in url using $storeResolver->getCurrentStoreId() (by @mimarcel)
+    * [#9362](https://github.com/magento/magento2/pull/9362) -- Fixed coding standard violations in the Framework\ObjectManager namespace (by @dverkade)
+    * [#9970](https://github.com/magento/magento2/pull/9970) -- Added public methods to make Sitemap model plugin friendly (by @7ochem)
+    * [#7729](https://github.com/magento/magento2/pull/7729) -- Allow USPS Shipping Methods Without ExtraServices (by @jaywilliams)
+    * [#9314](https://github.com/magento/magento2/pull/9314) -- Support null value for custom attributes. (by @meng-tian)
+    * [#10033](https://github.com/magento/magento2/pull/10033) -- Fix for file category image uploader (by @Bartlomiejsz)
+    * [#10047](https://github.com/magento/magento2/pull/10047) -- Include attribute code in error message (by @lazyguru)
+    * [#10056](https://github.com/magento/magento2/pull/10056) -- Translate password field placeholder in Checkout (by @mimarcel)
+    * [#7139](https://github.com/magento/magento2/pull/7139) -- Stickyjs improvements (by @vovayatsyuk)
+    * [#9681](https://github.com/magento/magento2/pull/9681) -- Issue 9680: Use parent name for variations (by @PascalBrouwers)
+    * [#10031](https://github.com/magento/magento2/pull/10031) -- Allow option disabling for optgroup binding (by @Bart-art)
+    * [#10060](https://github.com/magento/magento2/pull/10060) -- Adding escapeHtml to Newsletter phtml (by @rafaelstz)
+    * [#10062](https://github.com/magento/magento2/pull/10062) -- Fix formatting for USPS Carrier (by @ihor-sviziev)
+    * [#9672](https://github.com/magento/magento2/pull/9672) -- Revert minimum stability to stable, tasks #4359 (by @ktomk)
+    * [#9986](https://github.com/magento/magento2/pull/9986) -- Improved type hints and declarations for \Magento\Quote\Model\Quote\Address\Total (by @schmengler)
+    * [#10082](https://github.com/magento/magento2/pull/10082) -- M2 2266 (by @tzyganu)
+    * [#10086](https://github.com/magento/magento2/pull/10086) -- Fix condition for autoloader function definitions (by @miromichalicka)
+    * [#9611](https://github.com/magento/magento2/pull/9611) -- Admin Grid Mass action Select / Unselect All issue #9610 (by @minesh0111)
+    * [#9726](https://github.com/magento/magento2/pull/9726) -- Remove wrong '_setup' replace when getting DB connection (2) (by @jalogut)
+    * [#9754](https://github.com/magento/magento2/pull/9754) -- Remove zend json from form elements (by @dmanners)
+    * [#9992](https://github.com/magento/magento2/pull/9992) -- Make page title in layout files translatable (by @ajpevers)
+    * [#10052](https://github.com/magento/magento2/pull/10052) -- M2 5381 (by @tzyganu)
+    * [#1563](https://github.com/magento/magento2/pull/1563) -- Convert long form tags with echo to use short-echo tags (by @davidalger)
+    * [#4147](https://github.com/magento/magento2/pull/4147) -- Add filename paramenter log (by @fcapua-summa)
+    * [#10043](https://github.com/magento/magento2/pull/10043) -- Fix trailing slash used in url rewrites (by @ihor-sviziev)
+    * [#10106](https://github.com/magento/magento2/pull/10106) -- Return URL in getThumbnailUrl instead of nothing (by @samgranger)
+    * [#3889](https://github.com/magento/magento2/pull/3889) -- Add missing dependencies of magento/framework (by @GordonLesti)
+    * [#10114](https://github.com/magento/magento2/pull/10114) -- Add missing dependencies of magento/framework (by @okorshenko)
+    * [#7174](https://github.com/magento/magento2/pull/7174) -- Type hint for \DateTimeInterface instead of \DateTime (by @jameshalsall)
+    * [#9189](https://github.com/magento/magento2/pull/9189) -- Avoid duplicate ltrim function on not complied mode. (by @sivajik34)
+    * [#10094](https://github.com/magento/magento2/pull/10094) -- Fix for isoneof condition in catalogrule (by @duckchip)
+    * [#10105](https://github.com/magento/magento2/pull/10105) -- Add referrerPolicy to Vimeo Video iframe to allow domain-restricted videos (by @davefarthing)
+    * [#10126](https://github.com/magento/magento2/pull/10126) -- Fix width & height mapping during image upload (by @ihor-sviziev)
+    * [#10140](https://github.com/magento/magento2/pull/10140) -- Update attribute vat_id frontend_label to make it translatable (by @JeroenVanLeusden)
+    * [#10149](https://github.com/magento/magento2/pull/10149) -- Fix wrong ACL for Developer Section (by @PascalBrouwers)
+    * [#10151](https://github.com/magento/magento2/pull/10151) -- Fix Widget saving non-XML entities to layout_update (by @tdgroot)
+    * [#9588](https://github.com/magento/magento2/pull/9588) -- Support controller src_type for head links (by @kassner)
+    * [#9904](https://github.com/magento/magento2/pull/9904) -- Fixed pointless exception in logs every time a category with image is saved (by @woutersamaey)
+    * [#10059](https://github.com/magento/magento2/pull/10059) -- Fix fetching quote item by id (by @mladenilic)
+
 2.1.0
 =============
 To get detailed information about changes in Magento 2.1.0, please visit [Magento Community Edition (CE) Release Notes](http://devdocs.magento.com/guides/v2.1/release-notes/ReleaseNotes2.1.0CE.html "Magento Community Edition (CE) Release Notes")
diff --git a/app/.htaccess b/app/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/app/.htaccess
+++ b/app/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/app/code/Magento/AdvancedPricingImportExport/composer.json b/app/code/Magento/AdvancedPricingImportExport/composer.json
index ec54cfd1e5e622b7aca158de63bf06322058d2d0..79e6e2d36873678a9ff20ea2dcc47e0328445186 100644
--- a/app/code/Magento/AdvancedPricingImportExport/composer.json
+++ b/app/code/Magento/AdvancedPricingImportExport/composer.json
@@ -13,7 +13,7 @@
         "magento/framework": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Analytics/composer.json b/app/code/Magento/Analytics/composer.json
index edc3443e487b6067499a45ba930f0d7382c24b32..b17bb10cb411263cbb6ac6e6295878ec22c1780d 100644
--- a/app/code/Magento/Analytics/composer.json
+++ b/app/code/Magento/Analytics/composer.json
@@ -10,7 +10,7 @@
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json
index 036f0b4d54a465fcc0efb6bf543385e6d2e51ba6..3d8cfa49cd1fa01776cb4b12f0c66e00b489acf1 100644
--- a/app/code/Magento/Backend/composer.json
+++ b/app/code/Magento/Backend/composer.json
@@ -24,7 +24,7 @@
         "magento/module-theme": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Braintree/Block/Form.php b/app/code/Magento/Braintree/Block/Form.php
index f6cf62f5a21317170f9558b33ba37d2bb93abcb3..8a727ae87262fab411b093c1be2cbed77feb3302 100644
--- a/app/code/Magento/Braintree/Block/Form.php
+++ b/app/code/Magento/Braintree/Block/Form.php
@@ -9,7 +9,6 @@ use Magento\Backend\Model\Session\Quote;
 use Magento\Braintree\Gateway\Config\Config as GatewayConfig;
 use Magento\Braintree\Model\Adminhtml\Source\CcType;
 use Magento\Braintree\Model\Ui\ConfigProvider;
-use Magento\Framework\App\ObjectManager;
 use Magento\Framework\View\Element\Template\Context;
 use Magento\Payment\Block\Form\Cc;
 use Magento\Payment\Helper\Data;
@@ -21,7 +20,6 @@ use Magento\Vault\Model\VaultPaymentInterface;
  */
 class Form extends Cc
 {
-
     /**
      * @var Quote
      */
@@ -48,6 +46,7 @@ class Form extends Cc
      * @param Quote $sessionQuote
      * @param GatewayConfig $gatewayConfig
      * @param CcType $ccType
+     * @param Data $paymentDataHelper
      * @param array $data
      */
     public function __construct(
@@ -56,12 +55,14 @@ class Form extends Cc
         Quote $sessionQuote,
         GatewayConfig $gatewayConfig,
         CcType $ccType,
+        Data $paymentDataHelper,
         array $data = []
     ) {
         parent::__construct($context, $paymentConfig, $data);
         $this->sessionQuote = $sessionQuote;
         $this->gatewayConfig = $gatewayConfig;
         $this->ccType = $ccType;
+        $this->paymentDataHelper = $paymentDataHelper;
     }
 
     /**
@@ -81,7 +82,7 @@ class Form extends Cc
      */
     public function useCvv()
     {
-        return $this->gatewayConfig->isCvvEnabled();
+        return $this->gatewayConfig->isCvvEnabled($this->sessionQuote->getStoreId());
     }
 
     /**
@@ -90,9 +91,8 @@ class Form extends Cc
      */
     public function isVaultEnabled()
     {
-        $storeId = $this->_storeManager->getStore()->getId();
         $vaultPayment = $this->getVaultPayment();
-        return $vaultPayment->isActive($storeId);
+        return $vaultPayment->isActive($this->sessionQuote->getStoreId());
     }
 
     /**
@@ -102,7 +102,10 @@ class Form extends Cc
     private function getConfiguredCardTypes()
     {
         $types = $this->ccType->getCcTypeLabelMap();
-        $configCardTypes = array_fill_keys($this->gatewayConfig->getAvailableCardTypes(), '');
+        $configCardTypes = array_fill_keys(
+            $this->gatewayConfig->getAvailableCardTypes($this->sessionQuote->getStoreId()),
+            ''
+        );
 
         return array_intersect_key($types, $configCardTypes);
     }
@@ -116,7 +119,11 @@ class Form extends Cc
     private function filterCardTypesForCountry(array $configCardTypes, $countryId)
     {
         $filtered = $configCardTypes;
-        $countryCardTypes = $this->gatewayConfig->getCountryAvailableCardTypes($countryId);
+        $countryCardTypes = $this->gatewayConfig->getCountryAvailableCardTypes(
+            $countryId,
+            $this->sessionQuote->getStoreId()
+        );
+
         // filter card types only if specific card types are set for country
         if (!empty($countryCardTypes)) {
             $availableTypes = array_fill_keys($countryCardTypes, '');
@@ -131,19 +138,6 @@ class Form extends Cc
      */
     private function getVaultPayment()
     {
-        return $this->getPaymentDataHelper()->getMethodInstance(ConfigProvider::CC_VAULT_CODE);
-    }
-
-    /**
-     * Get payment data helper instance
-     * @return Data
-     * @deprecated 100.1.0
-     */
-    private function getPaymentDataHelper()
-    {
-        if ($this->paymentDataHelper === null) {
-            $this->paymentDataHelper = ObjectManager::getInstance()->get(Data::class);
-        }
-        return $this->paymentDataHelper;
+        return $this->paymentDataHelper->getMethodInstance(ConfigProvider::CC_VAULT_CODE);
     }
 }
diff --git a/app/code/Magento/Braintree/Block/Payment.php b/app/code/Magento/Braintree/Block/Payment.php
index 8e05856d9b57a540ad1a4b39300490af03fe89c9..1ba2f862e2fe567662f12f7fd43b2c4492c69a2a 100644
--- a/app/code/Magento/Braintree/Block/Payment.php
+++ b/app/code/Magento/Braintree/Block/Payment.php
@@ -48,6 +48,10 @@ class Payment extends Template
         $payment = $this->config->getConfig()['payment'];
         $config = $payment[$this->getCode()];
         $config['code'] = $this->getCode();
+        $config['clientTokenUrl'] = $this->_urlBuilder->getUrl(
+            'braintree/payment/getClientToken',
+            ['_secure' => true]
+        );
         return json_encode($config, JSON_UNESCAPED_SLASHES);
     }
 
diff --git a/app/code/Magento/Braintree/Controller/Adminhtml/Payment/GetClientToken.php b/app/code/Magento/Braintree/Controller/Adminhtml/Payment/GetClientToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..af0f1d75665d51f1d01ea38bb85fff38b95c3fb3
--- /dev/null
+++ b/app/code/Magento/Braintree/Controller/Adminhtml/Payment/GetClientToken.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Controller\Adminhtml\Payment;
+
+use Magento\Backend\App\Action;
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\Session\Quote;
+use Magento\Braintree\Gateway\Config\Config;
+use Magento\Braintree\Gateway\Request\PaymentDataBuilder;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
+use Magento\Framework\Controller\ResultFactory;
+
+class GetClientToken extends Action
+{
+    const ADMIN_RESOURCE = 'Magento_Braintree::get_client_token';
+
+    /**
+     * @var Config
+     */
+    private $config;
+
+    /**
+     * @var BraintreeAdapterFactory
+     */
+    private $adapterFactory;
+
+    /**
+     * @var Quote
+     */
+    private $quoteSession;
+
+    /**
+     * @param Context $context
+     * @param Config $config
+     * @param BraintreeAdapterFactory $adapterFactory
+     * @param Quote $quoteSession
+     */
+    public function __construct(
+        Context $context,
+        Config $config,
+        BraintreeAdapterFactory $adapterFactory,
+        Quote $quoteSession
+    ) {
+        parent::__construct($context);
+        $this->config = $config;
+        $this->adapterFactory = $adapterFactory;
+        $this->quoteSession = $quoteSession;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function execute()
+    {
+        $params = [];
+        $response = $this->resultFactory->create(ResultFactory::TYPE_JSON);
+
+        $storeId = $this->quoteSession->getStoreId();
+        $merchantAccountId = $this->config->getMerchantAccountId($storeId);
+        if (!empty($merchantAccountId)) {
+            $params[PaymentDataBuilder::MERCHANT_ACCOUNT_ID] = $merchantAccountId;
+        }
+
+        $clientToken = $this->adapterFactory->create($storeId)
+            ->generate($params);
+        $response->setData(['clientToken' => $clientToken]);
+
+        return $response;
+    }
+}
diff --git a/app/code/Magento/Braintree/Controller/Payment/GetNonce.php b/app/code/Magento/Braintree/Controller/Payment/GetNonce.php
index aecde869ca196f48d112ac55608f3cb77a93ad87..f8b152ded1556a8648949a9f7bf26fed3f689751 100644
--- a/app/code/Magento/Braintree/Controller/Payment/GetNonce.php
+++ b/app/code/Magento/Braintree/Controller/Payment/GetNonce.php
@@ -62,7 +62,10 @@ class GetNonce extends Action
         try {
             $publicHash = $this->getRequest()->getParam('public_hash');
             $customerId = $this->session->getCustomerId();
-            $result = $this->command->execute(['public_hash' => $publicHash, 'customer_id' => $customerId])->get();
+            $result = $this->command->execute(
+                ['public_hash' => $publicHash, 'customer_id' => $customerId, 'store_id' => $this->session->getStoreId()]
+            )
+                ->get();
             $response->setData(['paymentMethodNonce' => $result['paymentMethodNonce']]);
         } catch (\Exception $e) {
             $this->logger->critical($e);
diff --git a/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php b/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php
index f972eecf9f92d9ae62f27da769e8ff5689e4dba4..c8359f69bc47daf7fd900223680a552ddf9ac1a2 100644
--- a/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php
+++ b/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php
@@ -6,18 +6,19 @@
 namespace Magento\Braintree\Gateway\Command;
 
 use Braintree\Transaction;
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Gateway\SubjectReader;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Braintree\Model\Adapter\BraintreeSearchAdapter;
 use Magento\Framework\Api\FilterBuilder;
 use Magento\Framework\Api\SearchCriteriaBuilder;
-use Magento\Payment\Gateway\Command;
 use Magento\Payment\Gateway\Command\CommandPoolInterface;
 use Magento\Payment\Gateway\CommandInterface;
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
-use Magento\Sales\Api\TransactionRepositoryInterface;
 use Magento\Sales\Api\Data\TransactionInterface;
+use Magento\Sales\Api\TransactionRepositoryInterface;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 
 /**
  * Class CaptureStrategyCommand
@@ -66,9 +67,9 @@ class CaptureStrategyCommand implements CommandInterface
     private $subjectReader;
 
     /**
-     * @var BraintreeAdapter
+     * @var BraintreeAdapterFactory
      */
-    private $braintreeAdapter;
+    private $braintreeAdapterFactory;
 
     /**
      * @var BraintreeSearchAdapter
@@ -83,7 +84,7 @@ class CaptureStrategyCommand implements CommandInterface
      * @param FilterBuilder $filterBuilder
      * @param SearchCriteriaBuilder $searchCriteriaBuilder
      * @param SubjectReader $subjectReader
-     * @param BraintreeAdapter $braintreeAdapter
+     * @param BraintreeAdapterFactory $braintreeAdapterFactory,
      * @param BraintreeSearchAdapter $braintreeSearchAdapter
      */
     public function __construct(
@@ -92,7 +93,7 @@ class CaptureStrategyCommand implements CommandInterface
         FilterBuilder $filterBuilder,
         SearchCriteriaBuilder $searchCriteriaBuilder,
         SubjectReader $subjectReader,
-        BraintreeAdapter $braintreeAdapter,
+        BraintreeAdapterFactory $braintreeAdapterFactory,
         BraintreeSearchAdapter $braintreeSearchAdapter
     ) {
         $this->commandPool = $commandPool;
@@ -100,7 +101,7 @@ class CaptureStrategyCommand implements CommandInterface
         $this->filterBuilder = $filterBuilder;
         $this->searchCriteriaBuilder = $searchCriteriaBuilder;
         $this->subjectReader = $subjectReader;
-        $this->braintreeAdapter = $braintreeAdapter;
+        $this->braintreeAdapterFactory = $braintreeAdapterFactory;
         $this->braintreeSearchAdapter = $braintreeSearchAdapter;
     }
 
@@ -112,29 +113,29 @@ class CaptureStrategyCommand implements CommandInterface
         /** @var \Magento\Payment\Gateway\Data\PaymentDataObjectInterface $paymentDO */
         $paymentDO = $this->subjectReader->readPayment($commandSubject);
 
-        /** @var \Magento\Sales\Api\Data\OrderPaymentInterface $paymentInfo */
-        $paymentInfo = $paymentDO->getPayment();
-        ContextHelper::assertOrderPayment($paymentInfo);
-
-        $command = $this->getCommand($paymentInfo);
+        $command = $this->getCommand($paymentDO);
         $this->commandPool->get($command)->execute($commandSubject);
     }
 
     /**
-     * Get execution command name
-     * @param OrderPaymentInterface $payment
+     * Gets command name.
+     *
+     * @param PaymentDataObjectInterface $paymentDO
      * @return string
      */
-    private function getCommand(OrderPaymentInterface $payment)
+    private function getCommand(PaymentDataObjectInterface $paymentDO)
     {
-        // if auth transaction is not exists execute authorize&capture command
+        $payment = $paymentDO->getPayment();
+        ContextHelper::assertOrderPayment($payment);
+
+        // if auth transaction does not exist then execute authorize&capture command
         $existsCapture = $this->isExistsCaptureTransaction($payment);
         if (!$payment->getAuthorizationTransaction() && !$existsCapture) {
             return self::SALE;
         }
 
         // do capture for authorization transaction
-        if (!$existsCapture && !$this->isExpiredAuthorization($payment)) {
+        if (!$existsCapture && !$this->isExpiredAuthorization($payment, $paymentDO->getOrder())) {
             return self::CAPTURE;
         }
 
@@ -143,12 +144,16 @@ class CaptureStrategyCommand implements CommandInterface
     }
 
     /**
+     * Checks if authorization transaction does not expired yet.
+     *
      * @param OrderPaymentInterface $payment
-     * @return boolean
+     * @param OrderAdapterInterface $orderAdapter
+     * @return bool
      */
-    private function isExpiredAuthorization(OrderPaymentInterface $payment)
+    private function isExpiredAuthorization(OrderPaymentInterface $payment, OrderAdapterInterface $orderAdapter)
     {
-        $collection = $this->braintreeAdapter->search(
+        $adapter = $this->braintreeAdapterFactory->create($orderAdapter->getStoreId());
+        $collection = $adapter->search(
             [
                 $this->braintreeSearchAdapter->id()->is($payment->getLastTransId()),
                 $this->braintreeSearchAdapter->status()->is(Transaction::AUTHORIZATION_EXPIRED)
diff --git a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php
index 91c9f6c14bb5dd953ba0e36696a7bbc17a8f453b..64e38d2999676c5a96aee1887315271396d6922f 100644
--- a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php
+++ b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php
@@ -7,10 +7,9 @@
 namespace Magento\Braintree\Gateway\Command;
 
 use Exception;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Validator\PaymentNonceResponseValidator;
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
-use Magento\Payment\Gateway\Command;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Payment\Gateway\Command\Result\ArrayResultFactory;
 use Magento\Payment\Gateway\CommandInterface;
 use Magento\Vault\Api\PaymentTokenManagementInterface;
@@ -27,9 +26,9 @@ class GetPaymentNonceCommand implements CommandInterface
     private $tokenManagement;
 
     /**
-     * @var BraintreeAdapter
+     * @var BraintreeAdapterFactory
      */
-    private $adapter;
+    private $adapterFactory;
 
     /**
      * @var ArrayResultFactory
@@ -48,20 +47,20 @@ class GetPaymentNonceCommand implements CommandInterface
 
     /**
      * @param PaymentTokenManagementInterface $tokenManagement
-     * @param BraintreeAdapter $adapter
+     * @param BraintreeAdapterFactory $adapterFactory
      * @param ArrayResultFactory $resultFactory
      * @param SubjectReader $subjectReader
      * @param PaymentNonceResponseValidator $responseValidator
      */
     public function __construct(
         PaymentTokenManagementInterface $tokenManagement,
-        BraintreeAdapter $adapter,
+        BraintreeAdapterFactory $adapterFactory,
         ArrayResultFactory $resultFactory,
         SubjectReader $subjectReader,
         PaymentNonceResponseValidator $responseValidator
     ) {
         $this->tokenManagement = $tokenManagement;
-        $this->adapter = $adapter;
+        $this->adapterFactory = $adapterFactory;
         $this->resultFactory = $resultFactory;
         $this->subjectReader = $subjectReader;
         $this->responseValidator = $responseValidator;
@@ -80,7 +79,9 @@ class GetPaymentNonceCommand implements CommandInterface
             throw new Exception('No available payment tokens');
         }
 
-        $data = $this->adapter->createNonce($paymentToken->getGatewayToken());
+        $storeId = $this->subjectReader->readStoreId($commandSubject);
+        $data = $this->adapterFactory->create($storeId)
+            ->createNonce($paymentToken->getGatewayToken());
         $result = $this->responseValidator->validate(['response' => ['object' => $data]]);
 
         if (!$result->isValid()) {
diff --git a/app/code/Magento/Braintree/Gateway/Config/CanVoidHandler.php b/app/code/Magento/Braintree/Gateway/Config/CanVoidHandler.php
index 9dd52dc91afb937263cfe90aed6c0995fe78078a..0466216bdb7d2e525db5570adf375247b974cdf2 100644
--- a/app/code/Magento/Braintree/Gateway/Config/CanVoidHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Config/CanVoidHandler.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Config;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Config\ValueHandlerInterface;
 use Magento\Sales\Model\Order\Payment;
 
diff --git a/app/code/Magento/Braintree/Gateway/Config/Config.php b/app/code/Magento/Braintree/Gateway/Config/Config.php
index 7badd2b87ac3461d75881d331cefe3d24aa78380..01bb32fbb1a7e5dbbe4b5a6bca65c22e73478ab4 100644
--- a/app/code/Magento/Braintree/Gateway/Config/Config.php
+++ b/app/code/Magento/Braintree/Gateway/Config/Config.php
@@ -68,11 +68,12 @@ class Config extends \Magento\Payment\Gateway\Config\Config
     /**
      * Return the country specific card type config
      *
+     * @param int|null $storeId
      * @return array
      */
-    public function getCountrySpecificCardTypeConfig()
+    public function getCountrySpecificCardTypeConfig($storeId = null)
     {
-        $countryCardTypes = $this->getValue(self::KEY_COUNTRY_CREDIT_CARD);
+        $countryCardTypes = $this->getValue(self::KEY_COUNTRY_CREDIT_CARD, $storeId);
         if (!$countryCardTypes) {
             return [];
         }
@@ -83,11 +84,12 @@ class Config extends \Magento\Payment\Gateway\Config\Config
     /**
      * Retrieve available credit card types
      *
+     * @param int|null $storeId
      * @return array
      */
-    public function getAvailableCardTypes()
+    public function getAvailableCardTypes($storeId = null)
     {
-        $ccTypes = $this->getValue(self::KEY_CC_TYPES);
+        $ccTypes = $this->getValue(self::KEY_CC_TYPES, $storeId);
 
         return !empty($ccTypes) ? explode(',', $ccTypes) : [];
     }
@@ -108,79 +110,111 @@ class Config extends \Magento\Payment\Gateway\Config\Config
     }
 
     /**
-     * Get list of card types available for country
+     * Gets list of card types available for country.
+     *
      * @param string $country
+     * @param int|null $storeId
      * @return array
      */
-    public function getCountryAvailableCardTypes($country)
+    public function getCountryAvailableCardTypes($country, $storeId = null)
     {
-        $types = $this->getCountrySpecificCardTypeConfig();
+        $types = $this->getCountrySpecificCardTypeConfig($storeId);
 
         return (!empty($types[$country])) ? $types[$country] : [];
     }
 
     /**
-     * Check if cvv field is enabled
-     * @return boolean
+     * Checks if cvv field is enabled.
+     *
+     * @param int|null $storeId
+     * @return bool
      */
-    public function isCvvEnabled()
+    public function isCvvEnabled($storeId = null)
     {
-        return (bool) $this->getValue(self::KEY_USE_CVV);
+        return (bool) $this->getValue(self::KEY_USE_CVV, $storeId);
     }
 
     /**
-     * Check if 3d secure verification enabled
+     * Checks if 3d secure verification enabled.
+     *
+     * @param int|null $storeId
      * @return bool
      */
-    public function isVerify3DSecure()
+    public function isVerify3DSecure($storeId = null)
     {
-        return (bool) $this->getValue(self::KEY_VERIFY_3DSECURE);
+        return (bool) $this->getValue(self::KEY_VERIFY_3DSECURE, $storeId);
     }
 
     /**
-     * Get threshold amount for 3d secure
+     * Gets threshold amount for 3d secure.
+     *
+     * @param int|null $storeId
      * @return float
      */
-    public function getThresholdAmount()
+    public function getThresholdAmount($storeId = null)
     {
-        return (double) $this->getValue(self::KEY_THRESHOLD_AMOUNT);
+        return (double) $this->getValue(self::KEY_THRESHOLD_AMOUNT, $storeId);
     }
 
     /**
-     * Get list of specific countries for 3d secure
+     * Gets list of specific countries for 3d secure.
+     *
+     * @param int|null $storeId
      * @return array
      */
-    public function get3DSecureSpecificCountries()
+    public function get3DSecureSpecificCountries($storeId = null)
     {
-        if ((int) $this->getValue(self::KEY_VERIFY_ALLOW_SPECIFIC) == self::VALUE_3DSECURE_ALL) {
+        if ((int) $this->getValue(self::KEY_VERIFY_ALLOW_SPECIFIC, $storeId) == self::VALUE_3DSECURE_ALL) {
             return [];
         }
 
-        return explode(',', $this->getValue(self::KEY_VERIFY_SPECIFIC));
+        return explode(',', $this->getValue(self::KEY_VERIFY_SPECIFIC, $storeId));
+    }
+
+    /**
+     * Gets value of configured environment.
+     * Possible values: production or sandbox.
+     *
+     * @param int|null $storeId
+     * @return string
+     */
+    public function getEnvironment($storeId = null)
+    {
+        return $this->getValue(Config::KEY_ENVIRONMENT, $storeId);
     }
 
     /**
+     * Gets Kount merchant ID.
+     *
+     * @param int|null $storeId
      * @return string
+     * @internal param null $storeId
      */
-    public function getEnvironment()
+    public function getKountMerchantId($storeId = null)
     {
-        return $this->getValue(Config::KEY_ENVIRONMENT);
+        return $this->getValue(Config::KEY_KOUNT_MERCHANT_ID, $storeId);
     }
 
     /**
+     * Gets merchant ID.
+     *
+     * @param int|null $storeId
      * @return string
      */
-    public function getKountMerchantId()
+    public function getMerchantId($storeId = null)
     {
-        return $this->getValue(Config::KEY_KOUNT_MERCHANT_ID);
+        return $this->getValue(Config::KEY_MERCHANT_ID, $storeId);
     }
 
     /**
+     * Gets Merchant account ID.
+     *
+     * @param int|null $storeId
      * @return string
      */
-    public function getMerchantId()
+    public function getMerchantAccountId($storeId = null)
     {
-        return $this->getValue(Config::KEY_MERCHANT_ID);
+        return $this->getValue(self::KEY_MERCHANT_ACCOUNT_ID, $storeId);
     }
 
     /**
@@ -192,45 +226,42 @@ class Config extends \Magento\Payment\Gateway\Config\Config
     }
 
     /**
+     * Checks if fraud protection is enabled.
+     *
+     * @param int|null $storeId
      * @return bool
      */
-    public function hasFraudProtection()
+    public function hasFraudProtection($storeId = null)
     {
-        return (bool) $this->getValue(Config::FRAUD_PROTECTION);
+        return (bool) $this->getValue(Config::FRAUD_PROTECTION, $storeId);
     }
 
     /**
-     * Get Payment configuration status
+     * Gets Payment configuration status.
+     *
+     * @param int|null $storeId
      * @return bool
      */
-    public function isActive()
+    public function isActive($storeId = null)
     {
-        return (bool) $this->getValue(self::KEY_ACTIVE);
+        return (bool) $this->getValue(self::KEY_ACTIVE, $storeId);
     }
 
     /**
-     * Get list of configured dynamic descriptors
+     * Gets list of configured dynamic descriptors.
+     *
+     * @param int|null $storeId
      * @return array
      */
-    public function getDynamicDescriptors()
+    public function getDynamicDescriptors($storeId = null)
     {
         $values = [];
         foreach (self::$dynamicDescriptorKeys as $key) {
-            $value = $this->getValue('descriptor_' . $key);
+            $value = $this->getValue('descriptor_' . $key, $storeId);
             if (!empty($value)) {
                 $values[$key] = $value;
             }
         }
         return $values;
     }
-
-    /**
-     * Get Merchant account ID
-     *
-     * @return string
-     */
-    public function getMerchantAccountId()
-    {
-        return $this->getValue(self::KEY_MERCHANT_ACCOUNT_ID);
-    }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Http/Client/AbstractTransaction.php b/app/code/Magento/Braintree/Gateway/Http/Client/AbstractTransaction.php
index caeaaa7fe45a2c087a7a30aa4f0f83451f8a210b..ef35152bf7e95280819a28c0bec860925f88078a 100644
--- a/app/code/Magento/Braintree/Gateway/Http/Client/AbstractTransaction.php
+++ b/app/code/Magento/Braintree/Gateway/Http/Client/AbstractTransaction.php
@@ -6,7 +6,7 @@
 
 namespace Magento\Braintree\Gateway\Http\Client;
 
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Payment\Gateway\Http\ClientException;
 use Magento\Payment\Gateway\Http\ClientInterface;
 use Magento\Payment\Gateway\Http\TransferInterface;
@@ -29,22 +29,22 @@ abstract class AbstractTransaction implements ClientInterface
     protected $customLogger;
 
     /**
-     * @var BraintreeAdapter
+     * @var BraintreeAdapterFactory
      */
-    protected $adapter;
+    protected $adapterFactory;
 
     /**
      * Constructor
      *
      * @param LoggerInterface $logger
      * @param Logger $customLogger
-     * @param BraintreeAdapter $transaction
+     * @param BraintreeAdapterFactory $adapterFactory
      */
-    public function __construct(LoggerInterface $logger, Logger $customLogger, BraintreeAdapter $adapter)
+    public function __construct(LoggerInterface $logger, Logger $customLogger, BraintreeAdapterFactory $adapterFactory)
     {
         $this->logger = $logger;
         $this->customLogger = $customLogger;
-        $this->adapter = $adapter;
+        $this->adapterFactory = $adapterFactory;
     }
 
     /**
diff --git a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionRefund.php b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionRefund.php
index 180344ab7263ffcf06174366fef738cec0af97af..4c3f1e179d37803d94c7d5eff3cf86b11db12f73 100644
--- a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionRefund.php
+++ b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionRefund.php
@@ -16,9 +16,11 @@ class TransactionRefund extends AbstractTransaction
      */
     protected function process(array $data)
     {
-        return $this->adapter->refund(
-            $data['transaction_id'],
-            $data[PaymentDataBuilder::AMOUNT]
-        );
+        $storeId = $data['store_id'] ?? null;
+        // sending store id and other additional keys are restricted by Braintree API
+        unset($data['store_id']);
+
+        return $this->adapterFactory->create($storeId)
+            ->refund($data['transaction_id'], $data[PaymentDataBuilder::AMOUNT]);
     }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSale.php b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSale.php
index 81c79e522907dd88c0a30877684933c3a1af6749..529045b5b18f5c1cf11bbd73574b4bbe12aa9e39 100644
--- a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSale.php
+++ b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSale.php
@@ -15,6 +15,11 @@ class TransactionSale extends AbstractTransaction
      */
     protected function process(array $data)
     {
-        return $this->adapter->sale($data);
+        $storeId = $data['store_id'] ?? null;
+        // sending store id and other additional keys are restricted by Braintree API
+        unset($data['store_id']);
+
+        return $this->adapterFactory->create($storeId)
+            ->sale($data);
     }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSubmitForSettlement.php b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSubmitForSettlement.php
index 0df5799b54b831faedb51a1e9d6404c27faf0124..16ebd7a7a00c5b2f353458b5a31f954b9996f30d 100644
--- a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSubmitForSettlement.php
+++ b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionSubmitForSettlement.php
@@ -18,9 +18,11 @@ class TransactionSubmitForSettlement extends AbstractTransaction
      */
     protected function process(array $data)
     {
-        return  $this->adapter->submitForSettlement(
-            $data[CaptureDataBuilder::TRANSACTION_ID],
-            $data[PaymentDataBuilder::AMOUNT]
-        );
+        $storeId = $data['store_id'] ?? null;
+        // sending store id and other additional keys are restricted by Braintree API
+        unset($data['store_id']);
+
+        return  $this->adapterFactory->create($storeId)
+            ->submitForSettlement($data[CaptureDataBuilder::TRANSACTION_ID], $data[PaymentDataBuilder::AMOUNT]);
     }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionVoid.php b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionVoid.php
index a774065365b47ba2692e9c4b89f1fd88391bfa07..133c7f0f4062ed6485746c829058bf9fd5583927 100644
--- a/app/code/Magento/Braintree/Gateway/Http/Client/TransactionVoid.php
+++ b/app/code/Magento/Braintree/Gateway/Http/Client/TransactionVoid.php
@@ -14,6 +14,11 @@ class TransactionVoid extends AbstractTransaction
      */
     protected function process(array $data)
     {
-        return $this->adapter->void($data['transaction_id']);
+        $storeId = $data['store_id'] ?? null;
+        // sending store id and other additional keys are restricted by Braintree API
+        unset($data['store_id']);
+
+        return $this->adapterFactory->create($storeId)
+            ->void($data['transaction_id']);
     }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Request/AddressDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/AddressDataBuilder.php
index 9ff65149894f81b96d145a8a4ef2d786ce0ab1ca..f7d3aae823e566511da45da7b6b8706f19faaa0d 100644
--- a/app/code/Magento/Braintree/Gateway/Request/AddressDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/AddressDataBuilder.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Payment\Gateway\Request\BuilderInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 /**
  * Class AddressDataBuilder
diff --git a/app/code/Magento/Braintree/Gateway/Request/CaptureDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/CaptureDataBuilder.php
index c6588cfaca05fbb325ff65bf59b29d2b82aa5ed0..6f3a262d7efb41463d272ee15e248c39c99958f5 100644
--- a/app/code/Magento/Braintree/Gateway/Request/CaptureDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/CaptureDataBuilder.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Framework\Exception\LocalizedException;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Payment\Helper\Formatter;
 
diff --git a/app/code/Magento/Braintree/Gateway/Request/CustomerDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/CustomerDataBuilder.php
index 6b03f418c2545e67f1e120e448fc0e0c70d2b02a..6b3403bcd15c1b925b7ea15f78ce643c4218286f 100644
--- a/app/code/Magento/Braintree/Gateway/Request/CustomerDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/CustomerDataBuilder.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Payment\Gateway\Request\BuilderInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 /**
  * Class CustomerDataBuilder
diff --git a/app/code/Magento/Braintree/Gateway/Request/DescriptorDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/DescriptorDataBuilder.php
index 3794058c2be8cdd035d0e55b758f2ed3132cc14f..aac603bfb621a138e7bf574d6d3fb410aab62687 100644
--- a/app/code/Magento/Braintree/Gateway/Request/DescriptorDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/DescriptorDataBuilder.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request;
 
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Braintree\Gateway\Config\Config;
 
@@ -24,21 +25,29 @@ class DescriptorDataBuilder implements BuilderInterface
     private $config;
 
     /**
-     * DescriptorDataBuilder constructor.
+     * @var SubjectReader
+     */
+    private $subjectReader;
+
+    /**
      * @param Config $config
+     * @param SubjectReader $subjectReader
      */
-    public function __construct(Config $config)
+    public function __construct(Config $config, SubjectReader $subjectReader)
     {
         $this->config = $config;
+        $this->subjectReader = $subjectReader;
     }
 
     /**
      * @inheritdoc
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function build(array $buildSubject)
     {
-        $values = $this->config->getDynamicDescriptors();
+        $paymentDO = $this->subjectReader->readPayment($buildSubject);
+        $order = $paymentDO->getOrder();
+
+        $values = $this->config->getDynamicDescriptors($order->getStoreId());
         return !empty($values) ? [self::$descriptorKey => $values] : [];
     }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php
index 7eebbca1d42901c660e439cde43c5973655b6e63..8538667778504da29601f8ebb7fab87565bcb0a6 100644
--- a/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Observer\DataAssignObserver;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 
@@ -48,10 +48,12 @@ class KountPaymentDataBuilder implements BuilderInterface
     public function build(array $buildSubject)
     {
         $result = [];
-        if (!$this->config->hasFraudProtection()) {
+        $paymentDO = $this->subjectReader->readPayment($buildSubject);
+        $order = $paymentDO->getOrder();
+
+        if (!$this->config->hasFraudProtection($order->getStoreId())) {
             return $result;
         }
-        $paymentDO = $this->subjectReader->readPayment($buildSubject);
 
         $payment = $paymentDO->getPayment();
         $data = $payment->getAdditionalInformation();
diff --git a/app/code/Magento/Braintree/Gateway/Request/PayPal/DeviceDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PayPal/DeviceDataBuilder.php
index cea0f8f1291bbd2fc0747a22c538a9c0c58197f2..7d0d9dad0db065ce163302037d48d40d36b2d03a 100644
--- a/app/code/Magento/Braintree/Gateway/Request/PayPal/DeviceDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/PayPal/DeviceDataBuilder.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request\PayPal;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Observer\DataAssignObserver;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 
diff --git a/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php
index 6f76c3415c31a9371bec6fa214488691c1a890c5..a035c84b4cafd5e01d64039f3df85c8010580a82 100644
--- a/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request\PayPal;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Vault\Model\Ui\VaultConfigProvider;
 
diff --git a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php
index a3341c3fc18736fc1ce0cdb890f6751cda93c93e..85a0c644513983c797f554a149d4040b7c14fd56 100644
--- a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
 use Magento\Braintree\Observer\DataAssignObserver;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Payment\Helper\Formatter;
 
@@ -87,7 +87,7 @@ class PaymentDataBuilder implements BuilderInterface
             self::ORDER_ID => $order->getOrderIncrementId()
         ];
 
-        $merchantAccountId = $this->config->getMerchantAccountId();
+        $merchantAccountId = $this->config->getMerchantAccountId($order->getStoreId());
         if (!empty($merchantAccountId)) {
             $result[self::MERCHANT_ACCOUNT_ID] = $merchantAccountId;
         }
diff --git a/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php
index 82de8e84cbfea6f60852f03b3f86f74439db4d64..1c25646311160a14232ad20eed2537e8959d35dd 100644
--- a/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Payment\Helper\Formatter;
 use Magento\Sales\Api\Data\TransactionInterface;
diff --git a/app/code/Magento/Braintree/Gateway/Request/StoreConfigBuilder.php b/app/code/Magento/Braintree/Gateway/Request/StoreConfigBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..014df33690fa0034f6f32077c4aeaf23881ec5f2
--- /dev/null
+++ b/app/code/Magento/Braintree/Gateway/Request/StoreConfigBuilder.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Gateway\Request;
+
+use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\Braintree\Gateway\SubjectReader;
+
+/**
+ * This builder is used for correct store resolving and used only to retrieve correct store ID.
+ * The data from this build won't be send to Braintree Gateway.
+ */
+class StoreConfigBuilder implements BuilderInterface
+{
+    /**
+     * @var SubjectReader
+     */
+    private $subjectReader;
+
+    /**
+     * @param SubjectReader $subjectReader
+     */
+    public function __construct(SubjectReader $subjectReader)
+    {
+        $this->subjectReader = $subjectReader;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function build(array $buildSubject)
+    {
+        $paymentDO = $this->subjectReader->readPayment($buildSubject);
+        $order = $paymentDO->getOrder();
+
+        return [
+            'store_id' => $order->getStoreId()
+        ];
+    }
+}
diff --git a/app/code/Magento/Braintree/Gateway/Request/ThreeDSecureDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/ThreeDSecureDataBuilder.php
index c366a67701521e017cb6405d9b23283149b25347..520aa584577537c282165431a77a16c5d60830fa 100644
--- a/app/code/Magento/Braintree/Gateway/Request/ThreeDSecureDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/ThreeDSecureDataBuilder.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
 use Magento\Payment\Gateway\Data\OrderAdapterInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Payment\Helper\Formatter;
 
@@ -64,12 +64,15 @@ class ThreeDSecureDataBuilder implements BuilderInterface
      */
     private function is3DSecureEnabled(OrderAdapterInterface $order, $amount)
     {
-        if (!$this->config->isVerify3DSecure() || $amount < $this->config->getThresholdAmount()) {
+        $storeId = $order->getStoreId();
+        if (!$this->config->isVerify3DSecure($storeId)
+            || $amount < $this->config->getThresholdAmount($storeId)
+        ) {
             return false;
         }
 
         $billingAddress = $order->getBillingAddress();
-        $specificCounties = $this->config->get3DSecureSpecificCountries();
+        $specificCounties = $this->config->get3DSecureSpecificCountries($storeId);
         if (!empty($specificCounties) && !in_array($billingAddress->getCountryId(), $specificCounties)) {
             return false;
         }
diff --git a/app/code/Magento/Braintree/Gateway/Request/VaultCaptureDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/VaultCaptureDataBuilder.php
index 7182f87e082d137d6201d71682bf10ea6c56a36c..4280663178efb95801c49c5e6f76514fc884b899 100644
--- a/app/code/Magento/Braintree/Gateway/Request/VaultCaptureDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/VaultCaptureDataBuilder.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Payment\Helper\Formatter;
 
diff --git a/app/code/Magento/Braintree/Gateway/Request/VoidDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/VoidDataBuilder.php
index 2328ea10f78c74ce08d457272d23ed37bfd6078c..0bbda28cd344b4fec14e0cea8190429866034105 100644
--- a/app/code/Magento/Braintree/Gateway/Request/VoidDataBuilder.php
+++ b/app/code/Magento/Braintree/Gateway/Request/VoidDataBuilder.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Request;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Request\BuilderInterface;
 use Magento\Sales\Model\Order\Payment;
 
diff --git a/app/code/Magento/Braintree/Gateway/Response/CardDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/CardDetailsHandler.php
index 2715da5d3c4196f7971d73d33a9b7fecd9b74eab..e89e604867baaa28bff08dc2ac72cd7df44ef811 100644
--- a/app/code/Magento/Braintree/Gateway/Response/CardDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/CardDetailsHandler.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Response;
 
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Helper\ContextHelper;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
diff --git a/app/code/Magento/Braintree/Gateway/Response/PayPal/VaultDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/PayPal/VaultDetailsHandler.php
index 766b385851ab811cf9008c5e205ad51a278453a6..f527e9051935b7fc8d258d6ada419516856930d9 100644
--- a/app/code/Magento/Braintree/Gateway/Response/PayPal/VaultDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/PayPal/VaultDetailsHandler.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Response\PayPal;
 
 use Braintree\Transaction;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Framework\Intl\DateTimeFactory;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Payment\Model\InfoInterface;
diff --git a/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php
index 83d7e44a6b612a91ccc0678dfa91bb887b69cfb4..97bb312af4bd49ab5a6740eb3b8aaa28b06dfaea 100644
--- a/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Response;
 
 use Magento\Payment\Gateway\Response\HandlerInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
 
 /**
diff --git a/app/code/Magento/Braintree/Gateway/Response/PaymentDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/PaymentDetailsHandler.php
index 3941640aaeeb115b2820fcec04f7b3940192037a..6e509fae35fec28b5313f5fc1d8c656d7ce0965f 100644
--- a/app/code/Magento/Braintree/Gateway/Response/PaymentDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/PaymentDetailsHandler.php
@@ -8,7 +8,7 @@ namespace Magento\Braintree\Gateway\Response;
 use Braintree\Transaction;
 use Magento\Braintree\Observer\DataAssignObserver;
 use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
 
diff --git a/app/code/Magento/Braintree/Gateway/Response/RiskDataHandler.php b/app/code/Magento/Braintree/Gateway/Response/RiskDataHandler.php
index 95660e10b394cfbe4fee83f72ee1dc7544b0fa62..d4976ff18e0ee6f9229e70b2f95a774dc649b61c 100644
--- a/app/code/Magento/Braintree/Gateway/Response/RiskDataHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/RiskDataHandler.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Gateway\Response;
 
 use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 
 /**
diff --git a/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php
index 93f37cb561feb4bf418c7c17419a97541d7a320b..8d61660f03ce5d69264c693be589975940a17b35 100644
--- a/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Gateway\Response;
 
 use Braintree\Transaction;
 use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
 
diff --git a/app/code/Magento/Braintree/Gateway/Response/TransactionIdHandler.php b/app/code/Magento/Braintree/Gateway/Response/TransactionIdHandler.php
index 7dd79143736e5827e9b8b789a155587d4a895c78..18888bdcf3d4a2f9d36b034c0a95ca975c238c21 100644
--- a/app/code/Magento/Braintree/Gateway/Response/TransactionIdHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/TransactionIdHandler.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Gateway\Response;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Sales\Model\Order\Payment;
 
diff --git a/app/code/Magento/Braintree/Gateway/Response/VaultDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/VaultDetailsHandler.php
index a8332b9409f78f3a33d089d90499afb10462be4c..89bf7f14692b0567a7cd227a98bea5d9a293581d 100644
--- a/app/code/Magento/Braintree/Gateway/Response/VaultDetailsHandler.php
+++ b/app/code/Magento/Braintree/Gateway/Response/VaultDetailsHandler.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Gateway\Response;
 
 use Braintree\Transaction;
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Response\HandlerInterface;
 use Magento\Payment\Model\InfoInterface;
 use Magento\Sales\Api\Data\OrderPaymentExtensionInterface;
diff --git a/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php b/app/code/Magento/Braintree/Gateway/SubjectReader.php
similarity index 92%
rename from app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php
rename to app/code/Magento/Braintree/Gateway/SubjectReader.php
index e98597655190f891c65412befaf18acd4ad16dac..d5dc43a4c5e340fe7675788d9cd5a9117bf7c5d8 100644
--- a/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php
+++ b/app/code/Magento/Braintree/Gateway/SubjectReader.php
@@ -3,13 +3,12 @@
  * Copyright © Magento, Inc. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Braintree\Gateway\Helper;
+namespace Magento\Braintree\Gateway;
 
 use Braintree\Transaction;
-use Magento\Quote\Model\Quote;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Payment\Gateway\Helper;
 use Magento\Vault\Api\Data\PaymentTokenInterface;
-use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 
 /**
  * Class SubjectReader
@@ -119,4 +118,15 @@ class SubjectReader
 
         return $transaction->paypal;
     }
+
+    /**
+     * Reads store's ID, otherwise returns null.
+     *
+     * @param array $subject
+     * @return int|null
+     */
+    public function readStoreId(array $subject)
+    {
+        return $subject['store_id'] ?? null;
+    }
 }
diff --git a/app/code/Magento/Braintree/Gateway/Validator/GeneralResponseValidator.php b/app/code/Magento/Braintree/Gateway/Validator/GeneralResponseValidator.php
index a70bc2d02e0e5443ee7ce69242cfafaf91e75e21..8028bace0cf242d373e329f0a90fbdf9a1fb2bc9 100644
--- a/app/code/Magento/Braintree/Gateway/Validator/GeneralResponseValidator.php
+++ b/app/code/Magento/Braintree/Gateway/Validator/GeneralResponseValidator.php
@@ -8,7 +8,7 @@ namespace Magento\Braintree\Gateway\Validator;
 use Braintree\Result\Error;
 use Braintree\Result\Successful;
 use Magento\Payment\Gateway\Validator\AbstractValidator;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
 
 class GeneralResponseValidator extends AbstractValidator
diff --git a/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php
index 71f3828ebe9d4cef4fa9871fa6fc9161ff9edb22..d11be39a9bb490c871a5fbe4c0e31b01b197e2f8 100644
--- a/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php
+++ b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php
@@ -15,29 +15,40 @@ use Magento\Braintree\Model\Adminhtml\Source\Environment;
 
 /**
  * Class BraintreeAdapter
+ * Use \Magento\Braintree\Model\Adapter\BraintreeAdapterFactory to create new instance of adapter.
  * @codeCoverageIgnore
  */
 class BraintreeAdapter
 {
-
     /**
      * @var Config
      */
     private $config;
 
     /**
-     * @param Config $config
+     * @param string $merchantId
+     * @param string $publicKey
+     * @param string $privateKey
+     * @param string $environment
      */
-    public function __construct(Config $config)
+    public function __construct($merchantId, $publicKey, $privateKey, $environment)
     {
-        $this->config = $config;
-        $this->initCredentials();
+        $this->merchantId($merchantId);
+        $this->publicKey($publicKey);
+        $this->privateKey($privateKey);
+
+        if ($environment == Environment::ENVIRONMENT_PRODUCTION) {
+            $this->environment(Environment::ENVIRONMENT_PRODUCTION);
+        } else {
+            $this->environment(Environment::ENVIRONMENT_SANDBOX);
+        }
     }
 
     /**
      * Initializes credentials.
      *
      * @return void
+     * @deprecated is not used anymore
      */
     protected function initCredentials()
     {
diff --git a/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapterFactory.php b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapterFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..890f1a1021eda8cbc05656d5e507fb7772bb302a
--- /dev/null
+++ b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapterFactory.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Model\Adapter;
+
+use Magento\Braintree\Gateway\Config\Config;
+use Magento\Framework\ObjectManagerInterface;
+
+/**
+ * This factory is preferable to use for Braintree adapter instance creation.
+ */
+class BraintreeAdapterFactory
+{
+    /**
+     * @var ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * @var Config
+     */
+    private $config;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param Config $config
+     */
+    public function __construct(ObjectManagerInterface $objectManager, Config $config)
+    {
+        $this->config = $config;
+        $this->objectManager = $objectManager;
+    }
+
+    /**
+     * Creates instance of Braintree Adapter.
+     *
+     * @param int $storeId if null is provided as an argument, then current scope will be resolved
+     * by \Magento\Framework\App\Config\ScopeCodeResolver (useful for most cases) but for adminhtml area the store
+     * should be provided as the argument for correct config settings loading.
+     * @return BraintreeAdapter
+     */
+    public function create($storeId = null)
+    {
+        return $this->objectManager->create(
+            BraintreeAdapter::class,
+            [
+                'merchantId' => $this->config->getMerchantId($storeId),
+                'publicKey' => $this->config->getValue(Config::KEY_PUBLIC_KEY, $storeId),
+                'privateKey' => $this->config->getValue(Config::KEY_PRIVATE_KEY, $storeId),
+                'environment' => $this->config->getEnvironment($storeId)
+            ]
+        );
+    }
+}
diff --git a/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php b/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php
index edac6e35338498742f446bf560e97aeb5326a3e9..a237b64bf58ee4e4edc0506bb7eea75c99f0b1ad 100644
--- a/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php
+++ b/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php
@@ -5,7 +5,8 @@
  */
 namespace Magento\Braintree\Model\Report;
 
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
+use Magento\Braintree\Model\Report\Row\TransactionMap;
 use Magento\Framework\Api\Search\SearchResultInterface;
 use Magento\Framework\Api\SearchCriteriaInterface;
 use Magento\Framework\Data\Collection;
@@ -26,7 +27,7 @@ class TransactionsCollection extends Collection implements SearchResultInterface
      *
      * @var string
      */
-    protected $_itemObjectClass = \Magento\Braintree\Model\Report\Row\TransactionMap::class;
+    protected $_itemObjectClass = TransactionMap::class;
 
     /**
      * @var array
@@ -39,9 +40,9 @@ class TransactionsCollection extends Collection implements SearchResultInterface
     private $filterMapper;
 
     /**
-     * @var BraintreeAdapter
+     * @var BraintreeAdapterFactory
      */
-    private $braintreeAdapter;
+    private $braintreeAdapterFactory;
 
     /**
      * @var \Braintree\ResourceCollection | null
@@ -50,17 +51,17 @@ class TransactionsCollection extends Collection implements SearchResultInterface
 
     /**
      * @param EntityFactoryInterface $entityFactory
-     * @param BraintreeAdapter $braintreeAdapter
+     * @param BraintreeAdapterFactory $braintreeAdapterFactory
      * @param FilterMapper $filterMapper
      */
     public function __construct(
         EntityFactoryInterface $entityFactory,
-        BraintreeAdapter $braintreeAdapter,
+        BraintreeAdapterFactory $braintreeAdapterFactory,
         FilterMapper $filterMapper
     ) {
         parent::__construct($entityFactory);
         $this->filterMapper = $filterMapper;
-        $this->braintreeAdapter = $braintreeAdapter;
+        $this->braintreeAdapterFactory = $braintreeAdapterFactory;
     }
 
     /**
@@ -110,7 +111,8 @@ class TransactionsCollection extends Collection implements SearchResultInterface
         // Fetch all transaction IDs in order to filter
         if (empty($this->collection)) {
             $filters = $this->getFilters();
-            $this->collection = $this->braintreeAdapter->search($filters);
+            $this->collection = $this->braintreeAdapterFactory->create()
+                ->search($filters);
         }
 
         return $this->collection;
diff --git a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php
index c420195446270e49b3a75e6707a15a0a4835a9c8..6ab69923760ce6c7770102184aff40c58b4a323f 100644
--- a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php
+++ b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php
@@ -5,10 +5,11 @@
  */
 namespace Magento\Braintree\Model\Ui;
 
+use Magento\Braintree\Gateway\Config\Config;
 use Magento\Braintree\Gateway\Request\PaymentDataBuilder;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Checkout\Model\ConfigProviderInterface;
-use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Framework\Session\SessionManagerInterface;
 
 /**
  * Class ConfigProvider
@@ -25,27 +26,35 @@ class ConfigProvider implements ConfigProviderInterface
     private $config;
 
     /**
-     * @var BraintreeAdapter
+     * @var BraintreeAdapterFactory
      */
-    private $adapter;
+    private $adapterFactory;
 
     /**
      * @var string
      */
     private $clientToken = '';
 
+    /**
+     * @var SessionManagerInterface
+     */
+    private $session;
+
     /**
      * Constructor
      *
      * @param Config $config
-     * @param BraintreeAdapter $adapter
+     * @param BraintreeAdapterFactory $adapterFactory
+     * @param SessionManagerInterface $session
      */
     public function __construct(
         Config $config,
-        BraintreeAdapter $adapter
+        BraintreeAdapterFactory $adapterFactory,
+        SessionManagerInterface $session
     ) {
         $this->config = $config;
-        $this->adapter = $adapter;
+        $this->adapterFactory = $adapterFactory;
+        $this->session = $session;
     }
 
     /**
@@ -55,26 +64,27 @@ class ConfigProvider implements ConfigProviderInterface
      */
     public function getConfig()
     {
+        $storeId = $this->session->getStoreId();
         return [
             'payment' => [
                 self::CODE => [
-                    'isActive' => $this->config->isActive(),
+                    'isActive' => $this->config->isActive($storeId),
                     'clientToken' => $this->getClientToken(),
                     'ccTypesMapper' => $this->config->getCctypesMapper(),
                     'sdkUrl' => $this->config->getSdkUrl(),
-                    'countrySpecificCardTypes' => $this->config->getCountrySpecificCardTypeConfig(),
-                    'availableCardTypes' => $this->config->getAvailableCardTypes(),
-                    'useCvv' => $this->config->isCvvEnabled(),
-                    'environment' => $this->config->getEnvironment(),
-                    'kountMerchantId' => $this->config->getKountMerchantId(),
-                    'hasFraudProtection' => $this->config->hasFraudProtection(),
-                    'merchantId' => $this->config->getMerchantId(),
+                    'countrySpecificCardTypes' => $this->config->getCountrySpecificCardTypeConfig($storeId),
+                    'availableCardTypes' => $this->config->getAvailableCardTypes($storeId),
+                    'useCvv' => $this->config->isCvvEnabled($storeId),
+                    'environment' => $this->config->getEnvironment($storeId),
+                    'kountMerchantId' => $this->config->getKountMerchantId($storeId),
+                    'hasFraudProtection' => $this->config->hasFraudProtection($storeId),
+                    'merchantId' => $this->config->getMerchantId($storeId),
                     'ccVaultCode' => self::CC_VAULT_CODE
                 ],
                 Config::CODE_3DSECURE => [
-                    'enabled' => $this->config->isVerify3DSecure(),
-                    'thresholdAmount' => $this->config->getThresholdAmount(),
-                    'specificCountries' => $this->config->get3DSecureSpecificCountries()
+                    'enabled' => $this->config->isVerify3DSecure($storeId),
+                    'thresholdAmount' => $this->config->getThresholdAmount($storeId),
+                    'specificCountries' => $this->config->get3DSecureSpecificCountries($storeId)
                 ],
             ]
         ];
@@ -89,12 +99,14 @@ class ConfigProvider implements ConfigProviderInterface
         if (empty($this->clientToken)) {
             $params = [];
 
-            $merchantAccountId = $this->config->getMerchantAccountId();
+            $storeId = $this->session->getStoreId();
+            $merchantAccountId = $this->config->getMerchantAccountId($storeId);
             if (!empty($merchantAccountId)) {
                 $params[PaymentDataBuilder::MERCHANT_ACCOUNT_ID] = $merchantAccountId;
             }
 
-            $this->clientToken = $this->adapter->generate($params);
+            $this->clientToken = $this->adapterFactory->create($storeId)
+                ->generate($params);
         }
 
         return $this->clientToken;
diff --git a/app/code/Magento/Braintree/Test/Unit/Block/FormTest.php b/app/code/Magento/Braintree/Test/Unit/Block/FormTest.php
index 5b28e6d8aedcdd8979d23a2ac21d8f1e4992b06c..9d363c77f2b0557f15b406be6391161b2226ad56 100644
--- a/app/code/Magento/Braintree/Test/Unit/Block/FormTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Block/FormTest.php
@@ -13,8 +13,6 @@ use Magento\Braintree\Model\Ui\ConfigProvider;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 use Magento\Payment\Helper\Data;
 use Magento\Payment\Model\Config;
-use Magento\Store\Api\Data\StoreInterface;
-use Magento\Store\Model\StoreManagerInterface;
 use Magento\Vault\Model\VaultPaymentInterface;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
@@ -57,11 +55,6 @@ class FormTest extends \PHPUnit\Framework\TestCase
      */
     private $ccType;
 
-    /**
-     * @var StoreManagerInterface|MockObject
-     */
-    private $storeManager;
-
     /**
      * @var Data|MockObject
      */
@@ -72,8 +65,7 @@ class FormTest extends \PHPUnit\Framework\TestCase
         $this->initCcTypeMock();
         $this->initSessionQuoteMock();
         $this->initGatewayConfigMock();
-        
-        $this->storeManager = $this->getMockForAbstractClass(StoreManagerInterface::class);
+
         $this->paymentDataHelper = $this->getMockBuilder(Data::class)
             ->disableOriginalConstructor()
             ->setMethods(['getMethodInstance'])
@@ -84,15 +76,13 @@ class FormTest extends \PHPUnit\Framework\TestCase
             'paymentConfig' => $managerHelper->getObject(Config::class),
             'sessionQuote' => $this->sessionQuote,
             'gatewayConfig' => $this->gatewayConfig,
-            'ccType' => $this->ccType,
-            'storeManager' => $this->storeManager
+            'ccType' => $this->ccType
         ]);
 
         $managerHelper->setBackwardCompatibleProperty($this->block, 'paymentDataHelper', $this->paymentDataHelper);
     }
 
     /**
-     * @covers \Magento\Braintree\Block\Form::getCcAvailableTypes
      * @param string $countryId
      * @param array $availableTypes
      * @param array $expected
@@ -100,21 +90,18 @@ class FormTest extends \PHPUnit\Framework\TestCase
      */
     public function testGetCcAvailableTypes($countryId, array $availableTypes, array $expected)
     {
-        $this->sessionQuote->expects(static::once())
-            ->method('getCountryId')
+        $this->sessionQuote->method('getCountryId')
             ->willReturn($countryId);
 
-        $this->gatewayConfig->expects(static::once())
-            ->method('getAvailableCardTypes')
+        $this->gatewayConfig->method('getAvailableCardTypes')
             ->willReturn(self::$configCardTypes);
 
-        $this->gatewayConfig->expects(static::once())
-            ->method('getCountryAvailableCardTypes')
+        $this->gatewayConfig->method('getCountryAvailableCardTypes')
             ->with($countryId)
             ->willReturn($availableTypes);
 
         $result = $this->block->getCcAvailableTypes();
-        static::assertEquals($expected, array_values($result));
+        self::assertEquals($expected, array_values($result));
     }
 
     /**
@@ -131,33 +118,20 @@ class FormTest extends \PHPUnit\Framework\TestCase
         ];
     }
 
-    /**
-     * @covers \Magento\Braintree\Block\Form::isVaultEnabled
-     */
     public function testIsVaultEnabled()
     {
         $storeId = 1;
-        $store = $this->getMockForAbstractClass(StoreInterface::class);
-        $this->storeManager->expects(static::once())
-            ->method('getStore')
-            ->willReturn($store);
-        
-        $store->expects(static::once())
-            ->method('getId')
-            ->willReturn($storeId);
 
         $vaultPayment = $this->getMockForAbstractClass(VaultPaymentInterface::class);
-        $this->paymentDataHelper->expects(static::once())
-            ->method('getMethodInstance')
+        $this->paymentDataHelper->method('getMethodInstance')
             ->with(ConfigProvider::CC_VAULT_CODE)
             ->willReturn($vaultPayment);
 
-        $vaultPayment->expects(static::once())
-            ->method('isActive')
-            ->with($storeId)
+        $vaultPayment->method('isActive')
+            ->with(self::equalTo($storeId))
             ->willReturn(true);
 
-        static::assertTrue($this->block->isVaultEnabled());
+        self::assertTrue($this->block->isVaultEnabled());
     }
 
     /**
@@ -170,8 +144,7 @@ class FormTest extends \PHPUnit\Framework\TestCase
             ->setMethods(['getCcTypeLabelMap'])
             ->getMock();
 
-        $this->ccType->expects(static::any())
-            ->method('getCcTypeLabelMap')
+        $this->ccType->method('getCcTypeLabelMap')
             ->willReturn(self::$baseCardTypes);
     }
 
@@ -182,15 +155,15 @@ class FormTest extends \PHPUnit\Framework\TestCase
     {
         $this->sessionQuote = $this->getMockBuilder(Quote::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getQuote', 'getBillingAddress', 'getCountryId', '__wakeup'])
+            ->setMethods(['getQuote', 'getBillingAddress', 'getCountryId', 'getStoreId'])
             ->getMock();
 
-        $this->sessionQuote->expects(static::any())
-            ->method('getQuote')
+        $this->sessionQuote->method('getQuote')
             ->willReturnSelf();
-        $this->sessionQuote->expects(static::any())
-            ->method('getBillingAddress')
+        $this->sessionQuote->method('getBillingAddress')
             ->willReturnSelf();
+        $this->sessionQuote->method('getStoreId')
+            ->willReturn(1);
     }
 
     /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Payment/GetNonceTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Payment/GetNonceTest.php
index e78e54f011d44d68bf3a99fd929ae483dea688a3..723897491da63db8b07b58c49c371b9697385c43 100644
--- a/app/code/Magento/Braintree/Test/Unit/Controller/Payment/GetNonceTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Controller/Payment/GetNonceTest.php
@@ -16,6 +16,7 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 use Magento\Framework\Webapi\Exception;
 use Magento\Payment\Gateway\Command\ResultInterface as CommandResultInterface;
 use Psr\Log\LoggerInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class GetNonceTest
@@ -30,37 +31,37 @@ class GetNonceTest extends \PHPUnit\Framework\TestCase
     private $action;
 
     /**
-     * @var GetPaymentNonceCommand|\PHPUnit_Framework_MockObject_MockObject
+     * @var GetPaymentNonceCommand|MockObject
      */
     private $command;
 
     /**
-     * @var Session|\PHPUnit_Framework_MockObject_MockObject
+     * @var Session|MockObject
      */
     private $session;
 
     /**
-     * @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var LoggerInterface|MockObject
      */
     private $logger;
 
     /**
-     * @var ResultFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var ResultFactory|MockObject
      */
     private $resultFactory;
 
     /**
-     * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var ResultInterface|MockObject
      */
     private $result;
 
     /**
-     * @var Http|\PHPUnit_Framework_MockObject_MockObject
+     * @var Http|MockObject
      */
     private $request;
 
     /**
-     * @var CommandResultInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var CommandResultInterface|MockObject
      */
     private $commandResult;
 
@@ -84,7 +85,7 @@ class GetNonceTest extends \PHPUnit\Framework\TestCase
 
         $this->session = $this->getMockBuilder(Session::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getCustomerId'])
+            ->setMethods(['getCustomerId', 'getStoreId'])
             ->getMock();
 
         $this->logger = $this->createMock(LoggerInterface::class);
@@ -92,11 +93,9 @@ class GetNonceTest extends \PHPUnit\Framework\TestCase
         $context = $this->getMockBuilder(Context::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $context->expects(static::any())
-            ->method('getRequest')
+        $context->method('getRequest')
             ->willReturn($this->request);
-        $context->expects(static::any())
-            ->method('getResultFactory')
+        $context->method('getResultFactory')
             ->willReturn($this->resultFactory);
 
         $managerHelper = new ObjectManager($this);
@@ -108,81 +107,68 @@ class GetNonceTest extends \PHPUnit\Framework\TestCase
         ]);
     }
 
-    /**
-     * @covers \Magento\Braintree\Controller\Payment\GetNonce::execute
-     */
     public function testExecuteWithException()
     {
-        $this->request->expects(static::once())
-            ->method('getParam')
+        $this->request->method('getParam')
             ->with('public_hash')
             ->willReturn(null);
 
-        $this->session->expects(static::once())
-            ->method('getCustomerId')
+        $this->session->method('getCustomerId')
+            ->willReturn(null);
+        $this->session->method('getStoreId')
             ->willReturn(null);
 
         $exception = new \Exception('The "publicHash" field does not exists');
-        $this->command->expects(static::once())
-            ->method('execute')
+        $this->command->method('execute')
             ->willThrowException($exception);
 
-        $this->logger->expects(static::once())
-            ->method('critical')
+        $this->logger->method('critical')
             ->with($exception);
 
-        $this->result->expects(static::once())
-            ->method('setHttpResponseCode')
+        $this->result->method('setHttpResponseCode')
             ->with(Exception::HTTP_BAD_REQUEST);
-        $this->result->expects(static::once())
-            ->method('setData')
+        $this->result->method('setData')
             ->with(['message' => 'Sorry, but something went wrong']);
 
         $this->action->execute();
     }
 
-    /**
-     * @covers \Magento\Braintree\Controller\Payment\GetNonce::execute
-     */
     public function testExecute()
     {
         $customerId = 1;
         $publicHash = '65b7bae0dcb690d93';
         $nonce = 'f1hc45';
 
-        $this->request->expects(static::once())
-            ->method('getParam')
+        $this->request->method('getParam')
             ->with('public_hash')
             ->willReturn($publicHash);
 
-        $this->session->expects(static::once())
-            ->method('getCustomerId')
+        $this->session->method('getCustomerId')
             ->willReturn($customerId);
+        $this->session->method('getStoreId')
+            ->willReturn(null);
 
-        $this->commandResult->expects(static::once())
-            ->method('get')
+        $this->commandResult->method('get')
             ->willReturn([
                 'paymentMethodNonce' => $nonce
             ]);
-        $this->command->expects(static::once())
-            ->method('execute')
+        $this->command->method('execute')
             ->willReturn($this->commandResult);
 
-        $this->result->expects(static::once())
-            ->method('setData')
+        $this->result->method('setData')
             ->with(['paymentMethodNonce' => $nonce]);
 
-        $this->logger->expects(static::never())
+        $this->logger->expects(self::never())
             ->method('critical');
 
-        $this->result->expects(static::never())
+        $this->result->expects(self::never())
             ->method('setHttpResponseCode');
 
         $this->action->execute();
     }
 
     /**
-     * Create mock for result factory object
+     * Creates mock for result factory object
      */
     private function initResultFactoryMock()
     {
@@ -195,8 +181,7 @@ class GetNonceTest extends \PHPUnit\Framework\TestCase
             ->setMethods(['create'])
             ->getMock();
 
-        $this->resultFactory->expects(static::once())
-            ->method('create')
+        $this->resultFactory->method('create')
             ->willReturn($this->result);
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php
index 56ea1f97fa165e27c993735990796e17bffda64b..52e17c4ff5d557d3162dc6d40255675d95b46969 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php
@@ -6,23 +6,22 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Command;
 
 use Braintree\IsNode;
-use Braintree\MultipleValueNode;
-use Braintree\TextNode;
 use Magento\Braintree\Gateway\Command\CaptureStrategyCommand;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
+use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
+use Magento\Braintree\Model\Adapter\BraintreeSearchAdapter;
 use Magento\Framework\Api\FilterBuilder;
 use Magento\Framework\Api\Search\SearchCriteria;
 use Magento\Framework\Api\SearchCriteriaBuilder;
-use Magento\Payment\Gateway\Command;
 use Magento\Payment\Gateway\Command\CommandPoolInterface;
 use Magento\Payment\Gateway\Command\GatewayCommand;
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
 use Magento\Sales\Api\TransactionRepositoryInterface;
 use Magento\Sales\Model\Order\Payment;
-use Magento\Sales\Model\Order\Payment\Transaction;
 use Magento\Sales\Model\ResourceModel\Order\Payment\Transaction\CollectionFactory;
-use Magento\Braintree\Model\Adapter\BraintreeAdapter;
-use Magento\Braintree\Model\Adapter\BraintreeSearchAdapter;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class CaptureStrategyCommandTest
@@ -37,42 +36,42 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
     private $strategyCommand;
 
     /**
-     * @var CommandPoolInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var CommandPoolInterface|MockObject
      */
     private $commandPool;
 
     /**
-     * @var TransactionRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var TransactionRepositoryInterface|MockObject
      */
     private $transactionRepository;
 
     /**
-     * @var FilterBuilder|\PHPUnit_Framework_MockObject_MockObject
+     * @var FilterBuilder|MockObject
      */
     private $filterBuilder;
 
     /**
-     * @var SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+     * @var SearchCriteriaBuilder|MockObject
      */
     private $searchCriteriaBuilder;
 
     /**
-     * @var Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var Payment|MockObject
      */
     private $payment;
 
     /**
-     * @var GatewayCommand|\PHPUnit_Framework_MockObject_MockObject
+     * @var GatewayCommand|MockObject
      */
     private $command;
 
     /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+     * @var SubjectReader|MockObject
      */
-    private $subjectReaderMock;
+    private $subjectReader;
 
     /**
-     * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapter|MockObject
      */
     private $braintreeAdapter;
 
@@ -88,7 +87,7 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
             ->setMethods(['get', '__wakeup'])
             ->getMock();
 
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+        $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
             ->disableOriginalConstructor()
             ->getMock();
 
@@ -100,6 +99,13 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
         $this->braintreeAdapter = $this->getMockBuilder(BraintreeAdapter::class)
             ->disableOriginalConstructor()
             ->getMock();
+        /** @var BraintreeAdapterFactory|MockObject $adapterFactory */
+        $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adapterFactory->method('create')
+            ->willReturn($this->braintreeAdapter);
+
         $this->braintreeSearchAdapter = new BraintreeSearchAdapter();
 
         $this->strategyCommand = new CaptureStrategyCommand(
@@ -107,86 +113,68 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
             $this->transactionRepository,
             $this->filterBuilder,
             $this->searchCriteriaBuilder,
-            $this->subjectReaderMock,
-            $this->braintreeAdapter,
+            $this->subjectReader,
+            $adapterFactory,
             $this->braintreeSearchAdapter
         );
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute
-     */
     public function testSaleExecute()
     {
         $paymentData = $this->getPaymentDataObjectMock();
         $subject['payment'] = $paymentData;
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
+        $this->subjectReader->method('readPayment')
             ->with($subject)
             ->willReturn($paymentData);
 
-        $this->payment->expects(static::once())
-            ->method('getAuthorizationTransaction')
+        $this->payment->method('getAuthorizationTransaction')
             ->willReturn(false);
 
-        $this->payment->expects(static::once())
-            ->method('getId')
+        $this->payment->method('getId')
             ->willReturn(1);
 
         $this->buildSearchCriteria();
 
-        $this->transactionRepository->expects(static::once())
-            ->method('getTotalCount')
+        $this->transactionRepository->method('getTotalCount')
             ->willReturn(0);
 
-        $this->commandPool->expects(static::once())
-            ->method('get')
+        $this->commandPool->method('get')
             ->with(CaptureStrategyCommand::SALE)
             ->willReturn($this->command);
 
         $this->strategyCommand->execute($subject);
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute
-     */
     public function testCaptureExecute()
     {
         $paymentData = $this->getPaymentDataObjectMock();
         $subject['payment'] = $paymentData;
         $lastTransId = 'txnds';
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
+        $this->subjectReader->method('readPayment')
             ->with($subject)
             ->willReturn($paymentData);
 
-        $this->payment->expects(static::once())
-            ->method('getAuthorizationTransaction')
+        $this->payment->method('getAuthorizationTransaction')
             ->willReturn(true);
-        $this->payment->expects(static::once())
-            ->method('getLastTransId')
+        $this->payment->method('getLastTransId')
             ->willReturn($lastTransId);
 
-        $this->payment->expects(static::once())
-            ->method('getId')
+        $this->payment->method('getId')
             ->willReturn(1);
 
         $this->buildSearchCriteria();
 
-        $this->transactionRepository->expects(static::once())
-            ->method('getTotalCount')
+        $this->transactionRepository->method('getTotalCount')
             ->willReturn(0);
 
         // authorization transaction was not expired
         $collection = $this->getNotExpiredExpectedCollection($lastTransId);
-        $collection->expects(static::once())
-            ->method('maximumCount')
+        $collection->method('maximumCount')
             ->willReturn(0);
 
-        $this->commandPool->expects(static::once())
-            ->method('get')
+        $this->commandPool->method('get')
             ->with(CaptureStrategyCommand::CAPTURE)
             ->willReturn($this->command);
 
@@ -195,7 +183,7 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
 
     /**
      * @param string $lastTransactionId
-     * @return \Braintree\ResourceCollection|\PHPUnit_Framework_MockObject_MockObject
+     * @return \Braintree\ResourceCollection|MockObject
      */
     private function getNotExpiredExpectedCollection($lastTransactionId)
     {
@@ -208,10 +196,9 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->braintreeAdapter->expects(static::once())
-            ->method('search')
+        $this->braintreeAdapter->method('search')
             ->with(
-                static::callback(
+                self::callback(
                     function (array $filters) use ($isExpectations) {
                         foreach ($filters as $filter) {
                             /** @var IsNode $filter */
@@ -233,80 +220,62 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
         return $collection;
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute
-     */
     public function testExpiredAuthorizationPerformVaultCaptureExecute()
     {
         $paymentData = $this->getPaymentDataObjectMock();
         $subject['payment'] = $paymentData;
         $lastTransId = 'txnds';
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
+        $this->subjectReader->method('readPayment')
             ->with($subject)
             ->willReturn($paymentData);
 
-        $this->payment->expects(static::once())
-            ->method('getAuthorizationTransaction')
+        $this->payment->method('getAuthorizationTransaction')
             ->willReturn(true);
-        $this->payment->expects(static::once())
-            ->method('getLastTransId')
+        $this->payment->method('getLastTransId')
             ->willReturn($lastTransId);
 
-        $this->payment->expects(static::once())
-            ->method('getId')
+        $this->payment->method('getId')
             ->willReturn(1);
 
         $this->buildSearchCriteria();
 
-        $this->transactionRepository->expects(static::once())
-            ->method('getTotalCount')
+        $this->transactionRepository->method('getTotalCount')
             ->willReturn(0);
 
         // authorization transaction was expired
         $collection = $this->getNotExpiredExpectedCollection($lastTransId);
-        $collection->expects(static::once())
-            ->method('maximumCount')
+        $collection->method('maximumCount')
             ->willReturn(1);
 
-        $this->commandPool->expects(static::once())
-            ->method('get')
+        $this->commandPool->method('get')
             ->with(CaptureStrategyCommand::VAULT_CAPTURE)
             ->willReturn($this->command);
 
         $this->strategyCommand->execute($subject);
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute
-     */
     public function testVaultCaptureExecute()
     {
         $paymentData = $this->getPaymentDataObjectMock();
         $subject['payment'] = $paymentData;
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
+        $this->subjectReader->method('readPayment')
             ->with($subject)
             ->willReturn($paymentData);
 
-        $this->payment->expects(static::once())
-            ->method('getAuthorizationTransaction')
+        $this->payment->method('getAuthorizationTransaction')
             ->willReturn(true);
 
-        $this->payment->expects(static::once())
-            ->method('getId')
+        $this->payment->method('getId')
             ->willReturn(1);
 
         $this->buildSearchCriteria();
 
-        $this->transactionRepository->expects(static::once())
-            ->method('getTotalCount')
+        $this->transactionRepository->method('getTotalCount')
             ->willReturn(1);
 
-        $this->commandPool->expects(static::once())
-            ->method('get')
+        $this->commandPool->method('get')
             ->with(CaptureStrategyCommand::VAULT_CAPTURE)
             ->willReturn($this->command);
 
@@ -314,8 +283,8 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * Create mock for payment data object and order payment
-     * @return \PHPUnit_Framework_MockObject_MockObject
+     * Creates mock for payment data object and order payment
+     * @return MockObject
      */
     private function getPaymentDataObjectMock()
     {
@@ -324,19 +293,25 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
             ->getMock();
 
         $mock = $this->getMockBuilder(PaymentDataObject::class)
-            ->setMethods(['getPayment'])
+            ->setMethods(['getPayment', 'getOrder'])
             ->disableOriginalConstructor()
             ->getMock();
 
-        $mock->expects(static::once())
-            ->method('getPayment')
+        $mock->method('getPayment')
             ->willReturn($this->payment);
 
+        $order = $this->getMockBuilder(OrderAdapterInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->method('getOrder')
+            ->willReturn($order);
+
         return $mock;
     }
 
     /**
-     * Create mock for gateway command object
+     * Creates mock for gateway command object
      */
     private function initCommandMock()
     {
@@ -345,13 +320,12 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
             ->setMethods(['execute'])
             ->getMock();
 
-        $this->command->expects(static::once())
-            ->method('execute')
+        $this->command->method('execute')
             ->willReturn([]);
     }
 
     /**
-     * Create mock for filter object
+     * Creates mock for filter object
      */
     private function initFilterBuilderMock()
     {
@@ -362,27 +336,25 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * Build search criteria
+     * Builds search criteria
      */
     private function buildSearchCriteria()
     {
-        $this->filterBuilder->expects(static::exactly(2))
+        $this->filterBuilder->expects(self::exactly(2))
             ->method('setField')
             ->willReturnSelf();
-        $this->filterBuilder->expects(static::exactly(2))
+        $this->filterBuilder->expects(self::exactly(2))
             ->method('setValue')
             ->willReturnSelf();
 
         $searchCriteria = new SearchCriteria();
-        $this->searchCriteriaBuilder->expects(static::exactly(2))
+        $this->searchCriteriaBuilder->expects(self::exactly(2))
             ->method('addFilters')
             ->willReturnSelf();
-        $this->searchCriteriaBuilder->expects(static::once())
-            ->method('create')
+        $this->searchCriteriaBuilder->method('create')
             ->willReturn($searchCriteria);
 
-        $this->transactionRepository->expects(static::once())
-            ->method('getList')
+        $this->transactionRepository->method('getList')
             ->with($searchCriteria)
             ->willReturnSelf();
     }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php
index 333f29eb29136633763b0b7d38a8a4350663b1c2..1b06fc0d21a2702d9942ec74773b490ee8a5e6a9 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php
@@ -6,15 +6,16 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Command;
 
 use Magento\Braintree\Gateway\Command\GetPaymentNonceCommand;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Validator\PaymentNonceResponseValidator;
 use Magento\Braintree\Model\Adapter\BraintreeAdapter;
-use Magento\Payment\Gateway\Command;
-use Magento\Payment\Gateway\Command\Result\ArrayResultFactory;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Payment\Gateway\Command\Result\ArrayResult;
+use Magento\Payment\Gateway\Command\Result\ArrayResultFactory;
 use Magento\Payment\Gateway\Validator\ResultInterface;
 use Magento\Vault\Model\PaymentToken;
 use Magento\Vault\Model\PaymentTokenManagement;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class GetPaymentNonceCommandTest
@@ -29,37 +30,37 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
     private $command;
 
     /**
-     * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapter|MockObject
      */
     private $adapter;
 
     /**
-     * @var PaymentTokenManagement|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentTokenManagement|MockObject
      */
     private $tokenManagement;
 
     /**
-     * @var PaymentToken|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentToken|MockObject
      */
     private $paymentToken;
 
     /**
-     * @var ArrayResultFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var ArrayResultFactory|MockObject
      */
     private $resultFactory;
 
     /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+     * @var SubjectReader|MockObject
      */
     private $subjectReader;
 
     /**
-     * @var PaymentNonceResponseValidator|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentNonceResponseValidator|MockObject
      */
     private $responseValidator;
 
     /**
-     * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var ResultInterface|MockObject
      */
     private $validationResult;
 
@@ -79,6 +80,12 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
             ->disableOriginalConstructor()
             ->setMethods(['createNonce'])
             ->getMock();
+        /** @var BraintreeAdapterFactory|MockObject $adapterFactory */
+        $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adapterFactory->method('create')
+            ->willReturn($this->adapter);
 
         $this->resultFactory = $this->getMockBuilder(ArrayResultFactory::class)
             ->disableOriginalConstructor()
@@ -101,7 +108,7 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
 
         $this->command = new GetPaymentNonceCommand(
             $this->tokenManagement,
-            $this->adapter,
+            $adapterFactory,
             $this->resultFactory,
             $this->subjectReader,
             $this->responseValidator
@@ -109,7 +116,6 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute
      * @expectedException \InvalidArgumentException
      * @expectedExceptionMessage The "publicHash" field does not exists
      */
@@ -117,18 +123,16 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
     {
         $exception = new \InvalidArgumentException('The "publicHash" field does not exists');
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPublicHash')
+        $this->subjectReader->method('readPublicHash')
             ->willThrowException($exception);
 
-        $this->subjectReader->expects(static::never())
+        $this->subjectReader->expects(self::never())
             ->method('readCustomerId');
 
         $this->command->execute([]);
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute
      * @expectedException \InvalidArgumentException
      * @expectedExceptionMessage The "customerId" field does not exists
      */
@@ -136,23 +140,20 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
     {
         $publicHash = '3wv2m24d2er3';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPublicHash')
+        $this->subjectReader->method('readPublicHash')
             ->willReturn($publicHash);
 
         $exception = new \InvalidArgumentException('The "customerId" field does not exists');
-        $this->subjectReader->expects(static::once())
-            ->method('readCustomerId')
+        $this->subjectReader->method('readCustomerId')
             ->willThrowException($exception);
 
-        $this->tokenManagement->expects(static::never())
+        $this->tokenManagement->expects(self::never())
             ->method('getByPublicHash');
 
         $this->command->execute(['publicHash' => $publicHash]);
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute
      * @expectedException \Exception
      * @expectedExceptionMessage No available payment tokens
      */
@@ -161,27 +162,23 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
         $publicHash = '3wv2m24d2er3';
         $customerId = 1;
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPublicHash')
+        $this->subjectReader->method('readPublicHash')
             ->willReturn($publicHash);
 
-        $this->subjectReader->expects(static::once())
-            ->method('readCustomerId')
+        $this->subjectReader->method('readCustomerId')
             ->willReturn($customerId);
 
         $exception = new \Exception('No available payment tokens');
-        $this->tokenManagement->expects(static::once())
-            ->method('getByPublicHash')
+        $this->tokenManagement->method('getByPublicHash')
             ->willThrowException($exception);
 
-        $this->paymentToken->expects(static::never())
+        $this->paymentToken->expects(self::never())
             ->method('getGatewayToken');
 
         $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute
      * @expectedException \Exception
      * @expectedExceptionMessage Payment method nonce can't be retrieved.
      */
@@ -191,52 +188,41 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
         $customerId = 1;
         $token = 'jd2vnq';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPublicHash')
+        $this->subjectReader->method('readPublicHash')
             ->willReturn($publicHash);
 
-        $this->subjectReader->expects(static::once())
-            ->method('readCustomerId')
+        $this->subjectReader->method('readCustomerId')
             ->willReturn($customerId);
 
-        $this->tokenManagement->expects(static::once())
-            ->method('getByPublicHash')
+        $this->tokenManagement->method('getByPublicHash')
             ->with($publicHash, $customerId)
             ->willReturn($this->paymentToken);
 
-        $this->paymentToken->expects(static::once())
-            ->method('getGatewayToken')
+        $this->paymentToken->method('getGatewayToken')
             ->willReturn($token);
 
         $obj = new \stdClass();
         $obj->success = false;
-        $this->adapter->expects(static::once())
-            ->method('createNonce')
+        $this->adapter->method('createNonce')
             ->with($token)
             ->willReturn($obj);
 
-        $this->responseValidator->expects(static::once())
-            ->method('validate')
+        $this->responseValidator->method('validate')
             ->with(['response' => ['object' => $obj]])
             ->willReturn($this->validationResult);
 
-        $this->validationResult->expects(static::once())
-            ->method('isValid')
+        $this->validationResult->method('isValid')
             ->willReturn(false);
 
-        $this->validationResult->expects(static::once())
-            ->method('getFailsDescription')
+        $this->validationResult->method('getFailsDescription')
             ->willReturn(['Payment method nonce can\'t be retrieved.']);
 
-        $this->resultFactory->expects(static::never())
+        $this->resultFactory->expects(self::never())
             ->method('create');
 
         $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute
-     */
     public function testExecute()
     {
         $publicHash = '3wv2m24d2er3';
@@ -244,57 +230,48 @@ class GetPaymentNonceCommandTest extends \PHPUnit\Framework\TestCase
         $token = 'jd2vnq';
         $nonce = 's1dj23';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPublicHash')
+        $this->subjectReader->method('readPublicHash')
             ->willReturn($publicHash);
 
-        $this->subjectReader->expects(static::once())
-            ->method('readCustomerId')
+        $this->subjectReader->method('readCustomerId')
             ->willReturn($customerId);
 
-        $this->tokenManagement->expects(static::once())
-            ->method('getByPublicHash')
+        $this->tokenManagement->method('getByPublicHash')
             ->with($publicHash, $customerId)
             ->willReturn($this->paymentToken);
 
-        $this->paymentToken->expects(static::once())
-            ->method('getGatewayToken')
+        $this->paymentToken->method('getGatewayToken')
             ->willReturn($token);
 
         $obj = new \stdClass();
         $obj->success = true;
         $obj->paymentMethodNonce = new \stdClass();
         $obj->paymentMethodNonce->nonce = $nonce;
-        $this->adapter->expects(static::once())
-            ->method('createNonce')
+        $this->adapter->method('createNonce')
             ->with($token)
             ->willReturn($obj);
 
-        $this->responseValidator->expects(static::once())
-            ->method('validate')
+        $this->responseValidator->method('validate')
             ->with(['response' => ['object' => $obj]])
             ->willReturn($this->validationResult);
 
-        $this->validationResult->expects(static::once())
-            ->method('isValid')
+        $this->validationResult->method('isValid')
             ->willReturn(true);
 
-        $this->validationResult->expects(static::never())
+        $this->validationResult->expects(self::never())
             ->method('getFailsDescription');
 
         $expected = $this->getMockBuilder(ArrayResult::class)
             ->disableOriginalConstructor()
             ->setMethods(['get'])
             ->getMock();
-        $expected->expects(static::once())
-            ->method('get')
+        $expected->method('get')
             ->willReturn(['paymentMethodNonce' => $nonce]);
-        $this->resultFactory->expects(static::once())
-            ->method('create')
+        $this->resultFactory->method('create')
             ->willReturn($expected);
 
         $actual = $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
-        static::assertEquals($expected, $actual);
-        static::assertEquals($nonce, $actual->get()['paymentMethodNonce']);
+        self::assertEquals($expected, $actual);
+        self::assertEquals($nonce, $actual->get()['paymentMethodNonce']);
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Config/CanVoidHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Config/CanVoidHandlerTest.php
index 793700ab1971f221274de7c1fe3c59024c91482b..bb258f27455a486b7893de49e09b29cb01834452 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Config/CanVoidHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Config/CanVoidHandlerTest.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Config;
 
 use Magento\Braintree\Gateway\Config\CanVoidHandler;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Payment\Model\InfoInterface;
 use Magento\Sales\Model\Order\Payment;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php
index b2207563b8b0fe0fbcf9d3f85b42441395c38a0f..21b8a13be6bed53c01ae02fff4b7eaa7f91ad6d1 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Test\Unit\Gateway\Helper;
 
 use Braintree\Transaction;
 use InvalidArgumentException;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 /**
  * Class SubjectReaderTest
@@ -25,7 +25,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readCustomerId
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId
      * @expectedException InvalidArgumentException
      * @expectedExceptionMessage The "customerId" field does not exists
      */
@@ -35,7 +35,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readCustomerId
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId
      */
     public function testReadCustomerId()
     {
@@ -44,7 +44,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readPublicHash
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash
      * @expectedException InvalidArgumentException
      * @expectedExceptionMessage The "public_hash" field does not exists
      */
@@ -54,7 +54,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readPublicHash
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash
      */
     public function testReadPublicHash()
     {
@@ -63,7 +63,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readPayPal
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal
      * @expectedException \InvalidArgumentException
      * @expectedExceptionMessage Transaction has't paypal attribute
      */
@@ -76,7 +76,7 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Helper\SubjectReader::readPayPal
+     * @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal
      */
     public function testReadPayPal()
     {
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
index 5cbcfef8b6b9e3ee5a89ccc93c9fe14f0e25a126..48889f1efd2e512574b2a3992c98a909b5cdd929 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
@@ -7,8 +7,10 @@ namespace Magento\Braintree\Test\Unit\Gateway\Http\Client;
 
 use Magento\Braintree\Gateway\Http\Client\TransactionSale;
 use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Payment\Gateway\Http\TransferInterface;
 use Magento\Payment\Model\Method\Logger;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -22,35 +24,41 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
     private $model;
 
     /**
-     * @var Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var Logger|MockObject
      */
-    private $loggerMock;
+    private $logger;
 
     /**
-     * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapter|MockObject
      */
     private $adapter;
 
     /**
-     * Set up
-     *
-     * @return void
+     * @inheritdoc
      */
     protected function setUp()
     {
-        $criticalLoggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
-        $this->loggerMock = $this->getMockBuilder(Logger::class)
+        /** @var LoggerInterface|MockObject $criticalLogger */
+        $criticalLogger = $this->getMockForAbstractClass(LoggerInterface::class);
+        $this->logger = $this->getMockBuilder(Logger::class)
             ->disableOriginalConstructor()
             ->getMock();
+
         $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
             ->disableOriginalConstructor()
             ->getMock();
+        /** @var BraintreeAdapterFactory|MockObject $adapterFactory */
+        $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adapterFactory->method('create')
+            ->willReturn($this->adapter);
 
-        $this->model = new TransactionSale($criticalLoggerMock, $this->loggerMock, $this->adapter);
+        $this->model = new TransactionSale($criticalLogger, $this->logger, $adapterFactory);
     }
 
     /**
-     * Run test placeRequest method (exception)
+     * Runs test placeRequest method (exception)
      *
      * @return void
      *
@@ -59,8 +67,7 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
      */
     public function testPlaceRequestException()
     {
-        $this->loggerMock->expects($this->once())
-            ->method('debug')
+        $this->logger->method('debug')
             ->with(
                 [
                     'request' => $this->getTransferData(),
@@ -69,11 +76,10 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
                 ]
             );
 
-        $this->adapter->expects($this->once())
-            ->method('sale')
+        $this->adapter->method('sale')
             ->willThrowException(new \Exception('Test messages'));
 
-        /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
+        /** @var TransferInterface|MockObject $transferObjectMock */
         $transferObjectMock = $this->getTransferObjectMock();
 
         $this->model->placeRequest($transferObjectMock);
@@ -87,14 +93,11 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
     public function testPlaceRequestSuccess()
     {
         $response = $this->getResponseObject();
-        $this->adapter->expects($this->once())
-            ->method('sale')
+        $this->adapter->method('sale')
             ->with($this->getTransferData())
-            ->willReturn($response)
-        ;
+            ->willReturn($response);
 
-        $this->loggerMock->expects($this->once())
-            ->method('debug')
+        $this->logger->method('debug')
             ->with(
                 [
                     'request' => $this->getTransferData(),
@@ -110,19 +113,22 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * @return TransferInterface|\PHPUnit_Framework_MockObject_MockObject
+     * Creates mock object for TransferInterface.
+     *
+     * @return TransferInterface|MockObject
      */
     private function getTransferObjectMock()
     {
         $transferObjectMock = $this->createMock(TransferInterface::class);
-        $transferObjectMock->expects($this->once())
-            ->method('getBody')
+        $transferObjectMock->method('getBody')
             ->willReturn($this->getTransferData());
 
         return $transferObjectMock;
     }
 
     /**
+     * Creates stub for a response.
+     *
      * @return \stdClass
      */
     private function getResponseObject()
@@ -134,6 +140,8 @@ class TransactionSaleTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
+     * Creates stub request data.
+     *
      * @return array
      */
     private function getTransferData()
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php
index 86113c34ba218d05d3e561ffbc3514b833f4ea81..09b0efc58f3fbba82d25e87552cd3beba23c6af6 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php
@@ -8,8 +8,10 @@ namespace Magento\Braintree\Test\Unit\Gateway\Http\Client;
 use Braintree\Result\Successful;
 use Magento\Braintree\Gateway\Http\Client\TransactionSubmitForSettlement;
 use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Payment\Gateway\Http\TransferInterface;
 use Magento\Payment\Model\Method\Logger;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -23,76 +25,79 @@ class TransactionSubmitForSettlementTest extends \PHPUnit\Framework\TestCase
     private $client;
 
     /**
-     * @var Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var Logger|MockObject
      */
     private $logger;
 
     /**
-     * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapter|MockObject
      */
     private $adapter;
 
     protected function setUp()
     {
-        $criticalLoggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
+        /** @var LoggerInterface|MockObject $criticalLogger */
+        $criticalLogger = $this->getMockForAbstractClass(LoggerInterface::class);
         $this->logger = $this->getMockBuilder(Logger::class)
             ->disableOriginalConstructor()
             ->setMethods(['debug'])
             ->getMock();
+
         $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
             ->disableOriginalConstructor()
             ->setMethods(['submitForSettlement'])
             ->getMock();
+        /** @var BraintreeAdapterFactory|MockObject $adapterFactory */
+        $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adapterFactory->method('create')
+            ->willReturn($this->adapter);
 
         $this->client = new TransactionSubmitForSettlement(
-            $criticalLoggerMock,
+            $criticalLogger,
             $this->logger,
-            $this->adapter
+            $adapterFactory
         );
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Http\Client\TransactionSubmitForSettlement::placeRequest
      * @expectedException \Magento\Payment\Gateway\Http\ClientException
      * @expectedExceptionMessage Transaction has been declined
      */
     public function testPlaceRequestWithException()
     {
         $exception = new \Exception('Transaction has been declined');
-        $this->adapter->expects(static::once())
-            ->method('submitForSettlement')
+        $this->adapter->method('submitForSettlement')
             ->willThrowException($exception);
 
-        /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
-        $transferObjectMock = $this->getTransferObjectMock();
-        $this->client->placeRequest($transferObjectMock);
+        /** @var TransferInterface|MockObject $transferObject */
+        $transferObject = $this->getTransferObjectMock();
+        $this->client->placeRequest($transferObject);
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Http\Client\TransactionSubmitForSettlement::process
-     */
     public function testPlaceRequest()
     {
         $data = new Successful(['success'], [true]);
-        $this->adapter->expects(static::once())
-            ->method('submitForSettlement')
+        $this->adapter->method('submitForSettlement')
             ->willReturn($data);
 
-        /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
-        $transferObjectMock = $this->getTransferObjectMock();
-        $response = $this->client->placeRequest($transferObjectMock);
+        /** @var TransferInterface|MockObject $transferObject */
+        $transferObject = $this->getTransferObjectMock();
+        $response = $this->client->placeRequest($transferObject);
         static::assertTrue(is_object($response['object']));
         static::assertEquals(['object' => $data], $response);
     }
 
     /**
-     * @return TransferInterface|\PHPUnit_Framework_MockObject_MockObject
+     * Creates mock for TransferInterface
+     *
+     * @return TransferInterface|MockObject
      */
     private function getTransferObjectMock()
     {
         $mock = $this->createMock(TransferInterface::class);
-        $mock->expects($this->once())
-            ->method('getBody')
+        $mock->method('getBody')
             ->willReturn([
                 'transaction_id' => 'vb4c6b',
                 'amount' => 124.00
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/AddressDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
index 3f05aed45da6057b3a81998306caef97582e8954..702b3254e3085d694b63d5321efa41bb357a60d6 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
@@ -5,11 +5,12 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\AddressDataBuilder;
-use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
-use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Payment\Gateway\Data\AddressAdapterInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class AddressDataBuilderTest
@@ -17,34 +18,26 @@ use Magento\Braintree\Gateway\Helper\SubjectReader;
 class AddressDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
     /**
-     * @var PaymentDataObjectInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentDataObjectInterface|MockObject
      */
-    private $paymentDOMock;
+    private $paymentDO;
 
     /**
-     * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var OrderAdapterInterface|MockObject
      */
-    private $orderMock;
+    private $order;
 
     /**
      * @var AddressDataBuilder
      */
     private $builder;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReaderMock;
-
     protected function setUp()
     {
-        $this->paymentDOMock = $this->createMock(PaymentDataObjectInterface::class);
-        $this->orderMock = $this->createMock(OrderAdapterInterface::class);
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->getMock();
+        $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
+        $this->order = $this->createMock(OrderAdapterInterface::class);
 
-        $this->builder = new AddressDataBuilder($this->subjectReaderMock);
+        $this->builder = new AddressDataBuilder(new SubjectReader());
     }
 
     /**
@@ -56,37 +49,24 @@ class AddressDataBuilderTest extends \PHPUnit\Framework\TestCase
             'payment' => null,
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
-
         $this->builder->build($buildSubject);
     }
 
     public function testBuildNoAddresses()
     {
-        $this->paymentDOMock->expects(static::once())
-            ->method('getOrder')
-            ->willReturn($this->orderMock);
+        $this->paymentDO->method('getOrder')
+            ->willReturn($this->order);
 
-        $this->orderMock->expects(static::once())
-            ->method('getShippingAddress')
+        $this->order->method('getShippingAddress')
             ->willReturn(null);
-        $this->orderMock->expects(static::once())
-            ->method('getBillingAddress')
+        $this->order->method('getBillingAddress')
             ->willReturn(null);
 
         $buildSubject = [
-            'payment' => $this->paymentDOMock,
+            'payment' => $this->paymentDO,
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDOMock);
-
-        static::assertEquals([], $this->builder->build($buildSubject));
+        self::assertEquals([], $this->builder->build($buildSubject));
     }
 
     /**
@@ -97,28 +77,20 @@ class AddressDataBuilderTest extends \PHPUnit\Framework\TestCase
      */
     public function testBuild($addressData, $expectedResult)
     {
-        $addressMock = $this->getAddressMock($addressData);
+        $address = $this->getAddressMock($addressData);
 
-        $this->paymentDOMock->expects(static::once())
-            ->method('getOrder')
-            ->willReturn($this->orderMock);
+        $this->paymentDO->method('getOrder')
+            ->willReturn($this->order);
 
-        $this->orderMock->expects(static::once())
-            ->method('getShippingAddress')
-            ->willReturn($addressMock);
-        $this->orderMock->expects(static::once())
-            ->method('getBillingAddress')
-            ->willReturn($addressMock);
+        $this->order->method('getShippingAddress')
+            ->willReturn($address);
+        $this->order->method('getBillingAddress')
+            ->willReturn($address);
 
         $buildSubject = [
-            'payment' => $this->paymentDOMock,
+            'payment' => $this->paymentDO,
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDOMock);
-
         self::assertEquals($expectedResult, $this->builder->build($buildSubject));
     }
 
@@ -171,37 +143,37 @@ class AddressDataBuilderTest extends \PHPUnit\Framework\TestCase
 
     /**
      * @param array $addressData
-     * @return AddressAdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @return AddressAdapterInterface|MockObject
      */
     private function getAddressMock($addressData)
     {
         $addressMock = $this->createMock(AddressAdapterInterface::class);
 
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getFirstname')
             ->willReturn($addressData['first_name']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getLastname')
             ->willReturn($addressData['last_name']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getCompany')
             ->willReturn($addressData['company']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getStreetLine1')
             ->willReturn($addressData['street_1']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getStreetLine2')
             ->willReturn($addressData['street_2']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getCity')
             ->willReturn($addressData['city']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getRegionCode')
             ->willReturn($addressData['region_code']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getPostcode')
             ->willReturn($addressData['post_code']);
-        $addressMock->expects(static::exactly(2))
+        $addressMock->expects(self::exactly(2))
             ->method('getCountryId')
             ->willReturn($addressData['country_id']);
 
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php
index 9799b6f18c639aa7cc14ed879d78d90999ef1fcf..b42b1162b3d70c1d1bd4edd4d392a56b1915ded6 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php
@@ -8,7 +8,8 @@ namespace Magento\Braintree\Test\Unit\Gateway\Request;
 use Magento\Braintree\Gateway\Request\CaptureDataBuilder;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Model\Order\Payment;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class CaptureDataBuilderTest
@@ -21,35 +22,26 @@ class CaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
     private $builder;
 
     /**
-     * @var Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var Payment|MockObject
      */
     private $payment;
 
     /**
-     * @var \Magento\Sales\Model\Order\Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Sales\Model\Order\Payment|MockObject
      */
     private $paymentDO;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReaderMock;
-
     protected function setUp()
     {
         $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
         $this->payment = $this->getMockBuilder(Payment::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->getMock();
 
-        $this->builder = new CaptureDataBuilder($this->subjectReaderMock);
+        $this->builder = new CaptureDataBuilder(new SubjectReader());
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Request\CaptureDataBuilder::build
      * @expectedException \Magento\Framework\Exception\LocalizedException
      * @expectedExceptionMessage No authorization transaction to proceed capture.
      */
@@ -61,25 +53,15 @@ class CaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
             'amount' => $amount
         ];
 
-        $this->payment->expects(static::once())
-            ->method('getCcTransId')
+        $this->payment->method('getCcTransId')
             ->willReturn('');
 
-        $this->paymentDO->expects(static::once())
-            ->method('getPayment')
+        $this->paymentDO->method('getPayment')
             ->willReturn($this->payment);
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-
         $this->builder->build($buildSubject);
     }
 
-    /**
-     * @covers \Magento\Braintree\Gateway\Request\CaptureDataBuilder::build
-     */
     public function testBuild()
     {
         $transactionId = 'b3b99d';
@@ -95,23 +77,12 @@ class CaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
             'amount' => $amount
         ];
 
-        $this->payment->expects(static::once())
-            ->method('getCcTransId')
+        $this->payment->method('getCcTransId')
             ->willReturn($transactionId);
 
-        $this->paymentDO->expects(static::once())
-            ->method('getPayment')
+        $this->paymentDO->method('getPayment')
             ->willReturn($this->payment);
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willReturn($amount);
-
-        static::assertEquals($expected, $this->builder->build($buildSubject));
+        self::assertEquals($expected, $this->builder->build($buildSubject));
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
index 0f25b26fd2fa31d755816d192f12fe28bc0b7642..9b5cee30940df990c1363a0bc8c11d316443870d 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
@@ -5,46 +5,36 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\CustomerDataBuilder;
-use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
-use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Payment\Gateway\Data\AddressAdapterInterface;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
-/**
- * Class CustomerDataBuilderTest
- */
 class CustomerDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
     /**
-     * @var PaymentDataObjectInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentDataObjectInterface|MockObject
      */
-    private $paymentDOMock;
+    private $paymentDO;
 
     /**
-     * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var OrderAdapterInterface|MockObject
      */
-    private $orderMock;
+    private $order;
 
     /**
      * @var CustomerDataBuilder
      */
     private $builder;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReaderMock;
-
     protected function setUp()
     {
-        $this->paymentDOMock = $this->createMock(PaymentDataObjectInterface::class);
-        $this->orderMock = $this->createMock(OrderAdapterInterface::class);
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->getMock();
+        $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
+        $this->order = $this->createMock(OrderAdapterInterface::class);
 
-        $this->builder = new CustomerDataBuilder($this->subjectReaderMock);
+        $this->builder = new CustomerDataBuilder(new SubjectReader());
     }
 
     /**
@@ -56,11 +46,6 @@ class CustomerDataBuilderTest extends \PHPUnit\Framework\TestCase
             'payment' => null,
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
-
         $this->builder->build($buildSubject);
     }
 
@@ -74,22 +59,15 @@ class CustomerDataBuilderTest extends \PHPUnit\Framework\TestCase
     {
         $billingMock = $this->getBillingMock($billingData);
 
-        $this->paymentDOMock->expects(static::once())
-            ->method('getOrder')
-            ->willReturn($this->orderMock);
-        $this->orderMock->expects(static::once())
-            ->method('getBillingAddress')
+        $this->paymentDO->method('getOrder')
+            ->willReturn($this->order);
+        $this->order->method('getBillingAddress')
             ->willReturn($billingMock);
 
         $buildSubject = [
-            'payment' => $this->paymentDOMock,
+            'payment' => $this->paymentDO,
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDOMock);
-
         self::assertEquals($expectedResult, $this->builder->build($buildSubject));
     }
 
@@ -122,28 +100,23 @@ class CustomerDataBuilderTest extends \PHPUnit\Framework\TestCase
 
     /**
      * @param array $billingData
-     * @return AddressAdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @return AddressAdapterInterface|MockObject
      */
     private function getBillingMock($billingData)
     {
-        $addressMock = $this->createMock(AddressAdapterInterface::class);
+        $address = $this->createMock(AddressAdapterInterface::class);
 
-        $addressMock->expects(static::once())
-            ->method('getFirstname')
+        $address->method('getFirstname')
             ->willReturn($billingData['first_name']);
-        $addressMock->expects(static::once())
-            ->method('getLastname')
+        $address->method('getLastname')
             ->willReturn($billingData['last_name']);
-        $addressMock->expects(static::once())
-            ->method('getCompany')
+        $address->method('getCompany')
             ->willReturn($billingData['company']);
-        $addressMock->expects(static::once())
-            ->method('getTelephone')
+        $address->method('getTelephone')
             ->willReturn($billingData['phone']);
-        $addressMock->expects(static::once())
-            ->method('getEmail')
+        $address->method('getEmail')
             ->willReturn($billingData['email']);
 
-        return $addressMock;
+        return $address;
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/DescriptorDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/DescriptorDataBuilderTest.php
index 761d88b636ed73733fed97b32a608c63eb27c6b6..eda9121236045e6fd25aca51d862bf368aa051f3 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/DescriptorDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/DescriptorDataBuilderTest.php
@@ -6,12 +6,12 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\DescriptorDataBuilder;
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
-/**
- * Class DescriptorDataBuilderTest
- */
 class DescriptorDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
     /**
@@ -31,22 +31,25 @@ class DescriptorDataBuilderTest extends \PHPUnit\Framework\TestCase
             ->setMethods(['getDynamicDescriptors'])
             ->getMock();
 
-        $this->builder = new DescriptorDataBuilder($this->config);
+        $this->builder = new DescriptorDataBuilder($this->config, new SubjectReader());
     }
 
     /**
-     * @covers \Magento\Braintree\Gateway\Request\DescriptorDataBuilder::build
      * @param array $descriptors
      * @param array $expected
      * @dataProvider buildDataProvider
      */
     public function testBuild(array $descriptors, array $expected)
     {
-        $this->config->expects(static::once())
-            ->method('getDynamicDescriptors')
+        $paymentDO = $this->createMock(PaymentDataObjectInterface::class);
+        $order = $this->createMock(OrderAdapterInterface::class);
+        $paymentDO->method('getOrder')
+            ->willReturn($order);
+
+        $this->config->method('getDynamicDescriptors')
             ->willReturn($descriptors);
 
-        $actual = $this->builder->build([]);
+        $actual = $this->builder->build(['payment' => $paymentDO]);
         static::assertEquals($expected, $actual);
     }
 
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php
index ee0907a1ddbbbb888f0161c72d378ba38b9baf5e..3737089ed175e6ad01ad559a4c26cabc26ddc5d1 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php
@@ -5,12 +5,14 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
+use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Sales\Model\Order\Payment;
 use Magento\Braintree\Gateway\Config\Config;
 use Magento\Braintree\Observer\DataAssignObserver;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Braintree\Gateway\Request\KountPaymentDataBuilder;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class KountPaymentDataBuilderTest
@@ -27,39 +29,31 @@ class KountPaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
     private $builder;
 
     /**
-     * @var Config|\PHPUnit_Framework_MockObject_MockObject
+     * @var Config|MockObject
      */
-    private $configMock;
+    private $config;
 
     /**
-     * @var Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var Payment|MockObject
      */
-    private $paymentMock;
+    private $payment;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var MockObject
      */
     private $paymentDO;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReaderMock;
-
     protected function setUp()
     {
         $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
-        $this->configMock = $this->getMockBuilder(Config::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->paymentMock = $this->getMockBuilder(Payment::class)
+        $this->config = $this->getMockBuilder(Config::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+        $this->payment = $this->getMockBuilder(Payment::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->builder = new KountPaymentDataBuilder($this->configMock, $this->subjectReaderMock);
+        $this->builder = new KountPaymentDataBuilder($this->config, new SubjectReader());
     }
 
     /**
@@ -69,15 +63,9 @@ class KountPaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
     {
         $buildSubject = [];
 
-        $this->configMock->expects(static::once())
-            ->method('hasFraudProtection')
+        $this->config->method('hasFraudProtection')
             ->willReturn(true);
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
-
         $this->builder->build($buildSubject);
     }
 
@@ -91,26 +79,23 @@ class KountPaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
             KountPaymentDataBuilder::DEVICE_DATA => self::DEVICE_DATA,
         ];
 
+        $order = $this->createMock(OrderAdapterInterface::class);
+        $this->paymentDO->method('getOrder')
+            ->willReturn($order);
+
         $buildSubject = ['payment' => $this->paymentDO];
 
-        $this->paymentMock->expects(static::exactly(count($additionalData)))
+        $this->payment->expects(self::exactly(count($additionalData)))
             ->method('getAdditionalInformation')
             ->willReturn($additionalData);
 
-        $this->configMock->expects(static::once())
-            ->method('hasFraudProtection')
+        $this->config->method('hasFraudProtection')
             ->willReturn(true);
 
-        $this->paymentDO->expects(static::once())
-            ->method('getPayment')
-            ->willReturn($this->paymentMock);
-
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
+        $this->paymentDO->method('getPayment')
+            ->willReturn($this->payment);
 
-        static::assertEquals(
+        self::assertEquals(
             $expectedResult,
             $this->builder->build($buildSubject)
         );
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php
index fba65354d60959814cc2700ee8788c2afb4b332d..b363f2bcac673036452d92d4319a29f8683c65e6 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request\PayPal;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\PayPal\DeviceDataBuilder;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Payment\Model\InfoInterface;
@@ -16,15 +16,10 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject;
  */
 class DeviceDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
-    /**
-     * @var SubjectReader|MockObject
-     */
-    private $subjectReader;
-
     /**
      * @var PaymentDataObjectInterface|MockObject
      */
-    private $paymentDataObject;
+    private $paymentDO;
 
     /**
      * @var InfoInterface|MockObject
@@ -38,16 +33,10 @@ class DeviceDataBuilderTest extends \PHPUnit\Framework\TestCase
 
     protected function setUp()
     {
-        $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->setMethods(['readPayment'])
-            ->getMock();
-
-        $this->paymentDataObject = $this->createMock(PaymentDataObjectInterface::class);
-
+        $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
         $this->paymentInfo = $this->createMock(InfoInterface::class);
         
-        $this->builder = new DeviceDataBuilder($this->subjectReader);
+        $this->builder = new DeviceDataBuilder(new SubjectReader());
     }
 
     /**
@@ -59,24 +48,17 @@ class DeviceDataBuilderTest extends \PHPUnit\Framework\TestCase
     public function testBuild(array $paymentData, array $expected)
     {
         $subject = [
-            'payment' => $this->paymentDataObject
+            'payment' => $this->paymentDO
         ];
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPayment')
-            ->with($subject)
-            ->willReturn($this->paymentDataObject);
-
-        $this->paymentDataObject->expects(static::once())
-            ->method('getPayment')
+        $this->paymentDO->method('getPayment')
             ->willReturn($this->paymentInfo);
 
-        $this->paymentInfo->expects(static::once())
-            ->method('getAdditionalInformation')
+        $this->paymentInfo->method('getAdditionalInformation')
             ->willReturn($paymentData);
 
         $actual = $this->builder->build($subject);
-        static::assertEquals($expected, $actual);
+        self::assertEquals($expected, $actual);
     }
 
     /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php
index 8e83254727bf795c20a2bd49ab864e4a60f46991..10a96734b849aa79df526554609a1705153426d7 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request\PayPal;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\PayPal\VaultDataBuilder;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Payment\Model\InfoInterface;
@@ -17,15 +17,10 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject;
  */
 class VaultDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
-    /**
-     * @var SubjectReader|MockObject
-     */
-    private $subjectReader;
-
     /**
      * @var PaymentDataObjectInterface|MockObject
      */
-    private $paymentDataObject;
+    private $paymentDO;
 
     /**
      * @var InfoInterface|MockObject
@@ -39,16 +34,11 @@ class VaultDataBuilderTest extends \PHPUnit\Framework\TestCase
 
     protected function setUp()
     {
-        $this->paymentDataObject = $this->createMock(PaymentDataObjectInterface::class);
+        $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
 
         $this->paymentInfo = $this->createMock(InfoInterface::class);
 
-        $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->setMethods(['readPayment'])
-            ->getMock();
-
-        $this->builder = new VaultDataBuilder($this->subjectReader);
+        $this->builder = new VaultDataBuilder(new SubjectReader());
     }
 
     /**
@@ -60,24 +50,17 @@ class VaultDataBuilderTest extends \PHPUnit\Framework\TestCase
     public function testBuild(array $additionalInfo, array $expected)
     {
         $subject = [
-            'payment' => $this->paymentDataObject
+            'payment' => $this->paymentDO
         ];
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPayment')
-            ->with($subject)
-            ->willReturn($this->paymentDataObject);
-
-        $this->paymentDataObject->expects(static::once())
-            ->method('getPayment')
+        $this->paymentDO->method('getPayment')
             ->willReturn($this->paymentInfo);
 
-        $this->paymentInfo->expects(static::once())
-            ->method('getAdditionalInformation')
+        $this->paymentInfo->method('getAdditionalInformation')
             ->willReturn($additionalInfo);
 
         $actual = $this->builder->build($subject);
-        static::assertEquals($expected, $actual);
+        self::assertEquals($expected, $actual);
     }
 
     /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
index 12c613b8f216bbaf7e69d91739cecdd92894a37e..16f11559f73cc311c687da2b2ecc171658ec6883 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
@@ -6,12 +6,13 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\PaymentDataBuilder;
 use Magento\Braintree\Observer\DataAssignObserver;
 use Magento\Payment\Gateway\Data\OrderAdapterInterface;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Model\Order\Payment;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class PaymentDataBuilderTest
@@ -29,45 +30,37 @@ class PaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
     private $builder;
 
     /**
-     * @var Config|\PHPUnit_Framework_MockObject_MockObject
+     * @var Config|MockObject
      */
-    private $configMock;
+    private $config;
 
     /**
-     * @var Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var Payment|MockObject
      */
-    private $paymentMock;
+    private $payment;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var MockObject
      */
     private $paymentDO;
 
     /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+     * @var OrderAdapterInterface|MockObject
      */
-    private $subjectReaderMock;
-
-    /**
-     * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $orderMock;
+    private $order;
 
     protected function setUp()
     {
         $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
-        $this->configMock = $this->getMockBuilder(Config::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->paymentMock = $this->getMockBuilder(Payment::class)
+        $this->config = $this->getMockBuilder(Config::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+        $this->payment = $this->getMockBuilder(Payment::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->orderMock = $this->createMock(OrderAdapterInterface::class);
+        $this->order = $this->createMock(OrderAdapterInterface::class);
 
-        $this->builder = new PaymentDataBuilder($this->configMock, $this->subjectReaderMock);
+        $this->builder = new PaymentDataBuilder($this->config, new SubjectReader());
     }
 
     /**
@@ -77,11 +70,6 @@ class PaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
     {
         $buildSubject = [];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
-
         $this->builder->build($buildSubject);
     }
 
@@ -95,15 +83,6 @@ class PaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
             'amount' => null
         ];
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
-
         $this->builder->build($buildSubject);
     }
 
@@ -128,36 +107,23 @@ class PaymentDataBuilderTest extends \PHPUnit\Framework\TestCase
             'amount' => 10.00
         ];
 
-        $this->paymentMock->expects(static::exactly(count($additionalData)))
+        $this->payment->expects(self::exactly(count($additionalData)))
             ->method('getAdditionalInformation')
             ->willReturnMap($additionalData);
 
-        $this->configMock->expects(static::once())
-            ->method('getMerchantAccountId')
+        $this->config->method('getMerchantAccountId')
             ->willReturn(self::MERCHANT_ACCOUNT_ID);
 
-        $this->paymentDO->expects(static::once())
-            ->method('getPayment')
-            ->willReturn($this->paymentMock);
-
-        $this->paymentDO->expects(static::once())
-            ->method('getOrder')
-            ->willReturn($this->orderMock);
-
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willReturn(10.00);
-
-        $this->orderMock->expects(static::once())
-            ->method('getOrderIncrementId')
+        $this->paymentDO->method('getPayment')
+            ->willReturn($this->payment);
+
+        $this->paymentDO->method('getOrder')
+            ->willReturn($this->order);
+
+        $this->order->method('getOrderIncrementId')
             ->willReturn('000000101');
 
-        static::assertEquals(
+        self::assertEquals(
             $expectedResult,
             $this->builder->build($buildSubject)
         );
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php
index 5aa383d095a1e34481cdf5d4876ae675b5104131..ff4b2f4545fa66b908b341fb4e0159cdf88cd907 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\PaymentDataBuilder;
 use Magento\Braintree\Gateway\Request\RefundDataBuilder;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
@@ -14,11 +14,6 @@ use Magento\Sales\Model\Order\Payment;
 
 class RefundDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
-    /**
-     * @var SubjectReader | \PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReader;
-
     /**
      * @var RefundDataBuilder
      */
@@ -26,41 +21,25 @@ class RefundDataBuilderTest extends \PHPUnit\Framework\TestCase
 
     public function setUp()
     {
-        $this->subjectReader = $this->getMockBuilder(
-            SubjectReader::class
-        )->disableOriginalConstructor()
-            ->getMock();
-
-        $this->dataBuilder = new RefundDataBuilder($this->subjectReader);
+        $this->dataBuilder = new RefundDataBuilder(new SubjectReader());
     }
 
     public function testBuild()
     {
         $paymentDO = $this->createMock(PaymentDataObjectInterface::class);
-        $paymentModel = $this->getMockBuilder(
-            Payment::class
-        )->disableOriginalConstructor()
+        $paymentModel = $this->getMockBuilder(Payment::class)
+            ->disableOriginalConstructor()
             ->getMock();
 
         $buildSubject = ['payment' => $paymentDO, 'amount' => 12.358];
         $transactionId = 'xsd7n';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($paymentDO);
-        $paymentDO->expects(static::once())
-            ->method('getPayment')
+        $paymentDO->method('getPayment')
             ->willReturn($paymentModel);
-        $paymentModel->expects(static::once())
-            ->method('getParentTransactionId')
+        $paymentModel->method('getParentTransactionId')
             ->willReturn($transactionId);
-        $this->subjectReader->expects(static::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willReturn($buildSubject['amount']);
 
-        static::assertEquals(
+        self::assertEquals(
             [
                 'transaction_id' => $transactionId,
                 PaymentDataBuilder::AMOUNT => '12.36'
@@ -72,30 +51,19 @@ class RefundDataBuilderTest extends \PHPUnit\Framework\TestCase
     public function testBuildNullAmount()
     {
         $paymentDO = $this->createMock(PaymentDataObjectInterface::class);
-        $paymentModel = $this->getMockBuilder(
-            Payment::class
-        )->disableOriginalConstructor()
+        $paymentModel = $this->getMockBuilder(Payment::class)
+            ->disableOriginalConstructor()
             ->getMock();
 
         $buildSubject = ['payment' => $paymentDO];
         $transactionId = 'xsd7n';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($paymentDO);
-        $paymentDO->expects(static::once())
-            ->method('getPayment')
+        $paymentDO->method('getPayment')
             ->willReturn($paymentModel);
-        $paymentModel->expects(static::once())
-            ->method('getParentTransactionId')
+        $paymentModel->method('getParentTransactionId')
             ->willReturn($transactionId);
-        $this->subjectReader->expects(static::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
 
-        static::assertEquals(
+        self::assertEquals(
             [
                 'transaction_id' => $transactionId,
                 PaymentDataBuilder::AMOUNT => null
@@ -107,31 +75,20 @@ class RefundDataBuilderTest extends \PHPUnit\Framework\TestCase
     public function testBuildCutOffLegacyTransactionIdPostfix()
     {
         $paymentDO = $this->createMock(PaymentDataObjectInterface::class);
-        $paymentModel = $this->getMockBuilder(
-            Payment::class
-        )->disableOriginalConstructor()
+        $paymentModel = $this->getMockBuilder(Payment::class)
+            ->disableOriginalConstructor()
             ->getMock();
 
         $buildSubject = ['payment' => $paymentDO];
         $legacyTxnId = 'xsd7n-' . TransactionInterface::TYPE_CAPTURE;
         $transactionId = 'xsd7n';
 
-        $this->subjectReader->expects(static::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($paymentDO);
-        $paymentDO->expects(static::once())
-            ->method('getPayment')
+        $paymentDO->method('getPayment')
             ->willReturn($paymentModel);
-        $paymentModel->expects(static::once())
-            ->method('getParentTransactionId')
+        $paymentModel->method('getParentTransactionId')
             ->willReturn($legacyTxnId);
-        $this->subjectReader->expects(static::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willThrowException(new \InvalidArgumentException());
 
-        static::assertEquals(
+        self::assertEquals(
             [
                 'transaction_id' => $transactionId,
                 PaymentDataBuilder::AMOUNT => null
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/SettlementDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/SettlementDataBuilderTest.php
index 2f8f9542437495a30ebc886fa9a9040730af36c2..beccad6e9a045de1f18d1fb714e26c4e0293f3c3 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/SettlementDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/SettlementDataBuilderTest.php
@@ -11,7 +11,7 @@ class SettlementDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
     public function testBuild()
     {
-        $this->assertEquals(
+        self::assertEquals(
             [
                 'options' => [
                     SettlementDataBuilder::SUBMIT_FOR_SETTLEMENT => true
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php
index c28ac0c3ac3722aa75ed33703a6fd9262900cc30..e2bcc2c3b39679f039748ca07821a70ecf8d0e05 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php
@@ -6,68 +6,63 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
 use Magento\Braintree\Gateway\Config\Config;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder;
-use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
-use Magento\Payment\Gateway\Data\Order\OrderAdapter;
 use Magento\Payment\Gateway\Data\Order\AddressAdapter;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Payment\Gateway\Data\Order\OrderAdapter;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class ThreeDSecureDataBuilderTest
  */
 class ThreeDSecureDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
+    /**
+     * @var int
+     */
+    private static $storeId = 1;
+
     /**
      * @var ThreeDSecureDataBuilder
      */
     private $builder;
 
     /**
-     * @var Config|\PHPUnit_Framework_MockObject_MockObject
+     * @var Config|MockObject
      */
-    private $configMock;
+    private $config;
 
     /**
-     * @var PaymentDataObjectInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentDataObjectInterface|MockObject
      */
     private $paymentDO;
 
     /**
-     * @var OrderAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var OrderAdapter|MockObject
      */
     private $order;
 
     /**
-     * @var \Magento\Payment\Gateway\Data\Order\AddressAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var AddressAdapter|MockObject
      */
     private $billingAddress;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReaderMock;
-
     protected function setUp()
     {
         $this->initOrderMock();
 
         $this->paymentDO = $this->getMockBuilder(PaymentDataObjectInterface::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getOrder', 'getPayment'])
             ->getMock();
-        $this->paymentDO->expects(static::once())
-            ->method('getOrder')
+        $this->paymentDO->method('getOrder')
             ->willReturn($this->order);
 
-        $this->configMock = $this->getMockBuilder(Config::class)
-            ->setMethods(['isVerify3DSecure', 'getThresholdAmount', 'get3DSecureSpecificCountries'])
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+        $this->config = $this->getMockBuilder(Config::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->builder = new ThreeDSecureDataBuilder($this->configMock, $this->subjectReaderMock);
+        $this->builder = new ThreeDSecureDataBuilder($this->config, new SubjectReader());
     }
 
     /**
@@ -76,7 +71,6 @@ class ThreeDSecureDataBuilderTest extends \PHPUnit\Framework\TestCase
      * @param string $countryId
      * @param array $countries
      * @param array $expected
-     * @covers \Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder::build
      * @dataProvider buildDataProvider
      */
     public function testBuild($verify, $thresholdAmount, $countryId, array $countries, array $expected)
@@ -86,37 +80,28 @@ class ThreeDSecureDataBuilderTest extends \PHPUnit\Framework\TestCase
             'amount' => 25
         ];
 
-        $this->configMock->expects(static::once())
-            ->method('isVerify3DSecure')
+        $this->config->method('isVerify3DSecure')
+            ->with(self::equalTo(self::$storeId))
             ->willReturn($verify);
 
-        $this->configMock->expects(static::any())
-            ->method('getThresholdAmount')
+        $this->config->method('getThresholdAmount')
+            ->with(self::equalTo(self::$storeId))
             ->willReturn($thresholdAmount);
 
-        $this->configMock->expects(static::any())
-            ->method('get3DSecureSpecificCountries')
+        $this->config->method('get3DSecureSpecificCountries')
+            ->with(self::equalTo(self::$storeId))
             ->willReturn($countries);
 
-        $this->billingAddress->expects(static::any())
-            ->method('getCountryId')
+        $this->billingAddress->method('getCountryId')
             ->willReturn($countryId);
 
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-        $this->subjectReaderMock->expects(self::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willReturn(25);
-
         $result = $this->builder->build($buildSubject);
-        static::assertEquals($expected, $result);
+        self::assertEquals($expected, $result);
     }
 
     /**
-     * Get list of variations for build test
+     * Gets list of variations to build request data.
+     *
      * @return array
      */
     public function buildDataProvider()
@@ -144,22 +129,21 @@ class ThreeDSecureDataBuilderTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * Create mock object for order adapter
+     * Creates mock object for order adapter.
      */
     private function initOrderMock()
     {
         $this->billingAddress = $this->getMockBuilder(AddressAdapter::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getCountryId'])
             ->getMock();
 
         $this->order = $this->getMockBuilder(OrderAdapter::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getBillingAddress'])
             ->getMock();
 
-        $this->order->expects(static::any())
-            ->method('getBillingAddress')
+        $this->order->method('getBillingAddress')
             ->willReturn($this->billingAddress);
+        $this->order->method('getStoreId')
+            ->willReturn(self::$storeId);
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultCaptureDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultCaptureDataBuilderTest.php
index df11938ddba7047728c710be96f1ca0488b5b794..5af050002eb2debeefe73426f2638d450c5626d4 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultCaptureDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultCaptureDataBuilderTest.php
@@ -5,12 +5,13 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Request;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Api\Data\OrderPaymentExtension;
 use Magento\Sales\Model\Order\Payment;
 use Magento\Vault\Model\PaymentToken;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 class VaultCaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
 {
@@ -20,35 +21,25 @@ class VaultCaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
     private $builder;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var PaymentDataObjectInterface|MockObject
      */
     private $paymentDO;
 
     /**
-     * @var Payment|\PHPUnit_Framework_MockObject_MockObject
+     * @var Payment|MockObject
      */
     private $payment;
 
-    /**
-     * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $subjectReader;
-
     public function setUp()
     {
         $this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
         $this->payment = $this->getMockBuilder(Payment::class)
             ->disableOriginalConstructor()
             ->getMock();
-        $this->paymentDO->expects(static::once())
-            ->method('getPayment')
+        $this->paymentDO->method('getPayment')
             ->willReturn($this->payment);
 
-        $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $this->builder = new VaultCaptureDataBuilder($this->subjectReader);
+        $this->builder = new VaultCaptureDataBuilder(new SubjectReader());
     }
 
     /**
@@ -68,15 +59,6 @@ class VaultCaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
             'paymentMethodToken' => $token
         ];
 
-        $this->subjectReader->expects(self::once())
-            ->method('readPayment')
-            ->with($buildSubject)
-            ->willReturn($this->paymentDO);
-        $this->subjectReader->expects(self::once())
-            ->method('readAmount')
-            ->with($buildSubject)
-            ->willReturn($amount);
-
         $paymentExtension = $this->getMockBuilder(OrderPaymentExtension::class)
             ->setMethods(['getVaultPaymentToken'])
             ->disableOriginalConstructor()
@@ -86,18 +68,15 @@ class VaultCaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $paymentExtension->expects(static::once())
-            ->method('getVaultPaymentToken')
+        $paymentExtension->method('getVaultPaymentToken')
             ->willReturn($paymentToken);
-        $this->payment->expects(static::once())
-            ->method('getExtensionAttributes')
+        $this->payment->method('getExtensionAttributes')
             ->willReturn($paymentExtension);
 
-        $paymentToken->expects(static::once())
-            ->method('getGatewayToken')
+        $paymentToken->method('getGatewayToken')
             ->willReturn($token);
 
         $result = $this->builder->build($buildSubject);
-        static::assertEquals($expected, $result);
+        self::assertEquals($expected, $result);
     }
 }
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php
index 08b5526daeb04ef64cea6cbcf24f7749fd0be0a5..c4bd047a06bb8b64e5f007ea948780dcb89be79a 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php
@@ -20,7 +20,7 @@ class VaultDataBuilderTest extends \PHPUnit\Framework\TestCase
         $buildSubject = [];
 
         $builder = new VaultDataBuilder();
-        static::assertEquals(
+        self::assertEquals(
             $expectedResult,
             $builder->build($buildSubject)
         );
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
index 87e8e4e413c1bcc5ff1dda38f6598b54dc44950a..525b474040ea4ddb3fa37cf10deea03630251e98 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
@@ -11,7 +11,7 @@ use Magento\Braintree\Gateway\Response\CardDetailsHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
 use Magento\Sales\Model\Order\Payment;
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 /**
  * Class CardDetailsHandlerTest
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPal/VaultDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPal/VaultDetailsHandlerTest.php
index fdf3dc941bd776217d6830f4be92ac7ba49a21a6..0a3a9f2918a2181d124581eb118db2502cb59252 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPal/VaultDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPal/VaultDetailsHandlerTest.php
@@ -7,7 +7,7 @@ namespace Magento\Braintree\Test\Unit\Gateway\Response\PayPal;
 
 use Braintree\Transaction;
 use Braintree\Transaction\PayPalDetails;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Response\PayPal\VaultDetailsHandler;
 use Magento\Framework\Intl\DateTimeFactory;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php
index f1420ee895e5b7cb76e471c04a8690fd88af7f47..341135b6c03d0fa09ba472743d37ebd56bdd5f06 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php
@@ -10,7 +10,7 @@ use Magento\Braintree\Gateway\Response\PayPalDetailsHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
 use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Payment;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
index d90caa84b447b110d0d43f02a7e7a7161c9c0a8e..f941b8d7245d13ed0115256938ef62e06616e01e 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
@@ -10,7 +10,7 @@ use Magento\Braintree\Gateway\Response\PaymentDetailsHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
 use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Payment;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/RiskDataHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/RiskDataHandlerTest.php
index 2365c396c2f4a99934a807b6752ec278f2e4613a..374925b7339c0216537982b10b4a524e918fe2a2 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/RiskDataHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/RiskDataHandlerTest.php
@@ -6,7 +6,7 @@
 namespace Magento\Braintree\Test\Unit\Gateway\Response;
 
 use Braintree\Transaction;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Response\RiskDataHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Model\Order\Payment;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php
index 9ca9ca6aa07ae67217b5e76a167abda31dfaf464..6cffc00a89c418de24acb69bd1f7009560b333d7 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php
@@ -10,7 +10,7 @@ use Magento\Braintree\Gateway\Response\ThreeDSecureDetailsHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
 use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Payment;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/TransactionIdHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/TransactionIdHandlerTest.php
index 3a2d2f7073573f8bb942479940a27cb1f848bddf..6cbca707242f18790ba3ea25bb43e63d9984ca38 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/TransactionIdHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/TransactionIdHandlerTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Response;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Response\TransactionIdHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Model\Order\Payment;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php
index fb8f507bf1214260735ec49831ad28f4485e5ed7..568593273c58cbd29fe11975137bacadf4d000f1 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php
@@ -8,7 +8,7 @@ namespace Magento\Braintree\Test\Unit\Gateway\Response;
 use Braintree\Transaction;
 use Braintree\Transaction\CreditCardDetails;
 use Magento\Braintree\Gateway\Config\Config;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Response\VaultDetailsHandler;
 use Magento\Framework\DataObject;
 use Magento\Payment\Gateway\Data\PaymentDataObject;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php
index 398349a9692b7c6f81498775271a3056771e91a8..a541b0115fe63c5c741a7369d090e51c83675c48 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Braintree\Test\Unit\Gateway\Response;
 
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use Magento\Braintree\Gateway\Response\VoidHandler;
 use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
 use Magento\Sales\Model\Order\Payment;
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/GeneralResponseValidatorTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/GeneralResponseValidatorTest.php
index 1a9e547e9063600caa7f50646fb8e8f411da5d05..c8a46da504fef158a4a3d56137dc7d6debb3cc9f 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/GeneralResponseValidatorTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/GeneralResponseValidatorTest.php
@@ -10,7 +10,7 @@ use Magento\Framework\Phrase;
 use Magento\Payment\Gateway\Validator\ResultInterface;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
 use Magento\Braintree\Gateway\Validator\GeneralResponseValidator;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 class GeneralResponseValidatorTest extends \PHPUnit\Framework\TestCase
 {
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php
index 294226b1656ecbfdd96b79576be1157fbf1d5ae5..03363b5463d78dd8f4774da5d8c54e96a68e65d5 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php
@@ -9,7 +9,7 @@ use Braintree\Transaction;
 use Magento\Braintree\Gateway\Validator\PaymentNonceResponseValidator;
 use Magento\Payment\Gateway\Validator\ResultInterface;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 
 /**
  * Class PaymentNonceResponseValidatorTest
diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/ResponseValidatorTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
index aeb9b4a83077c3a1d73d70d116a84286a2ff1bea..4bd446079f9a70243944215ad450fede859cb59e 100644
--- a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
@@ -10,7 +10,7 @@ use Magento\Framework\Phrase;
 use Magento\Payment\Gateway\Validator\ResultInterface;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
 use Magento\Braintree\Gateway\Validator\ResponseValidator;
-use Magento\Braintree\Gateway\Helper\SubjectReader;
+use Magento\Braintree\Gateway\SubjectReader;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 use Braintree\Result\Error;
 use Braintree\Result\Successful;
diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php
index e43e67c18744f27308ff006c685b179508f97560..5fcb6a89244b5e4286855ec79a466113f557df99 100644
--- a/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php
@@ -6,10 +6,12 @@
 namespace Magento\Braintree\Test\Unit\Model\Report;
 
 use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Braintree\Model\Report\FilterMapper;
 use Magento\Braintree\Model\Report\TransactionsCollection;
 use Magento\Framework\Api\Search\DocumentInterface;
 use Magento\Framework\Data\Collection\EntityFactoryInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class TransactionsCollectionTest
@@ -19,48 +21,58 @@ use Magento\Framework\Data\Collection\EntityFactoryInterface;
 class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
 {
     /**
-     * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapter|MockObject
      */
-    private $braintreeAdapterMock;
+    private $braintreeAdapter;
 
     /**
-     * @var EntityFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var BraintreeAdapterFactory|MockObject
      */
-    private $entityFactoryMock;
+    private $adapterFactory;
 
     /**
-     * @var FilterMapper|\PHPUnit_Framework_MockObject_MockObject
+     * @var EntityFactoryInterface|MockObject
      */
-    private $filterMapperMock;
+    private $entityFactory;
 
     /**
-     * @var DocumentInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var FilterMapper|MockObject
      */
-    private $transactionMapMock;
+    private $filterMapper;
+
+    /**
+     * @var DocumentInterface|MockObject
+     */
+    private $transactionMap;
 
     /**
      * Setup
      */
     protected function setUp()
     {
-        $this->transactionMapMock = $this->getMockBuilder(DocumentInterface::class)
+        $this->transactionMap = $this->getMockBuilder(DocumentInterface::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->entityFactoryMock = $this->getMockBuilder(EntityFactoryInterface::class)
+        $this->entityFactory = $this->getMockBuilder(EntityFactoryInterface::class)
             ->setMethods(['create'])
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->filterMapperMock = $this->getMockBuilder(FilterMapper::class)
+        $this->filterMapper = $this->getMockBuilder(FilterMapper::class)
             ->setMethods(['getFilter'])
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->braintreeAdapterMock = $this->getMockBuilder(BraintreeAdapter::class)
+        $this->braintreeAdapter = $this->getMockBuilder(BraintreeAdapter::class)
             ->setMethods(['search'])
             ->disableOriginalConstructor()
             ->getMock();
+        $this->adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->adapterFactory->method('create')
+            ->willReturn($this->braintreeAdapter);
     }
 
     /**
@@ -68,28 +80,26 @@ class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
      */
     public function testGetItems()
     {
-        $this->filterMapperMock->expects($this->once())
-            ->method('getFilter')
+        $this->filterMapper->method('getFilter')
             ->willReturn(new BraintreeSearchNodeStub());
 
-        $this->braintreeAdapterMock->expects($this->once())
-            ->method('search')
+        $this->braintreeAdapter->method('search')
             ->willReturn(['transaction1', 'transaction2']);
 
-        $this->entityFactoryMock->expects($this->exactly(2))
+        $this->entityFactory->expects(self::exactly(2))
             ->method('create')
-            ->willReturn($this->transactionMapMock);
+            ->willReturn($this->transactionMap);
 
         $collection = new TransactionsCollection(
-            $this->entityFactoryMock,
-            $this->braintreeAdapterMock,
-            $this->filterMapperMock
+            $this->entityFactory,
+            $this->adapterFactory,
+            $this->filterMapper
         );
 
         $collection->addFieldToFilter('orderId', ['like' => '0']);
         $items = $collection->getItems();
-        $this->assertEquals(2, count($items));
-        $this->assertInstanceOf(DocumentInterface::class, $items[1]);
+        self::assertEquals(2, count($items));
+        self::assertInstanceOf(DocumentInterface::class, $items[1]);
     }
 
     /**
@@ -97,27 +107,25 @@ class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
      */
     public function testGetItemsEmptyCollection()
     {
-        $this->filterMapperMock->expects($this->once())
-            ->method('getFilter')
+        $this->filterMapper->method('getFilter')
             ->willReturn(new BraintreeSearchNodeStub());
 
-        $this->braintreeAdapterMock->expects($this->once())
-            ->method('search')
+        $this->braintreeAdapter->method('search')
             ->willReturn(null);
 
-        $this->entityFactoryMock->expects($this->never())
+        $this->entityFactory->expects(self::never())
             ->method('create')
-            ->willReturn($this->transactionMapMock);
+            ->willReturn($this->transactionMap);
 
         $collection = new TransactionsCollection(
-            $this->entityFactoryMock,
-            $this->braintreeAdapterMock,
-            $this->filterMapperMock
+            $this->entityFactory,
+            $this->adapterFactory,
+            $this->filterMapper
         );
 
         $collection->addFieldToFilter('orderId', ['like' => '0']);
         $items = $collection->getItems();
-        $this->assertEquals(0, count($items));
+        self::assertEquals(0, count($items));
     }
 
     /**
@@ -127,29 +135,27 @@ class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
     {
         $transations = range(1, TransactionsCollection::TRANSACTION_MAXIMUM_COUNT + 10);
 
-        $this->filterMapperMock->expects($this->once())
-            ->method('getFilter')
+        $this->filterMapper->method('getFilter')
             ->willReturn(new BraintreeSearchNodeStub());
 
-        $this->braintreeAdapterMock->expects($this->once())
-            ->method('search')
+        $this->braintreeAdapter->method('search')
             ->willReturn($transations);
 
-        $this->entityFactoryMock->expects($this->exactly(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT))
+        $this->entityFactory->expects(self::exactly(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT))
             ->method('create')
-            ->willReturn($this->transactionMapMock);
+            ->willReturn($this->transactionMap);
 
         $collection = new TransactionsCollection(
-            $this->entityFactoryMock,
-            $this->braintreeAdapterMock,
-            $this->filterMapperMock
+            $this->entityFactory,
+            $this->adapterFactory,
+            $this->filterMapper
         );
         $collection->setPageSize(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT);
 
         $collection->addFieldToFilter('orderId', ['like' => '0']);
         $items = $collection->getItems();
-        $this->assertEquals(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT, count($items));
-        $this->assertInstanceOf(DocumentInterface::class, $items[1]);
+        self::assertEquals(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT, count($items));
+        self::assertInstanceOf(DocumentInterface::class, $items[1]);
     }
 
     /**
@@ -159,29 +165,27 @@ class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
     {
         $transations = range(1, TransactionsCollection::TRANSACTION_MAXIMUM_COUNT + 10);
 
-        $this->filterMapperMock->expects($this->once())
-            ->method('getFilter')
+        $this->filterMapper->method('getFilter')
             ->willReturn(new BraintreeSearchNodeStub());
 
-        $this->braintreeAdapterMock->expects($this->once())
-            ->method('search')
+        $this->braintreeAdapter->method('search')
             ->willReturn($transations);
 
-        $this->entityFactoryMock->expects($this->exactly(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT))
+        $this->entityFactory->expects(self::exactly(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT))
             ->method('create')
-            ->willReturn($this->transactionMapMock);
+            ->willReturn($this->transactionMap);
 
         $collection = new TransactionsCollection(
-            $this->entityFactoryMock,
-            $this->braintreeAdapterMock,
-            $this->filterMapperMock
+            $this->entityFactory,
+            $this->adapterFactory,
+            $this->filterMapper
         );
         $collection->setPageSize(null);
 
         $collection->addFieldToFilter('orderId', ['like' => '0']);
         $items = $collection->getItems();
-        $this->assertEquals(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT, count($items));
-        $this->assertInstanceOf(DocumentInterface::class, $items[1]);
+        self::assertEquals(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT, count($items));
+        self::assertInstanceOf(DocumentInterface::class, $items[1]);
     }
 
     /**
@@ -191,18 +195,18 @@ class TransactionsCollectionTest extends \PHPUnit\Framework\TestCase
      */
     public function testAddToFilter($field, $condition, $filterMapperCall, $expectedCondition)
     {
-        $this->filterMapperMock->expects(static::exactly($filterMapperCall))
+        $this->filterMapper->expects(self::exactly($filterMapperCall))
             ->method('getFilter')
             ->with($field, $expectedCondition)
             ->willReturn(new BraintreeSearchNodeStub());
 
         $collection = new TransactionsCollection(
-            $this->entityFactoryMock,
-            $this->braintreeAdapterMock,
-            $this->filterMapperMock
+            $this->entityFactory,
+            $this->adapterFactory,
+            $this->filterMapper
         );
 
-        static::assertInstanceOf(
+        self::assertInstanceOf(
             TransactionsCollection::class,
             $collection->addFieldToFilter($field, $condition)
         );
diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php
index 6c85ae68eb7aff9c72550fb58860750e3a25a0ae..dca22c26c11da360360b8abfd37e285ee9c34452 100644
--- a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php
@@ -7,7 +7,9 @@ namespace Magento\Braintree\Test\Unit\Model\Ui;
 
 use Magento\Braintree\Gateway\Config\Config;
 use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
 use Magento\Braintree\Model\Ui\ConfigProvider;
+use Magento\Customer\Model\Session;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
@@ -31,6 +33,11 @@ class ConfigProviderTest extends \PHPUnit\Framework\TestCase
      */
     private $braintreeAdapter;
 
+    /**
+     * @var Session|MockObject
+     */
+    private $session;
+
     /**
      * @var ConfigProvider
      */
@@ -45,10 +52,24 @@ class ConfigProviderTest extends \PHPUnit\Framework\TestCase
         $this->braintreeAdapter = $this->getMockBuilder(BraintreeAdapter::class)
             ->disableOriginalConstructor()
             ->getMock();
+        /** @var BraintreeAdapterFactory|MockObject $adapterFactory */
+        $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $adapterFactory->method('create')
+            ->willReturn($this->braintreeAdapter);
+
+        $this->session = $this->getMockBuilder(Session::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getStoreId'])
+            ->getMock();
+        $this->session->method('getStoreId')
+            ->willReturn(null);
 
         $this->configProvider = new ConfigProvider(
             $this->config,
-            $this->braintreeAdapter
+            $adapterFactory,
+            $this->session
         );
     }
 
@@ -61,35 +82,30 @@ class ConfigProviderTest extends \PHPUnit\Framework\TestCase
      */
     public function testGetConfig($config, $expected)
     {
-        $this->braintreeAdapter->expects(static::once())
-            ->method('generate')
+        $this->braintreeAdapter->method('generate')
             ->willReturn(self::CLIENT_TOKEN);
 
         foreach ($config as $method => $value) {
-            $this->config->expects(static::once())
-                ->method($method)
+            $this->config->method($method)
                 ->willReturn($value);
         }
 
-        static::assertEquals($expected, $this->configProvider->getConfig());
+        self::assertEquals($expected, $this->configProvider->getConfig());
     }
 
     /**
-     * @covers \Magento\Braintree\Model\Ui\ConfigProvider::getClientToken
      * @dataProvider getClientTokenDataProvider
      */
     public function testGetClientToken($merchantAccountId, $params)
     {
-        $this->config->expects(static::once())
-            ->method('getMerchantAccountId')
+        $this->config->method('getMerchantAccountId')
             ->willReturn($merchantAccountId);
 
-        $this->braintreeAdapter->expects(static::once())
-            ->method('generate')
+        $this->braintreeAdapter->method('generate')
             ->with($params)
             ->willReturn(self::CLIENT_TOKEN);
 
-        static::assertEquals(self::CLIENT_TOKEN, $this->configProvider->getClientToken());
+        self::assertEquals(self::CLIENT_TOKEN, $this->configProvider->getClientToken());
     }
 
     /**
diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json
index 64d2e1950825fc305c7a5b9d142f4e84f18ab6c5..0248a62ccfbb2476f07dcec730edada1ed38374d 100644
--- a/app/code/Magento/Braintree/composer.json
+++ b/app/code/Magento/Braintree/composer.json
@@ -25,7 +25,7 @@
         "magento/module-theme": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "proprietary"
     ],
diff --git a/app/code/Magento/Braintree/etc/adminhtml/di.xml b/app/code/Magento/Braintree/etc/adminhtml/di.xml
index d0469ded83b67bebd4c875c1bedd3a223647ba0b..90fc927ed4f8026e6ee86fe22ec523a6eb3f69bf 100644
--- a/app/code/Magento/Braintree/etc/adminhtml/di.xml
+++ b/app/code/Magento/Braintree/etc/adminhtml/di.xml
@@ -28,6 +28,7 @@
                 <item name="address" xsi:type="string">Magento\Braintree\Gateway\Request\AddressDataBuilder</item>
                 <item name="vault" xsi:type="string">Magento\Braintree\Gateway\Request\VaultDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -39,6 +40,7 @@
                 <item name="channel" xsi:type="string">Magento\Braintree\Gateway\Request\ChannelDataBuilder</item>
                 <item name="address" xsi:type="string">Magento\Braintree\Gateway\Request\AddressDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -57,4 +59,9 @@
             <argument name="session" xsi:type="object">Magento\Backend\Model\Session\Quote</argument>
         </arguments>
     </type>
+    <type name="Magento\Braintree\Model\Ui\ConfigProvider">
+        <arguments>
+            <argument name="session" xsi:type="object">Magento\Backend\Model\Session\Quote</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Braintree/etc/di.xml b/app/code/Magento/Braintree/etc/di.xml
index 2a451e132eab0e5e69efdc656826327a8109c2c1..86c291181575437012da6db8ef0b2601eddd66bd 100644
--- a/app/code/Magento/Braintree/etc/di.xml
+++ b/app/code/Magento/Braintree/etc/di.xml
@@ -214,6 +214,7 @@
                 <item name="3dsecure" xsi:type="string">Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder</item>
                 <item name="device_data" xsi:type="string">Magento\Braintree\Gateway\Request\KountPaymentDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -245,6 +246,7 @@
         <arguments>
             <argument name="builders" xsi:type="array">
                 <item name="capture" xsi:type="string">Magento\Braintree\Gateway\Request\CaptureDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -268,6 +270,7 @@
                 <item name="3dsecure" xsi:type="string">Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder</item>
                 <item name="device_data" xsi:type="string">Magento\Braintree\Gateway\Request\KountPaymentDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -300,6 +303,7 @@
             <argument name="builders" xsi:type="array">
                 <item name="vault_capture" xsi:type="string">Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder</item>
                 <item name="settlement" xsi:type="string">Magento\Braintree\Gateway\Request\SettlementDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -321,6 +325,7 @@
                 <item name="vault" xsi:type="string">Magento\Braintree\Gateway\Request\PayPal\VaultDataBuilder</item>
                 <item name="device_data" xsi:type="string">Magento\Braintree\Gateway\Request\PayPal\DeviceDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -353,6 +358,7 @@
                 <item name="channel" xsi:type="string">Magento\Braintree\Gateway\Request\ChannelDataBuilder</item>
                 <item name="address" xsi:type="string">Magento\Braintree\Gateway\Request\AddressDataBuilder</item>
                 <item name="dynamic_descriptor" xsi:type="string">Magento\Braintree\Gateway\Request\DescriptorDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
             </argument>
         </arguments>
     </virtualType>
@@ -463,23 +469,41 @@
     <virtualType name="BraintreeVoidCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
         <arguments>
             <argument name="client" xsi:type="object">Magento\Braintree\Gateway\Http\Client\TransactionVoid</argument>
-            <argument name="requestBuilder" xsi:type="object">Magento\Braintree\Gateway\Request\VoidDataBuilder</argument>
+            <argument name="requestBuilder" xsi:type="object">BraintreeVoidRequestBuilder</argument>
             <argument name="handler" xsi:type="object">Magento\Braintree\Gateway\Response\VoidHandler</argument>
             <argument name="validator" xsi:type="object">Magento\Braintree\Gateway\Validator\GeneralResponseValidator</argument>
             <argument name="transferFactory" xsi:type="object">Magento\Braintree\Gateway\Http\TransferFactory</argument>
         </arguments>
     </virtualType>
+    <virtualType name="BraintreeVoidRequestBuilder" type="Magento\Payment\Gateway\Request\BuilderComposite">
+        <arguments>
+            <argument name="builders" xsi:type="array">
+                <item name="void" xsi:type="string">Magento\Braintree\Gateway\Request\VoidDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <!-- END Void Command -->
 
     <!-- Refund Command -->
     <virtualType name="BraintreeRefundCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
         <arguments>
             <argument name="client" xsi:type="object">Magento\Braintree\Gateway\Http\Client\TransactionRefund</argument>
-            <argument name="requestBuilder" xsi:type="object">Magento\Braintree\Gateway\Request\RefundDataBuilder</argument>
+            <argument name="requestBuilder" xsi:type="object">BraintreeRefundBuilder</argument>
             <argument name="validator" xsi:type="object">Magento\Braintree\Gateway\Validator\GeneralResponseValidator</argument>
             <argument name="handler" xsi:type="object">Magento\Braintree\Gateway\Response\RefundHandler</argument>
             <argument name="transferFactory" xsi:type="object">Magento\Braintree\Gateway\Http\TransferFactory</argument>
         </arguments>
     </virtualType>
+    <virtualType name="BraintreeRefundBuilder" type="Magento\Payment\Gateway\Request\BuilderComposite">
+        <arguments>
+            <argument name="builders" xsi:type="array">
+                <item name="refund" xsi:type="string">Magento\Braintree\Gateway\Request\RefundDataBuilder</item>
+                <item name="store" xsi:type="string">Magento\Braintree\Gateway\Request\StoreConfigBuilder</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <!-- END Refund Command -->
 
     <!-- Braintree validators infrastructure -->
     <virtualType name="BraintreeCountryValidator" type="Magento\Payment\Gateway\Validator\CountryValidator">
@@ -494,7 +518,7 @@
             </argument>
         </arguments>
     </virtualType>
-    <!-- Braintree validators infrastructure -->
+    <!-- END Braintree validators infrastructure -->
 
     <!-- Braintree PayPal validators -->
     <virtualType name="BraintreePayPalCountryValidator" type="Magento\Payment\Gateway\Validator\CountryValidator">
diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js b/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js
index 8324cfe463bdb78d7caf8eb88e4a61f2a91c3965..5e1e85e6a3c481aabcb5f6cf15536b0cd64c3ae9 100644
--- a/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js
+++ b/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js
@@ -116,7 +116,7 @@ define([
         },
 
         /**
-         * Setup Braintree SDK
+         * Retrieves client token and setup Braintree SDK
          */
         initBraintree: function () {
             var self = this;
@@ -124,35 +124,14 @@ define([
             try {
                 $('body').trigger('processStart');
 
-                self.braintree.setup(self.clientToken, 'custom', {
-                    id: self.selector,
-                    hostedFields: self.getHostedFields(),
-
-                    /**
-                     * Triggered when sdk was loaded
-                     */
-                    onReady: function () {
-                        $('body').trigger('processStop');
-                    },
+                $.getJSON(self.clientTokenUrl).done(function (response) {
+                    self.clientToken = response.clientToken;
+                    self._initBraintree();
+                }).fail(function (response) {
+                    var failed = JSON.parse(response.responseText);
 
-                    /**
-                     * Callback for success response
-                     * @param {Object} response
-                     */
-                    onPaymentMethodReceived: function (response) {
-                        if (self.validateCardType()) {
-                            self.setPaymentDetails(response.nonce);
-                            self.placeOrder();
-                        }
-                    },
-
-                    /**
-                     * Error callback
-                     * @param {Object} response
-                     */
-                    onError: function (response) {
-                        self.error(response.message);
-                    }
+                    $('body').trigger('processStop');
+                    self.error(failed.message);
                 });
             } catch (e) {
                 $('body').trigger('processStop');
@@ -160,6 +139,44 @@ define([
             }
         },
 
+        /**
+         * Setup Braintree SDK
+         */
+        _initBraintree: function () {
+            var self = this;
+
+            self.braintree.setup(self.clientToken, 'custom', {
+                id: self.selector,
+                hostedFields: self.getHostedFields(),
+
+                /**
+                 * Triggered when sdk was loaded
+                 */
+                onReady: function () {
+                    $('body').trigger('processStop');
+                },
+
+                /**
+                 * Callback for success response
+                 * @param {Object} response
+                 */
+                onPaymentMethodReceived: function (response) {
+                    if (self.validateCardType()) {
+                        self.setPaymentDetails(response.nonce);
+                        self.placeOrder();
+                    }
+                },
+
+                /**
+                 * Error callback
+                 * @param {Object} response
+                 */
+                onError: function (response) {
+                    self.error(response.message);
+                }
+            });
+        },
+
         /**
          * Get hosted fields configuration
          * @returns {Object}
diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json
index 39b5fe1b1a6d5c009b4cdd58b2b587842f57862f..0983d4c6b5946787f9937567f6654840d6ddd9b1 100644
--- a/app/code/Magento/Bundle/composer.json
+++ b/app/code/Magento/Bundle/composer.json
@@ -25,7 +25,7 @@
         "magento/module-bundle-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php
index ae0c3554c0d32547fd0f2cc540405eb8dd04f7cb..e61acc2aa09e5cb8fe15ff601d241886f397a438 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php
@@ -52,7 +52,6 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
      * @param \Magento\Framework\Indexer\BatchSizeManagementInterface|null $batchSizeManagement
      * @param \Magento\Framework\Indexer\BatchProviderInterface|null $batchProvider
      * @param \Magento\Framework\EntityManager\MetadataPool|null $metadataPool
-     * @param \Magento\Indexer\Model\Indexer\StateFactory|null $stateFactory
      * @param int|null $batchRowsCount
      * @param ActiveTableSwitcher|null $activeTableSwitcher
      */
@@ -87,6 +86,20 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
         $this->activeTableSwitcher = $activeTableSwitcher ?: $objectManager->get(ActiveTableSwitcher::class);
     }
 
+    /**
+     * Clear the table we'll be writing de-normalized data into
+     * to prevent archived data getting in the way of actual data.
+     *
+     * @return void
+     */
+    private function clearCurrentTable()
+    {
+        $this->connection->delete(
+            $this->activeTableSwitcher
+                ->getAdditionalTableName($this->getMainTable())
+        );
+    }
+
     /**
      * Refresh entities index
      *
@@ -94,6 +107,7 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
      */
     public function execute()
     {
+        $this->clearCurrentTable();
         $this->reindex();
         $this->activeTableSwitcher->switchTable($this->connection, [$this->getMainTable()]);
         return $this;
@@ -103,6 +117,7 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
      * Return select for remove unnecessary data
      *
      * @return \Magento\Framework\DB\Select
+     * @deprecated 102.0.1 Not needed anymore.
      */
     protected function getSelectUnnecessaryData()
     {
@@ -127,12 +142,15 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
      * Remove unnecessary data
      *
      * @return void
+     *
+     * @deprecated 102.0.1 Not needed anymore.
      */
     protected function removeUnnecessaryData()
     {
-        $this->connection->query(
-            $this->connection->deleteFromSelect($this->getSelectUnnecessaryData(), $this->getMainTable())
-        );
+        //Called for backwards compatibility.
+        $this->getSelectUnnecessaryData();
+        //This method is useless,
+        //left it here just in case somebody's using it in child classes.
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
index 05dd94dbe6e578c8c87fde185549dada98b48fc8..fbe0d4b550fa671288001e27e4c1d95956430859 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
@@ -179,6 +179,11 @@ class FlatTableBuilder
 
             $columnComment = isset($fieldProp['comment']) ? $fieldProp['comment'] : $fieldName;
 
+            if ($fieldName == 'created_at') {
+                $columnDefinition['nullable'] = true;
+                $columnDefinition['default'] = null;
+            }
+
             $table->addColumn($fieldName, $fieldProp['type'], $columnLength, $columnDefinition, $columnComment);
         }
 
diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json
index 5cdf62cdb34052e7142875300b8078087c555ad1..10b408c5458780245fde6ab32a77cccd2618be8c 100644
--- a/app/code/Magento/Catalog/composer.json
+++ b/app/code/Magento/Catalog/composer.json
@@ -34,7 +34,7 @@
         "magento/module-catalog-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "102.0.0",
+    "version": "102.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogAnalytics/composer.json b/app/code/Magento/CatalogAnalytics/composer.json
index 6cda52197f80a0ccb9fd5d7f4fc61c7ac0013f1c..7c622f6fbfa078366f811755a051ed1e07693e95 100644
--- a/app/code/Magento/CatalogAnalytics/composer.json
+++ b/app/code/Magento/CatalogAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-catalog": "101.1.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json
index 5ef316b2c065c975a463a82f0eadee00310292dd..2b70f65d1f830a79111c129ebf5726e322865a77 100644
--- a/app/code/Magento/CatalogImportExport/composer.json
+++ b/app/code/Magento/CatalogImportExport/composer.json
@@ -16,7 +16,7 @@
         "ext-ctype": "*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json
index 142ae98422e873e23fe60f4e44ef3e10cdc3a67b..79f86612d41bd21df75993308cc734d9aae0169c 100644
--- a/app/code/Magento/CatalogInventory/composer.json
+++ b/app/code/Magento/CatalogInventory/composer.json
@@ -13,7 +13,7 @@
         "magento/module-ui": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json
index 8bee82f6fe34be92d89c006ecf44081152e9c9bf..845bdeff31f427dbf74f8ecd0882de2794f15063 100644
--- a/app/code/Magento/CatalogRule/composer.json
+++ b/app/code/Magento/CatalogRule/composer.json
@@ -17,7 +17,7 @@
         "magento/module-catalog-rule-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json
index 8cdf797e1ca4cbd4d339ffbd00a971934b8b2e74..13be21e3248f248c064ad877fa80deb1add36ab1 100644
--- a/app/code/Magento/CatalogSearch/composer.json
+++ b/app/code/Magento/CatalogSearch/composer.json
@@ -15,7 +15,7 @@
         "magento/framework": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogUrlRewrite/composer.json b/app/code/Magento/CatalogUrlRewrite/composer.json
index f11467e9f8d1f9d2d4c4a54a7a5b15094cce36c7..344562864384fc0dde8a70554416dcb058092ffc 100644
--- a/app/code/Magento/CatalogUrlRewrite/composer.json
+++ b/app/code/Magento/CatalogUrlRewrite/composer.json
@@ -14,7 +14,7 @@
         "magento/module-ui": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json
index fa4b5071d4dd69aa36e719f79f419d36c5bf8689..48d6562c5c77e8912bb88ae1395cc87bcb657423 100644
--- a/app/code/Magento/Checkout/composer.json
+++ b/app/code/Magento/Checkout/composer.json
@@ -27,7 +27,7 @@
         "magento/module-cookie": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Checkout/i18n/en_US.csv b/app/code/Magento/Checkout/i18n/en_US.csv
index 53e6ef67d68cd0f2c9697282a95481590fe6ab9a..8d297c4060abd71e5e7cf9a4d43a22dbfe8007f4 100644
--- a/app/code/Magento/Checkout/i18n/en_US.csv
+++ b/app/code/Magento/Checkout/i18n/en_US.csv
@@ -62,7 +62,7 @@ Checkout,Checkout
 Error!,Error!
 "DB exception","DB exception"
 Message,Message
-"<a href=""%1"" onclick=""this.target='_blank'"" class=""print"">Print receipt</a>","<a href=""%1"" onclick=""this.target='_blank'"" class=""print"">Print receipt</a>"
+"Print receipt","Print receipt"
 "Apply Discount Code","Apply Discount Code"
 "Enter discount code","Enter discount code"
 "Apply Discount","Apply Discount"
diff --git a/app/code/Magento/Checkout/view/frontend/templates/button.phtml b/app/code/Magento/Checkout/view/frontend/templates/button.phtml
index e2bcd76cba35bbbf3dc843a0dfdbb800831104d8..c3edfe30f8bdd79afb8870bb81e8ac269c557f2c 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/button.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/button.phtml
@@ -10,6 +10,8 @@
 <?php /** @var $block \Magento\Checkout\Block\Onepage\Success */ ?>
 
 <?php if ($block->getCanViewOrder() && $block->getCanPrintOrder()) :?>
-    <?= /* @escapeNotVerified */ __('<a href="%1" onclick="this.target=\'_blank\'" class="print">Print receipt</a>', $block->getPrintUrl()) ?>
+    <a href="<?= /* @escapeNotVerified */ $block->getPrintUrl() ?>" target="_blank" class="print">
+        <?= /* @escapeNotVerified */ __('Print receipt') ?>
+    </a>
     <?= $block->getChildHtml() ?>
 <?php endif;?>
diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json
index c4f690db9cd1fe8b1a9bb4ed003b554f653b7fc8..3094908e69ca0cde95cff37e43d0701ce3d772c4 100644
--- a/app/code/Magento/Cms/composer.json
+++ b/app/code/Magento/Cms/composer.json
@@ -18,7 +18,7 @@
         "magento/module-cms-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "102.0.0",
+    "version": "102.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Config/Block/System/Config/Form.php b/app/code/Magento/Config/Block/System/Config/Form.php
index c540b8a3b0bb78dfed638c801a0e333a87c489f1..c17df229cf5490b6d4c81d0baf7a12a98df420fd 100644
--- a/app/code/Magento/Config/Block/System/Config/Form.php
+++ b/app/code/Magento/Config/Block/System/Config/Form.php
@@ -8,6 +8,7 @@ namespace Magento\Config\Block\System\Config;
 use Magento\Config\App\Config\Type\System;
 use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker;
 use Magento\Config\Model\Config\Structure\ElementVisibilityInterface;
+use Magento\Framework\App\Config\Data\ProcessorInterface;
 use Magento\Framework\App\Config\ScopeConfigInterface;
 use Magento\Framework\App\DeploymentConfig;
 use Magento\Framework\App\ObjectManager;
@@ -429,6 +430,18 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic
         if ($data === null) {
             $path = $field->getConfigPath() !== null ? $field->getConfigPath() : $path;
             $data = $this->getConfigValue($path);
+            if ($field->hasBackendModel()) {
+                $backendModel = $field->getBackendModel();
+                // Backend models which implement ProcessorInterface are processed by ScopeConfigInterface
+                if (!$backendModel instanceof ProcessorInterface) {
+                    $backendModel->setPath($path)
+                        ->setValue($data)
+                        ->setWebsite($this->getWebsiteCode())
+                        ->setStore($this->getStoreCode())
+                        ->afterLoad();
+                    $data = $backendModel->getValue();
+                }
+            }
         }
 
         return $data;
diff --git a/app/code/Magento/Config/Model/Config/Backend/Serialized.php b/app/code/Magento/Config/Model/Config/Backend/Serialized.php
index 634f470e87567883482c15fc644970def54211eb..3d5713357c39c13f5707bc8ca552101ad4fd02ce 100644
--- a/app/code/Magento/Config/Model/Config/Backend/Serialized.php
+++ b/app/code/Magento/Config/Model/Config/Backend/Serialized.php
@@ -5,7 +5,6 @@
  */
 namespace Magento\Config\Model\Config\Backend;
 
-use Magento\Framework\App\Config\Data\ProcessorInterface;
 use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Serialize\Serializer\Json;
 
@@ -13,7 +12,7 @@ use Magento\Framework\Serialize\Serializer\Json;
  * @api
  * @since 100.0.2
  */
-class Serialized extends \Magento\Framework\App\Config\Value implements ProcessorInterface
+class Serialized extends \Magento\Framework\App\Config\Value
 {
     /**
      * @var Json
@@ -68,12 +67,4 @@ class Serialized extends \Magento\Framework\App\Config\Value implements Processo
         parent::beforeSave();
         return $this;
     }
-
-    /**
-     * @inheritdoc
-     */
-    public function processValue($value)
-    {
-        return empty($value) ? '' : $this->serializer->unserialize($value);
-    }
 }
diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php
index e4170fbe8732eb0c0f5cae87e32cf6df84aada8c..72e8386bddaf6c3debeb26f6cb41e118fd8329dc 100644
--- a/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php
+++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php
@@ -548,7 +548,7 @@ class FormTest extends \PHPUnit\Framework\TestCase
                 false,
                 'some_value',
                 null,
-                0,
+                1,
                 false,
                 false,
                 false
@@ -560,7 +560,7 @@ class FormTest extends \PHPUnit\Framework\TestCase
                 true,
                 'Config Value',
                 null,
-                0,
+                1,
                 true,
                 false,
                 true
diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json
index fb4c80115334de64f8ff0da42fb87be4fa0781e9..a29f65473ab016f68708099ba19b640676e02935 100644
--- a/app/code/Magento/Config/composer.json
+++ b/app/code/Magento/Config/composer.json
@@ -13,7 +13,7 @@
         "magento/module-deploy": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json
index a62ce29813ce3f96ac1bf221fd0ff1ff62b63251..3b60f57c2f923e03c9253af43598268b9aceb323 100644
--- a/app/code/Magento/ConfigurableProduct/composer.json
+++ b/app/code/Magento/ConfigurableProduct/composer.json
@@ -24,7 +24,7 @@
         "magento/module-product-links-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Contact/Controller/Index/Post.php b/app/code/Magento/Contact/Controller/Index/Post.php
index 3374ff1fa5cf4440c1a61e8cb025a2d4004e9755..ee2d23b74df24e82461240a7a824f242dd33c164 100644
--- a/app/code/Magento/Contact/Controller/Index/Post.php
+++ b/app/code/Magento/Contact/Controller/Index/Post.php
@@ -9,12 +9,13 @@ namespace Magento\Contact\Controller\Index;
 use Magento\Contact\Model\ConfigInterface;
 use Magento\Contact\Model\MailInterface;
 use Magento\Framework\App\Action\Context;
-use Magento\Framework\App\ObjectManager;
 use Magento\Framework\App\Request\DataPersistorInterface;
 use Magento\Framework\Controller\Result\Redirect;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\HTTP\PhpEnvironment\Request;
 use Psr\Log\LoggerInterface;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\DataObject;
 
 class Post extends \Magento\Contact\Controller\Index
 {
@@ -56,7 +57,7 @@ class Post extends \Magento\Contact\Controller\Index
         $this->context = $context;
         $this->mail = $mail;
         $this->dataPersistor = $dataPersistor;
-        $this->logger = $logger ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LoggerInterface::class);
+        $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
     }
 
     /**
@@ -71,45 +72,33 @@ class Post extends \Magento\Contact\Controller\Index
         }
         try {
             $this->sendEmail($this->validatedParams());
-            $this->messageManager->addSuccess(
+            $this->messageManager->addSuccessMessage(
                 __('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.')
             );
-            $this->getDataPersistor()->clear('contact_us');
+            $this->dataPersistor->clear('contact_us');
         } catch (LocalizedException $e) {
             $this->messageManager->addErrorMessage($e->getMessage());
-            $this->getDataPersistor()->set('contact_us', $this->getRequest()->getParams());
+            $this->dataPersistor->set('contact_us', $this->getRequest()->getParams());
         } catch (\Exception $e) {
             $this->logger->critical($e);
             $this->messageManager->addErrorMessage(
                 __('An error occurred while processing your form. Please try again later.')
             );
-            $this->getDataPersistor()->set('contact_us', $this->getRequest()->getParams());
+            $this->dataPersistor->set('contact_us', $this->getRequest()->getParams());
         }
         return $this->resultRedirectFactory->create()->setPath('contact/index');
     }
 
-    /**
-     * Get Data Persistor
-     *
-     * @return DataPersistorInterface
-     */
-    private function getDataPersistor()
-    {
-        if ($this->dataPersistor === null) {
-            $this->dataPersistor = ObjectManager::getInstance()
-                ->get(DataPersistorInterface::class);
-        }
-
-        return $this->dataPersistor;
-    }
-
     /**
      * @param array $post Post data from contact form
      * @return void
      */
     private function sendEmail($post)
     {
-        $this->mail->send($post['email'], ['data' => new \Magento\Framework\DataObject($post)]);
+        $this->mail->send(
+            $post['email'],
+            ['data' => new DataObject($post)]
+        );
     }
 
     /**
diff --git a/app/code/Magento/Contact/Model/Mail.php b/app/code/Magento/Contact/Model/Mail.php
index d63efbbca573b94a0b8754763dd8c33fecdc46e5..43c1974252b5a7d14ce6e5fb8a4b3c6c21f8077a 100644
--- a/app/code/Magento/Contact/Model/Mail.php
+++ b/app/code/Magento/Contact/Model/Mail.php
@@ -6,9 +6,10 @@
 namespace Magento\Contact\Model;
 
 use Magento\Framework\Mail\Template\TransportBuilder;
-use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Translate\Inline\StateInterface;
 use Magento\Store\Model\StoreManagerInterface;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\App\Area;
 
 class Mail implements MailInterface
 {
@@ -49,8 +50,7 @@ class Mail implements MailInterface
         $this->contactsConfig = $contactsConfig;
         $this->transportBuilder = $transportBuilder;
         $this->inlineTranslation = $inlineTranslation;
-        $this->storeManager = $storeManager ?:
-            ObjectManager::getInstance()->get(StoreManagerInterface::class);
+        $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
     }
 
     /**
@@ -71,7 +71,7 @@ class Mail implements MailInterface
                 ->setTemplateIdentifier($this->contactsConfig->emailTemplate())
                 ->setTemplateOptions(
                     [
-                        'area' => 'frontend',
+                        'area' => Area::AREA_FRONTEND,
                         'store' => $this->storeManager->getStore()->getId()
                     ]
                 )
diff --git a/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php b/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php
index a18540d8cf9d57a87fbc76c64f93f08ff58f415d..2133ae5a323b4ec2de7b6a62b1cc4e7274dbd14b 100644
--- a/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php
+++ b/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php
@@ -38,7 +38,7 @@ interface CustomerRepositoryInterface
     public function get($email, $websiteId = null);
 
     /**
-     * Get customer by customer ID.
+     * Get customer by Customer ID.
      *
      * @param int $customerId
      * @return \Magento\Customer\Api\Data\CustomerInterface
@@ -70,7 +70,7 @@ interface CustomerRepositoryInterface
     public function delete(\Magento\Customer\Api\Data\CustomerInterface $customer);
 
     /**
-     * Delete customer by ID.
+     * Delete customer by Customer ID.
      *
      * @param int $customerId
      * @return bool true on success
diff --git a/app/code/Magento/Customer/Block/Address/Edit.php b/app/code/Magento/Customer/Block/Address/Edit.php
index 6362f28a4f96d0aab16f0e0afafa4ce36aabc431..e9e894b2bc130e5ecf3ad39c10cadc50e245fc68 100644
--- a/app/code/Magento/Customer/Block/Address/Edit.php
+++ b/app/code/Magento/Customer/Block/Address/Edit.php
@@ -5,7 +5,9 @@
  */
 namespace Magento\Customer\Block\Address;
 
+use Magento\Customer\Model\AttributeChecker;
 use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\App\ObjectManager;
 
 /**
  * Customer address edit block
@@ -46,6 +48,11 @@ class Edit extends \Magento\Directory\Block\Data
      */
     protected $dataObjectHelper;
 
+    /**
+     * @var AttributeChecker
+     */
+    private $attributeChecker;
+
     /**
      * Constructor
      *
@@ -61,7 +68,7 @@ class Edit extends \Magento\Directory\Block\Data
      * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer
      * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
      * @param array $data
-     *
+     * @param AttributeChecker $attributeChecker
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -76,13 +83,16 @@ class Edit extends \Magento\Directory\Block\Data
         \Magento\Customer\Api\Data\AddressInterfaceFactory $addressDataFactory,
         \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer,
         \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
-        array $data = []
+        array $data = [],
+        AttributeChecker $attributeChecker = null
     ) {
         $this->_customerSession = $customerSession;
         $this->_addressRepository = $addressRepository;
         $this->addressDataFactory = $addressDataFactory;
         $this->currentCustomer = $currentCustomer;
         $this->dataObjectHelper = $dataObjectHelper;
+        $this->attributeChecker = $attributeChecker ?: ObjectManager::getInstance()->get(AttributeChecker::class);
+
         parent::__construct(
             $context,
             $directoryHelper,
@@ -352,4 +362,16 @@ class Edit extends \Magento\Directory\Block\Data
     {
         return $this->_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
     }
+
+    /**
+     * Checks whether it is allowed to show an attribute on the form.
+     *
+     * @param string $attributeCode
+     * @param string $formName
+     * @return bool
+     */
+    public function isAttributeAllowedOnForm($attributeCode, $formName)
+    {
+        return $this->attributeChecker->isAttributeAllowedOnForm($attributeCode, $formName);
+    }
 }
diff --git a/app/code/Magento/Customer/Helper/Address.php b/app/code/Magento/Customer/Helper/Address.php
index 8dac704aaa08535f3ffe704907cedf24fbd2b90e..c74c62dc6d98cd153e7eeb52a061ec9d1f234b17 100644
--- a/app/code/Magento/Customer/Helper/Address.php
+++ b/app/code/Magento/Customer/Helper/Address.php
@@ -8,9 +8,7 @@ namespace Magento\Customer\Helper;
 use Magento\Customer\Api\AddressMetadataInterface;
 use Magento\Customer\Api\CustomerMetadataInterface;
 use Magento\Customer\Api\Data\AttributeMetadataInterface;
-use Magento\Customer\Model\Metadata\AttributeResolver;
 use Magento\Directory\Model\Country\Format;
-use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\NoSuchEntityException;
 
 /**
@@ -95,11 +93,6 @@ class Address extends \Magento\Framework\App\Helper\AbstractHelper
      */
     protected $_addressConfig;
 
-    /**
-     * @var AttributeResolver
-     */
-    private $attributeResolver;
-
     /**
      * @param \Magento\Framework\App\Helper\Context $context
      * @param \Magento\Framework\View\Element\BlockFactory $blockFactory
@@ -107,7 +100,6 @@ class Address extends \Magento\Framework\App\Helper\AbstractHelper
      * @param CustomerMetadataInterface $customerMetadataService
      * @param AddressMetadataInterface $addressMetadataService
      * @param \Magento\Customer\Model\Address\Config $addressConfig
-     * @param AttributeResolver|null $attributeResolver
      */
     public function __construct(
         \Magento\Framework\App\Helper\Context $context,
@@ -115,15 +107,13 @@ class Address extends \Magento\Framework\App\Helper\AbstractHelper
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         CustomerMetadataInterface $customerMetadataService,
         AddressMetadataInterface $addressMetadataService,
-        \Magento\Customer\Model\Address\Config $addressConfig,
-        AttributeResolver $attributeResolver = null
+        \Magento\Customer\Model\Address\Config $addressConfig
     ) {
         $this->_blockFactory = $blockFactory;
         $this->_storeManager = $storeManager;
         $this->_customerMetadataService = $customerMetadataService;
         $this->_addressMetadataService = $addressMetadataService;
         $this->_addressConfig = $addressConfig;
-        $this->attributeResolver = $attributeResolver ?: ObjectManager::getInstance()->get(AttributeResolver::class);
         parent::__construct($context);
     }
 
@@ -401,31 +391,4 @@ class Address extends \Magento\Framework\App\Helper\AbstractHelper
         }
         return false;
     }
-
-    /**
-     * Checks whether it is allowed to show an attribute on the form
-     *
-     * This check relies on the attribute's property 'getUsedInForms' which contains a list of forms
-     * where allowed to render specified attribute.
-     *
-     * @param string $attributeCode
-     * @param string $formName
-     * @return bool
-     */
-    public function isAttributeAllowedOnForm($attributeCode, $formName)
-    {
-        $isAllowed = false;
-        $attributeMetadata = $this->_addressMetadataService->getAttributeMetadata($attributeCode);
-        if ($attributeMetadata) {
-            /** @var \Magento\Customer\Model\Attribute $attribute */
-            $attribute = $this->attributeResolver->getModelByAttribute(
-                \Magento\Customer\Api\AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS,
-                $attributeMetadata
-            );
-            $usedInForms = $attribute->getUsedInForms();
-            $isAllowed = in_array($formName, $usedInForms, true);
-        }
-
-        return $isAllowed;
-    }
 }
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index 59205a4d918384c7bedc306bf80f07c32bbdc1a9..ba646549f6919a5f933831cdb33b05930988a2d8 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -531,12 +531,8 @@ class AccountManagement implements AccountManagementInterface
                     $this->getEmailNotification()->passwordResetConfirmation($customer);
                     break;
                 default:
-                    throw new InputException(
-                        __(
-                            'Invalid value of "%value" provided for the %fieldName field.',
-                            ['value' => $template, 'fieldName' => 'email type']
-                        )
-                    );
+                    $this->handleUnknownTemplate($template);
+                    break;
             }
             return true;
         } catch (MailException $e) {
@@ -546,6 +542,25 @@ class AccountManagement implements AccountManagementInterface
         return false;
     }
 
+    /**
+     * Handle not supported template
+     *
+     * @param string $template
+     * @throws InputException
+     */
+    private function handleUnknownTemplate($template)
+    {
+        throw new InputException(__(
+            'Invalid value of "%value" provided for the %fieldName field. Possible values: %template1 or %template2.',
+            [
+                'value' => $template,
+                'fieldName' => 'template',
+                'template1' => AccountManagement::EMAIL_REMINDER,
+                'template2' => AccountManagement::EMAIL_RESET
+            ]
+        ));
+    }
+
     /**
      * {@inheritdoc}
      */
diff --git a/app/code/Magento/Customer/Model/AttributeChecker.php b/app/code/Magento/Customer/Model/AttributeChecker.php
new file mode 100644
index 0000000000000000000000000000000000000000..6cc27697ccff7cc5baf0cc8141e9001b2b2f908d
--- /dev/null
+++ b/app/code/Magento/Customer/Model/AttributeChecker.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model;
+
+use Magento\Customer\Api\AddressMetadataInterface;
+use Magento\Customer\Api\AddressMetadataManagementInterface;
+use Magento\Customer\Model\Metadata\AttributeResolver;
+use Magento\Framework\App\Helper\Context;
+
+/**
+ * Customer attribute checker.
+ */
+class AttributeChecker
+{
+    /**
+     * @var AddressMetadataInterface
+     */
+    private $addressMetadata;
+
+    /**
+     * @var AttributeResolver
+     */
+    private $attributeResolver;
+
+    /**
+     * @param AddressMetadataInterface $addressMetadata
+     * @param AttributeResolver $attributeResolver
+     */
+    public function __construct(
+        AddressMetadataInterface $addressMetadata,
+        AttributeResolver $attributeResolver
+    ) {
+        $this->addressMetadata = $addressMetadata;
+        $this->attributeResolver = $attributeResolver;
+    }
+
+    /**
+     * Checks whether it is allowed to show an attribute on the form
+     *
+     * This check relies on the attribute's property 'getUsedInForms' which contains a list of forms
+     * where allowed to render specified attribute.
+     *
+     * @param string $attributeCode
+     * @param string $formName
+     * @return bool
+     */
+    public function isAttributeAllowedOnForm($attributeCode, $formName)
+    {
+        $isAllowed = false;
+        $attributeMetadata = $this->addressMetadata->getAttributeMetadata($attributeCode);
+        if ($attributeMetadata) {
+            /** @var Attribute $attribute */
+            $attribute = $this->attributeResolver->getModelByAttribute(
+                AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS,
+                $attributeMetadata
+            );
+            $usedInForms = $attribute->getUsedInForms();
+            $isAllowed = in_array($formName, $usedInForms, true);
+        }
+
+        return $isAllowed;
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php
index 7b42e8b7774c85cd026f0fa436fcde737337aed7..50785247d7965b4beaa573814b74179f277e6f8d 100644
--- a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php
@@ -7,7 +7,6 @@
 namespace Magento\Customer\Test\Unit\Helper;
 
 use Magento\Customer\Api\AddressMetadataInterface;
-use Magento\Customer\Api\AddressMetadataManagementInterface;
 use Magento\Customer\Api\CustomerMetadataInterface;
 
 /**
@@ -36,9 +35,6 @@ class AddressTest extends \PHPUnit\Framework\TestCase
     /** @var \Magento\Customer\Model\Address\Config|\PHPUnit_Framework_MockObject_MockObject */
     protected $addressConfig;
 
-    /** @var  \Magento\Customer\Model\Metadata\AttributeResolver|\PHPUnit_Framework_MockObject_MockObject */
-    protected $attributeResolver;
-
     /** @var \PHPUnit_Framework_MockObject_MockObject|AddressMetadataInterface */
     private $addressMetadataService;
 
@@ -55,7 +51,6 @@ class AddressTest extends \PHPUnit\Framework\TestCase
         $this->customerMetadataService = $arguments['customerMetadataService'];
         $this->addressConfig = $arguments['addressConfig'];
         $this->addressMetadataService = $arguments['addressMetadataService'];
-        $this->attributeResolver = $arguments['attributeResolver'];
 
         $this->helper = $objectManagerHelper->getObject($className, $arguments);
     }
@@ -408,68 +403,4 @@ class AddressTest extends \PHPUnit\Framework\TestCase
             ['invalid_code', false],
         ];
     }
-
-    /**
-     * @dataProvider attributeOnFormDataProvider
-     * @param bool $isAllowed
-     * @param bool $isMetadataExists
-     * @param string $attributeCode
-     * @param string $formName
-     * @param array $attributeFormsList
-     */
-    public function testIsAttributeAllowedOnForm(
-        $isAllowed,
-        $isMetadataExists,
-        $attributeCode,
-        $formName,
-        array $attributeFormsList
-    ) {
-        $attributeMetadata = null;
-        if ($isMetadataExists) {
-            $attributeMetadata = $this->getMockBuilder(\Magento\Customer\Api\Data\AttributeMetadataInterface::class)
-                ->getMockForAbstractClass();
-            $attribute = $this->getMockBuilder(\Magento\Customer\Model\Attribute::class)
-                ->disableOriginalConstructor()
-                ->getMock();
-            $this->attributeResolver->expects($this->once())
-                ->method('getModelByAttribute')
-                ->with(AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS, $attributeMetadata)
-                ->willReturn($attribute);
-            $attribute->expects($this->once())
-                ->method('getUsedInForms')
-                ->willReturn($attributeFormsList);
-        }
-        $this->addressMetadataService->expects($this->once())
-            ->method('getAttributeMetadata')
-            ->with($attributeCode)
-            ->willReturn($attributeMetadata);
-        $this->assertEquals($isAllowed, $this->helper->isAttributeAllowedOnForm($attributeCode, $formName));
-    }
-
-    public function attributeOnFormDataProvider()
-    {
-        return [
-            'metadata not exists' => [
-                'isAllowed' => false,
-                'isMetadataExists' => false,
-                'attributeCode' => 'attribute_code',
-                'formName' => 'form_name',
-                'attributeFormsList' => [],
-                ],
-            'form not in the list' => [
-                'isAllowed' => false,
-                'isMetadataExists' => true,
-                'attributeCode' => 'attribute_code',
-                'formName' => 'form_name',
-                'attributeFormsList' => ['form_1', 'form_2'],
-                ],
-            'allowed' => [
-                'isAllowed' => true,
-                'isMetadataExists' => true,
-                'attributeCode' => 'attribute_code',
-                'formName' => 'form_name',
-                'attributeFormsList' => ['form_name', 'form_1', 'form_2'],
-            ],
-        ];
-    }
 }
diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
index 34662eecc0c1c9e41d6169e0fcfdb74f57330e58..2a6b9fe6fd4ea44edfed07f85aaaf36d69357eca 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
@@ -1173,10 +1173,6 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase
         $this->assertTrue($this->accountManagement->initiatePasswordReset($email, $template));
     }
 
-    /**
-     * @expectedException \Magento\Framework\Exception\InputException
-     * @expectedExceptionMessage Invalid value of "" provided for the email type field
-     */
     public function testInitiatePasswordResetNoTemplate()
     {
         $storeId = 1;
@@ -1192,6 +1188,10 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase
 
         $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash);
 
+        $this->expectException(\Magento\Framework\Exception\InputException::class);
+        $this->expectExceptionMessage(
+            'Invalid value of "" provided for the template field. Possible values: email_reminder or email_reset.'
+        );
         $this->accountManagement->initiatePasswordReset($email, $template);
     }
 
diff --git a/app/code/Magento/Customer/Test/Unit/Model/AttributeCheckerTest.php b/app/code/Magento/Customer/Test/Unit/Model/AttributeCheckerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..480f5be96e318367a34ecfa3bfff0d2f9b31330e
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/AttributeCheckerTest.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Unit\Model;
+
+use Magento\Customer\Api\AddressMetadataInterface;
+use Magento\Customer\Api\AddressMetadataManagementInterface;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Model\AttributeChecker;
+use Magento\Customer\Model\Attribute;
+use Magento\Customer\Model\Metadata\AttributeResolver;
+
+class AttributeCheckerTest extends \PHPUnit\Framework\TestCase
+{
+    /** @var AttributeChecker|\PHPUnit_Framework_MockObject_MockObject */
+    private $model;
+
+    /** @var  AttributeResolver|\PHPUnit_Framework_MockObject_MockObject */
+    private $attributeResolver;
+
+    /** @var AddressMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    private $addressMetadataService;
+
+    protected function setUp()
+    {
+        $this->addressMetadataService = $this->getMockForAbstractClass(AddressMetadataInterface::class);
+        $this->attributeResolver = $this->getMockBuilder(AttributeResolver::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = new AttributeChecker(
+            $this->addressMetadataService,
+            $this->attributeResolver
+        );
+    }
+
+    /**
+     * @param bool $isAllowed
+     * @param bool $isMetadataExists
+     * @param string $attributeCode
+     * @param string $formName
+     * @param array $attributeFormsList
+     *
+     * @dataProvider attributeOnFormDataProvider
+     */
+    public function testIsAttributeAllowedOnForm(
+        $isAllowed,
+        $isMetadataExists,
+        $attributeCode,
+        $formName,
+        array $attributeFormsList
+    ) {
+        $attributeMetadata = null;
+        if ($isMetadataExists) {
+            $attributeMetadata = $this->getMockForAbstractClass(AttributeMetadataInterface::class);
+            $attribute = $this->getMockBuilder(Attribute::class)
+                ->disableOriginalConstructor()
+                ->getMock();
+            $this->attributeResolver->expects($this->once())
+                ->method('getModelByAttribute')
+                ->with(AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS, $attributeMetadata)
+                ->willReturn($attribute);
+            $attribute->expects($this->once())
+                ->method('getUsedInForms')
+                ->willReturn($attributeFormsList);
+        }
+        $this->addressMetadataService->expects($this->once())
+            ->method('getAttributeMetadata')
+            ->with($attributeCode)
+            ->willReturn($attributeMetadata);
+
+        $this->assertEquals($isAllowed, $this->model->isAttributeAllowedOnForm($attributeCode, $formName));
+    }
+
+    public function attributeOnFormDataProvider()
+    {
+        return [
+            'metadata not exists' => [
+                'isAllowed' => false,
+                'isMetadataExists' => false,
+                'attributeCode' => 'attribute_code',
+                'formName' => 'form_name',
+                'attributeFormsList' => [],
+                ],
+            'form not in the list' => [
+                'isAllowed' => false,
+                'isMetadataExists' => true,
+                'attributeCode' => 'attribute_code',
+                'formName' => 'form_name',
+                'attributeFormsList' => ['form_1', 'form_2'],
+                ],
+            'allowed' => [
+                'isAllowed' => true,
+                'isMetadataExists' => true,
+                'attributeCode' => 'attribute_code',
+                'formName' => 'form_name',
+                'attributeFormsList' => ['form_name', 'form_1', 'form_2'],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index 0e8ebf957edf57b29157e54f2040066ac127f53b..61fcb62932992ab4e16bce2e0b347388bb6be42e 100644
--- a/app/code/Magento/Customer/composer.json
+++ b/app/code/Magento/Customer/composer.json
@@ -29,7 +29,7 @@
         "magento/module-customer-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml
index c35e9fa4b4c8a81e4213c397797dc9db9f00b75a..da4b80536e631781050273dbe407e57f41eaa6f2 100644
--- a/app/code/Magento/Customer/etc/config.xml
+++ b/app/code/Magento/Customer/etc/config.xml
@@ -56,7 +56,7 @@
                 <fax_show/>
             </address>
             <startup>
-                <redirect_dashboard>1</redirect_dashboard>
+                <redirect_dashboard>0</redirect_dashboard>
             </startup>
             <address_templates>
                 <text>{{depend prefix}}{{var prefix}} {{/depend}}{{var firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var lastname}}{{depend suffix}} {{var suffix}}{{/depend}}
diff --git a/app/code/Magento/Customer/etc/webapi.xml b/app/code/Magento/Customer/etc/webapi.xml
index 26a9c41f20c0d8b80d535f2a8ebe59cd322e5774..c536e26bcc82aa38bdd976fe7a0b7aad1d652311 100644
--- a/app/code/Magento/Customer/etc/webapi.xml
+++ b/app/code/Magento/Customer/etc/webapi.xml
@@ -128,7 +128,7 @@
             <resource ref="anonymous"/>
         </resources>
     </route>
-    <route url="/V1/customers/:id" method="PUT">
+    <route url="/V1/customers/:customerId" method="PUT">
         <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="save"/>
         <resources>
             <resource ref="Magento_Customer::manage"/>
diff --git a/app/code/Magento/CustomerAnalytics/composer.json b/app/code/Magento/CustomerAnalytics/composer.json
index 36e7492decc50fdaef50668ad2059820632dcc47..d34d6ba751e2afcd8d0113cdfb22baa1d508c922 100644
--- a/app/code/Magento/CustomerAnalytics/composer.json
+++ b/app/code/Magento/CustomerAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-customer": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
index bee4479526037eebc841b70b3e3344efa345e13c..016dca2fa526c5cca2ba86387772fe3dbccdfe40 100644
--- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
@@ -270,13 +270,29 @@ class Customer extends AbstractCustomer
             $this->_connection->insertOnDuplicate(
                 $this->_entityTable,
                 $entitiesToUpdate,
-                $this->customerFields
+                $this->getCustomerEntityFieldsToUpdate($entitiesToUpdate)
             );
         }
 
         return $this;
     }
 
+    /**
+     * Filter the entity that are being updated so we only change fields found in the importer file
+     *
+     * @param array $entitiesToUpdate
+     * @return array
+     */
+    private function getCustomerEntityFieldsToUpdate(array $entitiesToUpdate): array
+    {
+        $firstCustomer = reset($entitiesToUpdate);
+        $columnsToUpdate = array_keys($firstCustomer);
+        $customerFieldsToUpdate = array_filter($this->customerFields, function ($field) use ($columnsToUpdate) {
+            return in_array($field, $columnsToUpdate);
+        });
+        return $customerFieldsToUpdate;
+    }
+
     /**
      * Save customer attributes.
      *
diff --git a/app/code/Magento/Deploy/Model/Filesystem.php b/app/code/Magento/Deploy/Model/Filesystem.php
index 3dd28f4d3e82090d43fd881ad281d19c5e7465fa..0557914f48d24b1c26f46099733f2c91d8600b99 100644
--- a/app/code/Magento/Deploy/Model/Filesystem.php
+++ b/app/code/Magento/Deploy/Model/Filesystem.php
@@ -5,17 +5,16 @@
  */
 namespace Magento\Deploy\Model;
 
-use Symfony\Component\Console\Output\OutputInterface;
-use Magento\Framework\App\State;
-use Magento\Framework\App\DeploymentConfig\Writer;
 use Magento\Framework\App\Filesystem\DirectoryList;
 use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Validator\Locale;
 use Magento\User\Model\ResourceModel\User\Collection as UserCollection;
+use Symfony\Component\Console\Output\OutputInterface;
 
 /**
  * Generate static files, compile
  *
- * Сlear generated/code, generated/metadata/, var/view_preprocessed and pub/static directories
+ * Clear generated/code, generated/metadata/, var/view_preprocessed and pub/static directories
  *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
@@ -50,21 +49,6 @@ class Filesystem
      */
     const DEFAULT_THEME = 'Magento/blank';
 
-    /**
-     * @var \Magento\Framework\App\DeploymentConfig\Writer
-     */
-    private $writer;
-
-    /**
-     * @var \Magento\Framework\App\DeploymentConfig\Reader
-     */
-    private $reader;
-
-    /**
-     * @var \Magento\Framework\ObjectManagerInterface
-     */
-    private $objectManager;
-
     /**
      * @var \Magento\Framework\Filesystem
      */
@@ -101,33 +85,35 @@ class Filesystem
     private $userCollection;
 
     /**
-     * @param \Magento\Framework\App\DeploymentConfig\Writer $writer
-     * @param \Magento\Framework\App\DeploymentConfig\Reader $reader
-     * @param \Magento\Framework\ObjectManagerInterface $objectManager
+     * @var Locale
+     */
+    private $locale;
+
+    /**
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\App\Filesystem\DirectoryList $directoryList
      * @param \Magento\Framework\Filesystem\Driver\File $driverFile
      * @param \Magento\Store\Model\Config\StoreView $storeView
      * @param \Magento\Framework\ShellInterface $shell
+     * @param UserCollection $userCollection
+     * @param Locale $locale
      */
     public function __construct(
-        \Magento\Framework\App\DeploymentConfig\Writer $writer,
-        \Magento\Framework\App\DeploymentConfig\Reader $reader,
-        \Magento\Framework\ObjectManagerInterface $objectManager,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\App\Filesystem\DirectoryList $directoryList,
         \Magento\Framework\Filesystem\Driver\File $driverFile,
         \Magento\Store\Model\Config\StoreView $storeView,
-        \Magento\Framework\ShellInterface $shell
+        \Magento\Framework\ShellInterface $shell,
+        UserCollection $userCollection,
+        Locale $locale
     ) {
-        $this->writer = $writer;
-        $this->reader = $reader;
-        $this->objectManager = $objectManager;
         $this->filesystem = $filesystem;
         $this->directoryList = $directoryList;
         $this->driverFile = $driverFile;
         $this->storeView = $storeView;
         $this->shell = $shell;
+        $this->userCollection = $userCollection;
+        $this->locale = $locale;
         $this->functionCallPath =
             PHP_BINARY . ' -f ' . BP . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'magento ';
     }
@@ -141,7 +127,7 @@ class Filesystem
     public function regenerateStatic(
         OutputInterface $output
     ) {
-        // Сlear generated/code, generated/metadata/, var/view_preprocessed and pub/static directories
+        // Clear generated/code, generated/metadata/, var/view_preprocessed and pub/static directories
         $this->cleanupFilesystem(
             [
                 DirectoryList::CACHE,
@@ -193,7 +179,7 @@ class Filesystem
     private function getAdminUserInterfaceLocales()
     {
         $locales = [];
-        foreach ($this->getUserCollection() as $user) {
+        foreach ($this->userCollection as $user) {
             $locales[] = $user->getInterfaceLocale();
         }
         return $locales;
@@ -203,6 +189,7 @@ class Filesystem
      * Get used store and admin user locales
      *
      * @return array
+     * @throws \InvalidArgumentException if unknown locale is provided by the store configuration
      */
     private function getUsedLocales()
     {
@@ -210,25 +197,18 @@ class Filesystem
             $this->storeView->retrieveLocales(),
             $this->getAdminUserInterfaceLocales()
         );
-        return array_unique($usedLocales);
-    }
-
-    /**
-     * Get user collection
-     *
-     * @return UserCollection
-     * @deprecated 100.1.0 Added to not break backward compatibility of the constructor signature
-     * by injecting the new dependency directly.
-     * The method can be removed in a future major release, when constructor signature can be changed.
-     */
-    private function getUserCollection()
-    {
-        if (!($this->userCollection instanceof UserCollection)) {
-            return \Magento\Framework\App\ObjectManager::getInstance()->get(
-                UserCollection::class
-            );
-        }
-        return $this->userCollection;
+        return array_map(
+            function ($locale) {
+                if (!$this->locale->isValid($locale)) {
+                    throw new \InvalidArgumentException(
+                        $locale .
+                        ' argument has invalid value, run info:language:list for list of available locales'
+                    );
+                }
+                return $locale;
+            },
+            array_unique($usedLocales)
+        );
     }
 
     /**
diff --git a/app/code/Magento/Deploy/Package/Bundle/RequireJs.php b/app/code/Magento/Deploy/Package/Bundle/RequireJs.php
index 73a15554f8b78f8a76f4aef673c07124251c4cfc..c7c9e5315c7abe7a14929d79d910eda2ee9ce0a9 100644
--- a/app/code/Magento/Deploy/Package/Bundle/RequireJs.php
+++ b/app/code/Magento/Deploy/Package/Bundle/RequireJs.php
@@ -240,9 +240,12 @@ class RequireJs implements BundleInterface
     private function getFileContent($sourcePath)
     {
         if (!isset($this->fileContent[$sourcePath])) {
-            $this->fileContent[$sourcePath] = utf8_encode(
-                $this->staticDir->readFile($this->minification->addMinifiedSign($sourcePath))
-            );
+            $content = $this->staticDir->readFile($this->minification->addMinifiedSign($sourcePath));
+            if (mb_detect_encoding($content) !== "UTF-8") {
+                $content = mb_convert_encoding($content, "UTF-8");
+            }
+
+            $this->fileContent[$sourcePath] = $content;
         }
         return $this->fileContent[$sourcePath];
     }
diff --git a/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php b/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php
index 673f31c04ffd3c51c4dca01bd711908c71025120..d14c86c4a3264ca49f00e0f4c315dcaaa715e7ad 100644
--- a/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php
+++ b/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php
@@ -5,47 +5,64 @@
  */
 namespace Magento\Deploy\Test\Unit\Model;
 
+use Magento\Deploy\Model\Filesystem as DeployFilesystem;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\WriteInterface;
+use Magento\Framework\ObjectManagerInterface;
+use Magento\Framework\ShellInterface;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Store\Model\Config\StoreView;
+use Magento\User\Model\ResourceModel\User\Collection;
+use Magento\User\Model\User;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+use Symfony\Component\Console\Output\OutputInterface;
+use Magento\Framework\Validator\Locale;
+use Magento\Framework\Setup\Lists;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class FilesystemTest extends \PHPUnit\Framework\TestCase
 {
     /**
-     * @var \Magento\Store\Model\Config\StoreView
+     * @var StoreView|MockObject
      */
-    private $storeViewMock;
+    private $storeView;
 
     /**
-     * @var \Magento\Framework\ShellInterface
+     * @var ShellInterface|MockObject
      */
-    private $shellMock;
+    private $shell;
 
     /**
-     * @var \Magento\User\Model\ResourceModel\User\Collection
+     * @var OutputInterface|MockObject
      */
-    private $userCollectionMock;
+    private $output;
 
     /**
-     * @var \Symfony\Component\Console\Output\OutputInterface
+     * @var Filesystem|MockObject
      */
-    private $outputMock;
+    private $filesystem;
 
     /**
-     * @var \Magento\Framework\Filesystem
+     * @var WriteInterface|MockObject
      */
-    private $filesystemMock;
+    private $directoryWrite;
 
     /**
-     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
+     * @var Collection|MockObject
      */
-    private $directoryWriteMock;
+    private $userCollection;
 
     /**
-     * @var \Magento\Framework\ObjectManagerInterface
+     * @var ObjectManagerInterface|MockObject
      */
-    private $objectManagerMock;
+    private $objectManager;
 
     /**
-     * @var \Magento\Deploy\Model\Filesystem
+     * @var DeployFilesystem
      */
-    private $filesystem;
+    private $deployFilesystem;
 
     /**
      * @var string
@@ -54,75 +71,127 @@ class FilesystemTest extends \PHPUnit\Framework\TestCase
 
     protected function setUp()
     {
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-
-        $this->storeViewMock = $this->createMock(\Magento\Store\Model\Config\StoreView::class);
-        $this->shellMock = $this->createMock(\Magento\Framework\ShellInterface::class);
-        $this->userCollectionMock = $this->createMock(\Magento\User\Model\ResourceModel\User\Collection::class);
-        $this->outputMock = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class);
-        $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class);
-        $this->filesystemMock = $this->createMock(\Magento\Framework\Filesystem::class);
-        $this->directoryWriteMock = $this->createMock(\Magento\Framework\Filesystem\Directory\WriteInterface::class);
-        $this->filesystemMock->expects($this->any())
-            ->method('getDirectoryWrite')
-            ->willReturn($this->directoryWriteMock);
-        $this->filesystem = $objectManager->getObject(
-            \Magento\Deploy\Model\Filesystem::class,
+        $objectManager = new ObjectManager($this);
+
+        $this->storeView = $this->createMock(StoreView::class);
+        $this->shell = $this->createMock(ShellInterface::class);
+        $this->output = $this->createMock(OutputInterface::class);
+        $this->objectManager = $this->createMock(ObjectManagerInterface::class);
+        $this->filesystem = $this->createMock(Filesystem::class);
+        $this->directoryWrite = $this->createMock(WriteInterface::class);
+        $this->filesystem->method('getDirectoryWrite')
+            ->willReturn($this->directoryWrite);
+
+        $this->userCollection = $this->createMock(Collection::class);
+
+        $lists = $this->getMockBuilder(Lists::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $lists->method('getLocaleList')
+            ->willReturn([
+                'fr_FR' => 'France',
+                'de_DE' => 'Germany',
+                'nl_NL' => 'Netherlands',
+                'en_US' => 'USA'
+            ]);
+        $locale = $objectManager->getObject(Locale::class, ['lists' => $lists]);
+
+        $this->deployFilesystem = $objectManager->getObject(
+            DeployFilesystem::class,
             [
-                'storeView' => $this->storeViewMock,
-                'shell' => $this->shellMock,
-                'filesystem' => $this->filesystemMock
+                'storeView' => $this->storeView,
+                'shell' => $this->shell,
+                'filesystem' => $this->filesystem,
+                'userCollection' => $this->userCollection,
+                'locale' => $locale
             ]
         );
 
-        $userCollection = new \ReflectionProperty(\Magento\Deploy\Model\Filesystem::class, 'userCollection');
-        $userCollection->setAccessible(true);
-        $userCollection->setValue($this->filesystem, $this->userCollectionMock);
-
         $this->cmdPrefix = PHP_BINARY . ' -f ' . BP . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'magento ';
     }
 
     public function testRegenerateStatic()
     {
         $storeLocales = ['fr_FR', 'de_DE', 'nl_NL'];
-        $adminUserInterfaceLocales = ['de_DE', 'en_US'];
-        $this->storeViewMock->expects($this->once())
-            ->method('retrieveLocales')
+        $this->storeView->method('retrieveLocales')
             ->willReturn($storeLocales);
-        $userMock = $this->createMock(\Magento\User\Model\User::class);
-        $userMock->expects($this->once())
-            ->method('getInterfaceLocale')
-            ->willReturn('en_US');
-        $this->userCollectionMock->expects($this->once())
-            ->method('getIterator')
-            ->willReturn(new \ArrayIterator([$userMock]));
-
-        $usedLocales = array_unique(
-            array_merge($storeLocales, $adminUserInterfaceLocales)
-        );
-        $staticContentDeployCmd = $this->cmdPrefix . 'setup:static-content:deploy -f '
-            . implode(' ', $usedLocales);
+
         $setupDiCompileCmd = $this->cmdPrefix . 'setup:di:compile';
-        $this->shellMock->expects($this->at(0))
+        $this->shell->expects(self::at(0))
             ->method('execute')
             ->with($setupDiCompileCmd);
-        $this->shellMock->expects($this->at(1))
+
+        $this->initAdminLocaleMock('en_US');
+
+        $usedLocales = ['fr_FR', 'de_DE', 'nl_NL', 'en_US'];
+        $staticContentDeployCmd = $this->cmdPrefix . 'setup:static-content:deploy -f '
+            . implode(' ', $usedLocales);
+        $this->shell->expects(self::at(1))
             ->method('execute')
             ->with($staticContentDeployCmd);
 
-        $this->outputMock->expects($this->at(0))
+        $this->output->expects(self::at(0))
             ->method('writeln')
             ->with('Starting compilation');
-        $this->outputMock->expects($this->at(2))
+        $this->output->expects(self::at(2))
             ->method('writeln')
             ->with('Compilation complete');
-        $this->outputMock->expects($this->at(3))
+        $this->output->expects(self::at(3))
             ->method('writeln')
             ->with('Starting deployment of static content');
-        $this->outputMock->expects($this->at(5))
+        $this->output->expects(self::at(5))
             ->method('writeln')
             ->with('Deployment of static content complete');
 
-        $this->filesystem->regenerateStatic($this->outputMock);
+        $this->deployFilesystem->regenerateStatic($this->output);
+    }
+
+    /**
+     * Checks a case when configuration contains incorrect locale code.
+     *
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage ;echo argument has invalid value, run info:language:list for list of available locales
+     */
+    public function testGenerateStaticForNotAllowedStoreViewLocale()
+    {
+        $storeLocales = ['fr_FR', 'de_DE', ';echo'];
+        $this->storeView->method('retrieveLocales')
+            ->willReturn($storeLocales);
+
+        $this->initAdminLocaleMock('en_US');
+
+        $this->deployFilesystem->regenerateStatic($this->output);
+    }
+
+    /**
+     * Checks as case when admin locale is incorrect.
+     *
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage ;echo argument has invalid value, run info:language:list for list of available locales
+     */
+    public function testGenerateStaticForNotAllowedAdminLocale()
+    {
+        $storeLocales = ['fr_FR', 'de_DE', 'en_US'];
+        $this->storeView->method('retrieveLocales')
+            ->willReturn($storeLocales);
+
+        $this->initAdminLocaleMock(';echo');
+
+        $this->deployFilesystem->regenerateStatic($this->output);
+    }
+
+    /**
+     * Initializes admin user locale.
+     *
+     * @param string $locale
+     */
+    private function initAdminLocaleMock($locale)
+    {
+        /** @var User|MockObject $user */
+        $user = $this->createMock(User::class);
+        $user->method('getInterfaceLocale')
+            ->willReturn($locale);
+        $this->userCollection->method('getIterator')
+            ->willReturn(new \ArrayIterator([$user]));
     }
 }
diff --git a/app/code/Magento/Deploy/composer.json b/app/code/Magento/Deploy/composer.json
index 8092f80be0e1a98701aaf118744ea78f11ec4269..e33d2e72f64a418362a935618ca5d76e7cd5290f 100644
--- a/app/code/Magento/Deploy/composer.json
+++ b/app/code/Magento/Deploy/composer.json
@@ -10,7 +10,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Developer/composer.json b/app/code/Magento/Developer/composer.json
index a0782be817c0afdd3be09e8bed2de8d6fcc7c130..518f2cc77c07e04f14f14b92534d556573762f72 100644
--- a/app/code/Magento/Developer/composer.json
+++ b/app/code/Magento/Developer/composer.json
@@ -8,7 +8,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php
index 8bfa2fc7d64ccb9c3fba467ab885d0b1fd9cba67..2eb8f582c54fa57a7e3aceecb5945fe6ef8ad99a 100644
--- a/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php
+++ b/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php
@@ -369,7 +369,7 @@ class FilterTest extends \PHPUnit\Framework\TestCase
                 '<html><head><style type="text/css">div { color: #111; }</style></head><p></p></html>',
                 'p { color: #000 }',
                 [
-                    '<head><style type="text/css">div { color: #111; }</style></head>',
+                    '<style type="text/css">div { color: #111; }</style>',
                     '<p style="color: #000;"></p>',
                 ],
             ],
diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json
index bf7eadd9f708f1e305afcf3e4ca0b13e1fe07d0c..b74763a22ec14456b20a59850b520ef9b377e2c4 100644
--- a/app/code/Magento/GoogleAnalytics/composer.json
+++ b/app/code/Magento/GoogleAnalytics/composer.json
@@ -12,7 +12,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
index 91cfbefbd57a22f0071d1508e2039fbec7a65d1c..e490ee4018376c084dc900e165ccd7f5bae30dd7 100644
--- a/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
+++ b/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
@@ -39,7 +39,7 @@ class Download extends \Magento\ImportExport\Controller\Adminhtml\History
      */
     public function execute()
     {
-        $fileName = $this->getRequest()->getParam('filename');
+        $fileName = basename($this->getRequest()->getParam('filename'));
 
         /** @var \Magento\ImportExport\Helper\Report $reportHelper */
         $reportHelper = $this->_objectManager->get(\Magento\ImportExport\Helper\Report::class);
diff --git a/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php b/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
index 73b97dfc6775104bdd104ea13542ae8a28aefee2..3eb14e673f648bc54ba0cb116b9c64c9ebc9ff6b 100644
--- a/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
+++ b/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
@@ -72,8 +72,9 @@ class DownloadTest extends \PHPUnit\Framework\TestCase
      */
     protected function setUp()
     {
-        $this->request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getParam']);
-        $this->request->expects($this->any())->method('getParam')->with('filename')->willReturn('filename');
+        $this->request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
+            ->disableOriginalConstructor()
+            ->getMock();
         $this->reportHelper = $this->createPartialMock(
             \Magento\ImportExport\Helper\Report::class,
             ['importFileExists', 'getReportSize', 'getReportOutput']
@@ -126,11 +127,12 @@ class DownloadTest extends \PHPUnit\Framework\TestCase
     }
 
     /**
-     * Test execute()
+     * Tests execute()
      */
     public function testExecute()
     {
-        $this->reportHelper->expects($this->any())->method('importFileExists')->willReturn(true);
+        $this->reportHelper->expects($this->atLeastOnce())->method('importFileExists')->willReturn(true);
+
         $this->resultRaw->expects($this->once())->method('setContents');
         $this->downloadController->execute();
     }
@@ -140,7 +142,8 @@ class DownloadTest extends \PHPUnit\Framework\TestCase
      */
     public function testExecuteFileNotFound()
     {
-        $this->reportHelper->expects($this->any())->method('importFileExists')->willReturn(false);
+        $this->request->method('getParam')->with('filename')->willReturn('filename');
+        $this->reportHelper->method('importFileExists')->willReturn(false);
         $this->resultRaw->expects($this->never())->method('setContents');
         $this->downloadController->execute();
     }
diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json
index 623346e0a77828fce1990096149757fcec327a0d..23ed2f6346ef7b45b6c148f940eb27a1481dcf54 100644
--- a/app/code/Magento/ImportExport/composer.json
+++ b/app/code/Magento/ImportExport/composer.json
@@ -12,7 +12,7 @@
         "ext-ctype": "*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CarrierFinder.php b/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CarrierFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..0eb2afd04140a09cb10a74dabee705f65f401322
--- /dev/null
+++ b/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CarrierFinder.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\InstantPurchase\Model\ShippingMethodChoose;
+
+use Magento\Customer\Model\Address;
+use Magento\Framework\DataObject;
+use Magento\Shipping\Model\Config as CarriersConfig;
+use Magento\Store\Model\StoreManagerInterface;
+
+/**
+ * Collect shipping rates for customer address without packaging estiamtion.
+ */
+class CarrierFinder
+{
+    /**
+     * @var CarriersConfig
+     */
+    private $carriersConfig;
+
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
+
+    /**
+     * CarrierFinder constructor.
+     * @param CarriersConfig $carriersConfig
+     * @param StoreManagerInterface $storeManager
+     */
+    public function __construct(
+        CarriersConfig $carriersConfig,
+        StoreManagerInterface $storeManager
+    ) {
+        $this->carriersConfig = $carriersConfig;
+        $this->storeManager = $storeManager;
+    }
+
+    /**
+     * Finds carriers delivering to customer address
+     *
+     * @param Address $address
+     * @return array
+     */
+    public function getCarriersForCustomerAddress(Address $address): array
+    {
+        $request = new DataObject([
+            'dest_country_id' => $address->getCountryId()
+        ]);
+
+        $carriers = [];
+        foreach ($this->carriersConfig->getActiveCarriers($this->storeManager->getStore()->getId()) as $carrier) {
+            $checked = $carrier->checkAvailableShipCountries($request);
+            if (false !== $checked && null === $checked->getErrorMessage() && !empty($checked->getAllowedMethods())) {
+                $carriers[] = $checked;
+            }
+        }
+
+        return $carriers;
+    }
+}
diff --git a/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CheapestMethodChooser.php b/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CheapestMethodChooser.php
index a9abf09c8b22c94f645ebd21d9341479b4297444..f01bde29cbc7d511874686a47b6717cad8473d30 100644
--- a/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CheapestMethodChooser.php
+++ b/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/CheapestMethodChooser.php
@@ -6,7 +6,6 @@
 namespace Magento\InstantPurchase\Model\ShippingMethodChoose;
 
 use Magento\Customer\Model\Address;
-use Magento\Quote\Api\Data\ShippingMethodInterface;
 use Magento\Quote\Api\Data\ShippingMethodInterfaceFactory;
 
 /**
@@ -20,21 +19,21 @@ class CheapestMethodChooser implements ShippingMethodChooserInterface
     private $shippingMethodFactory;
 
     /**
-     * @var ShippingRateFinder
+     * @var CarrierFinder
      */
-    private $shippingRateFinder;
+    private $carrierFinder;
 
     /**
      * CheapestMethodChooser constructor.
      * @param ShippingMethodInterfaceFactory $shippingMethodFactory
-     * @param ShippingRateFinder $shippingRateFinder
+     * @param CarrierFinder $carrierFinder
      */
     public function __construct(
         ShippingMethodInterfaceFactory $shippingMethodFactory,
-        ShippingRateFinder $shippingRateFinder
+        CarrierFinder $carrierFinder
     ) {
         $this->shippingMethodFactory = $shippingMethodFactory;
-        $this->shippingRateFinder = $shippingRateFinder;
+        $this->carrierFinder = $carrierFinder;
     }
 
     /**
@@ -58,7 +57,7 @@ class CheapestMethodChooser implements ShippingMethodChooserInterface
      */
     private function areShippingMethodsAvailable(Address $address): bool
     {
-        $shippingRatesForAddress = $this->shippingRateFinder->getRatesForCustomerAddress($address);
-        return !empty($shippingRatesForAddress);
+        $carriersForAddress = $this->carrierFinder->getCarriersForCustomerAddress($address);
+        return !empty($carriersForAddress);
     }
 }
diff --git a/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/ShippingRateFinder.php b/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/ShippingRateFinder.php
deleted file mode 100644
index 065f3fe946e7109bbec93b4cb08feab3ee858373..0000000000000000000000000000000000000000
--- a/app/code/Magento/InstantPurchase/Model/ShippingMethodChoose/ShippingRateFinder.php
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\InstantPurchase\Model\ShippingMethodChoose;
-
-use Magento\Customer\Model\Address;
-use Magento\Quote\Model\Quote\Address\RateCollectorInterfaceFactory;
-use Magento\Quote\Model\Quote\Address\RateRequest;
-use Magento\Quote\Model\Quote\Address\RateRequestFactory;
-use Magento\Store\Model\StoreManagerInterface;
-
-/**
- * Collect shipping rates for customer address without packaging estiamtion.
- */
-class ShippingRateFinder
-{
-    /**
-     * @var RateRequestFactory
-     */
-    private $rateRequestFactory;
-    /**
-     * @var StoreManagerInterface
-     */
-    private $storeManager;
-    /**
-     * @var RateCollectorInterfaceFactory
-     */
-    private $rateCollectorFactory;
-
-    /**
-     * RateCheck constructor.
-     * @param RateRequestFactory $rateRequestFactory
-     * @param RateCollectorInterfaceFactory $rateCollectorFactory
-     * @param StoreManagerInterface $storeManager
-     */
-    public function __construct(
-        RateRequestFactory $rateRequestFactory,
-        RateCollectorInterfaceFactory $rateCollectorFactory,
-        StoreManagerInterface $storeManager
-    ) {
-        $this->rateRequestFactory = $rateRequestFactory;
-        $this->storeManager = $storeManager;
-        $this->rateCollectorFactory = $rateCollectorFactory;
-    }
-
-    /**
-     * Finds shipping rates for an address.
-     *
-     * @param Address $address
-     * @return array
-     */
-    public function getRatesForCustomerAddress(Address $address): array
-    {
-        /** @var $request RateRequest */
-        $request = $this->rateRequestFactory->create();
-        $request->setDestCountryId($address->getCountryId());
-        $request->setDestRegionId($address->getRegionId());
-        $request->setDestRegionCode($address->getRegionCode());
-        $request->setDestStreet($address->getStreetFull());
-        $request->setDestCity($address->getCity());
-        $request->setDestPostcode($address->getPostcode());
-        $request->setStoreId($this->storeManager->getStore()->getId());
-        $request->setWebsiteId($this->storeManager->getWebsite()->getId());
-        $request->setBaseCurrency($this->storeManager->getStore()->getBaseCurrency());
-        $request->setPackageCurrency($this->storeManager->getStore()->getCurrentCurrency());
-        // Because of wrong compare operator in \Magento\OfflineShipping\Model\Carrier\Tablerate on line: 167
-        $request->setPackageQty(-1);
-
-        $result = $this->rateCollectorFactory->create()->collectRates($request)->getResult();
-
-        $shippingRates = [];
-
-        if ($result) {
-            $shippingRates = $result->getAllRates();
-        }
-
-        return $shippingRates;
-    }
-}
diff --git a/app/code/Magento/InstantPurchase/composer.json b/app/code/Magento/InstantPurchase/composer.json
index df13e10f55b8fef052e0d47b604231c5820a9a2e..1c3b97a6beb9449b70a7658e424bbf50114dcf13 100644
--- a/app/code/Magento/InstantPurchase/composer.json
+++ b/app/code/Magento/InstantPurchase/composer.json
@@ -13,6 +13,7 @@
     "magento/module-catalog": "102.0.*",
     "magento/module-customer": "101.0.*",
     "magento/module-sales": "101.0.*",
+    "magento/module-shipping": "100.2.*",
     "magento/module-quote": "101.0.*",
     "magento/module-vault": "101.0.*",
     "magento/framework": "100.2.*"
diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php
index acb0444d508038b7ee058af9900c6ac0ab88f574..08b646a66189804651f5ec94a31d7bdaa2c73fe4 100644
--- a/app/code/Magento/Paypal/Model/Config.php
+++ b/app/code/Magento/Paypal/Model/Config.php
@@ -226,6 +226,7 @@ class Config extends AbstractConfig
         'TWD',
         'THB',
         'USD',
+        'INR',
     ];
 
     /**
diff --git a/app/code/Magento/Quote/Setup/UpgradeSchema.php b/app/code/Magento/Quote/Setup/UpgradeSchema.php
index e4912892dbe17a3aeddc80faa570975b48de7fa2..1bb20a669bdf2693ce65f0ae97c6809da998de61 100644
--- a/app/code/Magento/Quote/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Quote/Setup/UpgradeSchema.php
@@ -48,17 +48,17 @@ class UpgradeSchema implements UpgradeSchemaInterface
         }
         //drop foreign key for single DB case
         if (version_compare($context->getVersion(), '2.0.3', '<')
-            && $setup->tableExists($setup->getTable('quote_item'))
+            && $setup->tableExists($setup->getTable('quote_item', self::$connectionName))
         ) {
-            $setup->getConnection()->dropForeignKey(
-                $setup->getTable('quote_item'),
+            $setup->getConnection(self::$connectionName)->dropForeignKey(
+                $setup->getTable('quote_item', self::$connectionName),
                 $setup->getFkName('quote_item', 'product_id', 'catalog_product_entity', 'entity_id')
             );
         }
         if (version_compare($context->getVersion(), '2.0.5', '<')) {
-            $connection = $setup->getConnection();
+            $connection = $setup->getConnection(self::$connectionName);
             $connection->modifyColumn(
-                $setup->getTable('quote_address'),
+                $setup->getTable('quote_address', self::$connectionName),
                 'shipping_method',
                 [
                     'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json
index 5d4c5f35a3a24f7383c18cffd3e8961b46060751..a892697802e63de0f4f4de752428712064cd09c1 100644
--- a/app/code/Magento/Quote/composer.json
+++ b/app/code/Magento/Quote/composer.json
@@ -23,7 +23,7 @@
         "magento/module-webapi": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/QuoteAnalytics/composer.json b/app/code/Magento/QuoteAnalytics/composer.json
index 7f38e489ab0b0f5131c4ee665a03f1d8a49fb052..abbb0ce7a042ba696adc92047667a9d2eac485db 100644
--- a/app/code/Magento/QuoteAnalytics/composer.json
+++ b/app/code/Magento/QuoteAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-quote": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json
index 74ed132bc65d2de3379df36a6efa779719df6990..1058052dd11221bd5e9acc1071e3740918574bae 100644
--- a/app/code/Magento/Reports/composer.json
+++ b/app/code/Magento/Reports/composer.json
@@ -22,7 +22,7 @@
         "magento/framework": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json
index f3b36e8b3f3fa24dc850ea4ce48f612e64f1ff7e..47680b454c29f631231f31f767700efceed59902 100644
--- a/app/code/Magento/Review/composer.json
+++ b/app/code/Magento/Review/composer.json
@@ -18,7 +18,7 @@
         "magento/module-review-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ReviewAnalytics/composer.json b/app/code/Magento/ReviewAnalytics/composer.json
index b31c420e181bfa550f32880892c3d619ca52011b..965b6294db16a4e0815b872a0f563d5986b91c5a 100644
--- a/app/code/Magento/ReviewAnalytics/composer.json
+++ b/app/code/Magento/ReviewAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-review": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedAtListProvider.php b/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedAtListProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..846fa46572fdecbdea836317f36599612630e2a4
--- /dev/null
+++ b/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedAtListProvider.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Model\ResourceModel\Provider;
+
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+
+/**
+ * Retrieves ID's of not synced by `updated_at` column entities.
+ * The result should contain list of entities ID's from the main table which have `updated_at` column greater
+ * than in the grid table.
+ */
+class UpdatedAtListProvider implements NotSyncedDataProviderInterface
+{
+    /**
+     * @var ResourceConnection
+     */
+    private $resourceConnection;
+
+    /**
+     * @var AdapterInterface
+     */
+    private $connection;
+
+    /**
+     * @param ResourceConnection $resourceConnection
+     */
+    public function __construct(ResourceConnection $resourceConnection)
+    {
+        $this->connection = $resourceConnection->getConnection('sales');
+        $this->resourceConnection = $resourceConnection;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getIds($mainTableName, $gridTableName)
+    {
+        $mainTableName = $this->resourceConnection->getTableName($mainTableName);
+        $gridTableName = $this->resourceConnection->getTableName($gridTableName);
+        $select = $this->connection->select()
+            ->from($mainTableName, [$mainTableName . '.entity_id'])
+            ->joinInner(
+                [$gridTableName => $gridTableName],
+                sprintf(
+                    '%s.entity_id = %s.entity_id AND %s.updated_at > %s.updated_at',
+                    $mainTableName,
+                    $gridTableName,
+                    $mainTableName,
+                    $gridTableName
+                ),
+                []
+            );
+
+        return $this->connection->fetchAll($select, [], \Zend_Db::FETCH_COLUMN);
+    }
+}
diff --git a/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedIdListProvider.php b/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedIdListProvider.php
index 59906c79215fa41b25aca8245c2467266cffc9d4..42c6e9d6503158276c6b368fcc04507c99ecf51a 100644
--- a/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedIdListProvider.php
+++ b/app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedIdListProvider.php
@@ -38,10 +38,12 @@ class UpdatedIdListProvider implements NotSyncedDataProviderInterface
      */
     public function getIds($mainTableName, $gridTableName)
     {
+        $mainTableName = $this->resourceConnection->getTableName($mainTableName);
+        $gridTableName = $this->resourceConnection->getTableName($gridTableName);
         $select = $this->getConnection()->select()
-            ->from($this->getConnection()->getTableName($mainTableName), [$mainTableName . '.entity_id'])
+            ->from($mainTableName, [$mainTableName . '.entity_id'])
             ->joinLeft(
-                [$gridTableName => $this->getConnection()->getTableName($gridTableName)],
+                [$gridTableName => $gridTableName],
                 sprintf(
                     '%s.%s = %s.%s',
                     $mainTableName,
diff --git a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Provider/NotSyncedDataProviderTest.php b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Provider/NotSyncedDataProviderTest.php
index 8e248d239a501da1fa2855179682d2940a2db4cd..5ed60f8de306f65e1ed1adf0e33a9c0ed65b9a3d 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Provider/NotSyncedDataProviderTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Provider/NotSyncedDataProviderTest.php
@@ -5,15 +5,11 @@
  */
 namespace Magento\Sales\Test\Unit\Model\ResourceModel\Provider;
 
-use Magento\Framework\ObjectManager\TMap;
 use Magento\Framework\ObjectManager\TMapFactory;
 use Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProvider;
 use Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProviderInterface;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
-/**
- * Class NotSyncedDataProviderTest
- */
 class NotSyncedDataProviderTest extends \PHPUnit\Framework\TestCase
 {
     public function testGetIdsEmpty()
@@ -23,30 +19,14 @@ class NotSyncedDataProviderTest extends \PHPUnit\Framework\TestCase
             ->disableOriginalConstructor()
             ->setMethods(['create'])
             ->getMock();
-        $tMap = $this->getMockBuilder(TMap::class)
-            ->disableOriginalConstructor()
-            ->getMock();
 
-        $tMapFactory->expects(static::once())
-            ->method('create')
-            ->with(
-                [
-                    'array' => [],
-                    'type' => NotSyncedDataProviderInterface::class
-                ]
-            )
-            ->willReturn($tMap);
-        $tMap->expects(static::once())
-            ->method('getIterator')
-            ->willReturn(new \ArrayIterator([]));
+        $tMapFactory->method('create')
+            ->willReturn([]);
 
-        $provider = new NotSyncedDataProvider($tMapFactory, []);
-        static::assertEquals([], $provider->getIds('main_table', 'grid_table'));
+        $provider = new NotSyncedDataProvider($tMapFactory);
+        self::assertEquals([], $provider->getIds('main_table', 'grid_table'));
     }
 
-    /**
-     * @covers \Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProvider::getIds
-     */
     public function testGetIds()
     {
         /** @var TMapFactory|MockObject $tMapFactory */
@@ -54,46 +34,31 @@ class NotSyncedDataProviderTest extends \PHPUnit\Framework\TestCase
             ->disableOriginalConstructor()
             ->setMethods(['create'])
             ->getMock();
-        $tMap = $this->getMockBuilder(TMap::class)
-            ->disableOriginalConstructor()
-            ->getMock();
 
         $provider1 = $this->getMockBuilder(NotSyncedDataProviderInterface::class)
             ->getMockForAbstractClass();
-        $provider1->expects(static::once())
-            ->method('getIds')
+        $provider1->method('getIds')
             ->willReturn([1, 2]);
 
         $provider2 = $this->getMockBuilder(NotSyncedDataProviderInterface::class)
             ->getMockForAbstractClass();
-        $provider2->expects(static::once())
-            ->method('getIds')
+        $provider2->method('getIds')
             ->willReturn([2, 3, 4]);
 
-        $tMapFactory->expects(static::once())
-            ->method('create')
-            ->with(
+        $tMapFactory->method('create')
+            ->with(self::equalTo(
                 [
-                    'array' => [
-                        'provider1' => NotSyncedDataProviderInterface::class,
-                        'provider2' => NotSyncedDataProviderInterface::class
-                    ],
+                    'array' => [$provider1, $provider2],
                     'type' => NotSyncedDataProviderInterface::class
                 ]
-            )
-            ->willReturn($tMap);
-        $tMap->expects(static::once())
-            ->method('getIterator')
-            ->willReturn(new \ArrayIterator([$provider1, $provider2]));
+            ))
+            ->willReturn([$provider1, $provider2]);
 
-        $provider = new NotSyncedDataProvider(
-            $tMapFactory,
-            [
-                'provider1' => NotSyncedDataProviderInterface::class,
-                'provider2' => NotSyncedDataProviderInterface::class,
-            ]
-        );
+        $provider = new NotSyncedDataProvider($tMapFactory, [$provider1, $provider2]);
 
-        static::assertEquals([1, 2, 3, 4], array_values($provider->getIds('main_table', 'grid_table')));
+        self::assertEquals(
+            [1, 2, 3, 4],
+            array_values($provider->getIds('main_table', 'grid_table'))
+        );
     }
 }
diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json
index c4a99e5b45076d8465642594cc025f7a746bac41..9761f82d1894aff5881756eb5718520f912ad4e6 100644
--- a/app/code/Magento/Sales/composer.json
+++ b/app/code/Magento/Sales/composer.json
@@ -32,7 +32,7 @@
         "magento/module-sales-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml
index 9de3f238d6a395965d8766e77b2981f88157acb4..22ddc7b333574db38629f0fe5124bd031c972e1e 100644
--- a/app/code/Magento/Sales/etc/di.xml
+++ b/app/code/Magento/Sales/etc/di.xml
@@ -470,6 +470,15 @@
             <argument name="entityRelationComposite" xsi:type="object">CreditmemoRelationsComposite</argument>
         </arguments>
     </type>
+    
+    <virtualType name="Magento\Sales\Model\ResourceModel\Provider\NotSyncedOrderDataProvider" type="Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProvider">
+        <arguments>
+            <argument name="providers" xsi:type="array">
+                <item name="default" xsi:type="string">Magento\Sales\Model\ResourceModel\Provider\UpdatedIdListProvider</item>
+                <item name="updated_at" xsi:type="string">Magento\Sales\Model\ResourceModel\Provider\UpdatedAtListProvider</item>
+            </argument>
+        </arguments>
+    </virtualType>
     <virtualType name="Magento\Sales\Model\ResourceModel\Order\Grid" type="Magento\Sales\Model\ResourceModel\Grid">
         <arguments>
             <argument name="mainTableName" xsi:type="string">sales_order</argument>
@@ -520,6 +529,7 @@
                 <item name="payment_method" xsi:type="string">sales_order_payment.method</item>
                 <item name="total_refunded" xsi:type="string">sales_order.total_refunded</item>
             </argument>
+            <argument name="notSyncedDataProvider" xsi:type="object">Magento\Sales\Model\ResourceModel\Provider\NotSyncedOrderDataProvider</argument>
         </arguments>
     </virtualType>
     <virtualType name="ShipmentGridAggregator" type="Magento\Sales\Model\ResourceModel\Grid">
diff --git a/app/code/Magento/SalesAnalytics/composer.json b/app/code/Magento/SalesAnalytics/composer.json
index 7c9270a503b0d0aaf824c879ff6396fe0ad906d6..344971d7056cfb88649a7a98d0b0e8788d22b18b 100644
--- a/app/code/Magento/SalesAnalytics/composer.json
+++ b/app/code/Magento/SalesAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-sales": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/SalesRule/Model/Quote/Discount.php b/app/code/Magento/SalesRule/Model/Quote/Discount.php
index bee007b41181fd60c2e32086a513a8b4a59d208e..693a61b272f66e7128b3c369fd024a1ffe6418d1 100644
--- a/app/code/Magento/SalesRule/Model/Quote/Discount.php
+++ b/app/code/Magento/SalesRule/Model/Quote/Discount.php
@@ -179,7 +179,7 @@ class Discount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
             $roundingDelta[$key] = 0.0000001;
         }
         foreach ($item->getChildren() as $child) {
-            $ratio = $child->getBaseRowTotal() / $parentBaseRowTotal;
+            $ratio = $parentBaseRowTotal != 0 ? $child->getBaseRowTotal() / $parentBaseRowTotal : 0;
             foreach ($keys as $key) {
                 if (!$item->hasData($key)) {
                     continue;
diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php
index a1c325f39a94759b497a1ef98675515ef23528a9..671f20a27a4606e12fd5e9ac25fbd020adfa7da1 100644
--- a/app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php
+++ b/app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php
@@ -229,7 +229,30 @@ class DiscountTest extends \PHPUnit\Framework\TestCase
     {
         $data = [
             // 3 items, each $100, testing that discount are distributed to item correctly
-            'three_items' => [
+            [
+                    'child_item_data' => [
+                        'item1' => [
+                            'base_row_total' => 0,
+                        ]
+                    ],
+                    'parent_item_data' => [
+                        'discount_amount' => 20,
+                        'base_discount_amount' => 10,
+                        'original_discount_amount' => 40,
+                        'base_original_discount_amount' => 20,
+                        'base_row_total' => 0,
+                    ],
+                    'expected_child_item_data' => [
+                        'item1' => [
+                            'discount_amount' => 0,
+                            'base_discount_amount' => 0,
+                            'original_discount_amount' => 0,
+                            'base_original_discount_amount' => 0,
+                        ]
+                    ],
+                ],
+            [
+                // 3 items, each $100, testing that discount are distributed to item correctly
                 'child_item_data' => [
                     'item1' => [
                         'base_row_total' => 100,
diff --git a/app/code/Magento/Search/composer.json b/app/code/Magento/Search/composer.json
index 60ba6550cddf478494eccf5065543993ba78f3bc..c6aecd101fc6fee6dc8a14d44a818739a37e53c2 100644
--- a/app/code/Magento/Search/composer.json
+++ b/app/code/Magento/Search/composer.json
@@ -11,7 +11,7 @@
         "magento/module-ui": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json
index 06fa1e5295c6009c37190efa67957e04b26bba71..a7a2a3d48b06e30f2cb0769fdcbadace2b17ec98 100644
--- a/app/code/Magento/Shipping/composer.json
+++ b/app/code/Magento/Shipping/composer.json
@@ -25,7 +25,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Signifyd/composer.json b/app/code/Magento/Signifyd/composer.json
index f11b23cc3b6c411cfb91472ee550204d36ae7cce..a162cef1614cad8f5089f53d1591021fab5f9aae 100644
--- a/app/code/Magento/Signifyd/composer.json
+++ b/app/code/Magento/Signifyd/composer.json
@@ -3,21 +3,21 @@
     "description": "Submitting Case Entry to Signifyd on Order Creation",
     "require": {
         "php": "7.0.2|7.0.4|~7.0.6|~7.1.0",
-        "magento/module-config": "100.2.*",
-        "magento/framework": "100.2.*",
-        "magento/module-sales": "100.2.*",
+        "magento/module-config": "101.0.*",
+        "magento/framework": "101.0.*",
+        "magento/module-sales": "101.0.*",
         "magento/module-store": "100.2.*",
-        "magento/module-customer": "100.2.*",
+        "magento/module-customer": "101.0.*",
         "magento/module-directory": "100.2.*",
         "magento/module-checkout": "100.2.*",
         "magento/module-backend": "100.2.*",
         "magento/module-payment": "100.2.*"
     },
     "suggest": {
-        "magento/module-config": "100.2.*"
+        "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.1",
     "license": [
         "proprietary"
     ],
diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json
index 71d9198a332a72a38fab0cedc8dfac1ef4199a9d..88be3616eebd05bfee6474f704389a3a0127d32d 100644
--- a/app/code/Magento/Sitemap/composer.json
+++ b/app/code/Magento/Sitemap/composer.json
@@ -18,7 +18,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json
index 662414049c9556446b3021be0959fc80c3808361..f9eb84e2f9fa1010b126310f61ab18c741f0209a 100644
--- a/app/code/Magento/Store/composer.json
+++ b/app/code/Magento/Store/composer.json
@@ -14,7 +14,7 @@
         "magento/module-deploy": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Store/etc/config.xml b/app/code/Magento/Store/etc/config.xml
index 470337a97dcd93a862b3ae7f05549bf1ec237819..bb5b23620df4b0bc9dd7e3666082658068d3ccac 100644
--- a/app/code/Magento/Store/etc/config.xml
+++ b/app/code/Magento/Store/etc/config.xml
@@ -115,6 +115,10 @@
             <file>
                 <protected_extensions>
                     <php>php</php>
+                    <php3>php3</php3>
+                    <php4>php4</php4>
+                    <php5>php5</php5>
+                    <php7>php7</php7>
                     <htaccess>htaccess</htaccess>
                     <jsp>jsp</jsp>
                     <pl>pl</pl>
diff --git a/app/code/Magento/Swagger/composer.json b/app/code/Magento/Swagger/composer.json
index 2429607dc8716157fe9627889335712f3b8a07dc..787d58891c9e09c90c69da2ecc97764851d0aa93 100644
--- a/app/code/Magento/Swagger/composer.json
+++ b/app/code/Magento/Swagger/composer.json
@@ -6,7 +6,7 @@
         "magento/framework": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Tax/Model/Plugin/OrderSave.php b/app/code/Magento/Tax/Model/Plugin/OrderSave.php
index 720328524868833b4bb501b3858b79490977a88b..3c87086cdf585b285fbe49fda23912c167851c26 100644
--- a/app/code/Magento/Tax/Model/Plugin/OrderSave.php
+++ b/app/code/Magento/Tax/Model/Plugin/OrderSave.php
@@ -163,7 +163,9 @@ class OrderSave
                                     if (isset($quoteItemId['id'])) {
                                         //This is a product item
                                         $item = $order->getItemByQuoteItemId($quoteItemId['id']);
-                                        $itemId = $item->getId();
+                                        if ($item !== null && $item->getId()) {
+                                            $itemId = $item->getId();
+                                        }
                                     } elseif (isset($quoteItemId['associated_item_id'])) {
                                         //This item is associated with a product item
                                         $item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
diff --git a/app/code/Magento/Tax/composer.json b/app/code/Magento/Tax/composer.json
index 140b0ee8450cd3872f7882af4bb5c9dbfa24c472..1d09fb64eed893b1257cc3c6f399bda00ca77322 100644
--- a/app/code/Magento/Tax/composer.json
+++ b/app/code/Magento/Tax/composer.json
@@ -22,7 +22,7 @@
         "magento/module-tax-sample-data": "Sample Data version:100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Theme/Model/Config/Processor/DesignTheme.php b/app/code/Magento/Theme/Model/Config/Processor/DesignTheme.php
index 258be67979ed2fd5e896dc0b68b74ef2b73bca1a..d9d2c0e041e990d6b008be0816c67e613a3d4032 100644
--- a/app/code/Magento/Theme/Model/Config/Processor/DesignTheme.php
+++ b/app/code/Magento/Theme/Model/Config/Processor/DesignTheme.php
@@ -72,8 +72,8 @@ class DesignTheme implements PreProcessorInterface
     private function changeThemeFullPathToIdentifier($configItems)
     {
         $theme = null;
-        if ($this->arrayManager->exists(DesignInterface::XML_PATH_THEME_ID, $configItems)) {
-            $themeIdentifier = $this->arrayManager->get(DesignInterface::XML_PATH_THEME_ID, $configItems);
+        $themeIdentifier = $this->arrayManager->get(DesignInterface::XML_PATH_THEME_ID, $configItems);
+        if (!empty($themeIdentifier)) {
             if (!is_numeric($themeIdentifier)) {
                 // workaround for case when db is not available
                 try {
diff --git a/app/code/Magento/Theme/Test/Unit/Model/Config/Processor/DesignThemeTest.php b/app/code/Magento/Theme/Test/Unit/Model/Config/Processor/DesignThemeTest.php
index 1f3ab5642f47190569de2837b491f9207fc3a943..bb2160f1e293de80dbcbd3e5685e06452447d1dd 100644
--- a/app/code/Magento/Theme/Test/Unit/Model/Config/Processor/DesignThemeTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Model/Config/Processor/DesignThemeTest.php
@@ -5,7 +5,6 @@
  */
 namespace Magento\Theme\Test\Unit\Model\Config\Processor;
 
-use Magento\Config\App\Config\Source\DumpConfigSourceAggregated;
 use Magento\Framework\Stdlib\ArrayManager;
 use Magento\Framework\View\Design\Theme\ListInterface;
 use Magento\Theme\Model\Config\Processor\DesignTheme;
@@ -78,6 +77,7 @@ class DesignThemeTest extends \PHPUnit\Framework\TestCase
 
     /**
      * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     public function getDumpConfigDataProvider()
     {
@@ -163,6 +163,22 @@ class DesignThemeTest extends \PHPUnit\Framework\TestCase
                     ],
                 ],
             ],
+            [
+                [
+                    'websites' => [
+                        'base' => [
+                            'design' => ['theme' => ['theme_id' => '']],
+                        ],
+                    ],
+                ],
+                [
+                    'websites' => [
+                        'base' => [
+                            'design' => ['theme' => ['theme_id' => '']],
+                        ],
+                    ],
+                ],
+            ],
         ];
     }
 }
diff --git a/app/code/Magento/Theme/composer.json b/app/code/Magento/Theme/composer.json
index 3d3161c476ef1791797c76467e2d18124d68537a..4593eccd23dea1c3a06f47791e2c8b3e12f79b23 100644
--- a/app/code/Magento/Theme/composer.json
+++ b/app/code/Magento/Theme/composer.json
@@ -22,7 +22,7 @@
         "magento/module-directory": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json
index f7c581340eb2e1caf2997e1e109499a591041be4..a2504cdfbb9cd9da1b1f17743a08b6cdab199d1d 100644
--- a/app/code/Magento/Translation/composer.json
+++ b/app/code/Magento/Translation/composer.json
@@ -12,7 +12,7 @@
         "magento/module-deploy": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json
index f93b97b1b30fe32dd9785b6d04ba74fad37f0423..1f58c55ce61b683d7fad83f62d35982917fc5e37 100644
--- a/app/code/Magento/Ui/composer.json
+++ b/app/code/Magento/Ui/composer.json
@@ -13,7 +13,7 @@
         "magento/module-config": "101.0.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json
index db825c41f392b9ef94ec39344ef2adb186925000..32086222e43f147748f721b95978de56f9ba89ef 100644
--- a/app/code/Magento/UrlRewrite/composer.json
+++ b/app/code/Magento/UrlRewrite/composer.json
@@ -12,7 +12,7 @@
         "magento/module-cms-url-rewrite": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php
index ee7d65e4847925068d0db6b97aa9acb9cd1d1610..3df6966fb01b38976d57061366dee93ce24e2588 100644
--- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php
+++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php
@@ -204,14 +204,17 @@ class Generator extends AbstractSchemaGenerator
     protected function generatePathInfo($methodName, $httpMethodData, $tagName)
     {
         $methodData = $httpMethodData[Converter::KEY_METHOD];
+
+        $operationId = $this->typeProcessor->getOperationName($tagName, $methodData[Converter::KEY_METHOD]);
+        $operationId .= ucfirst($methodName);
+
         $pathInfo = [
             'tags' => [$tagName],
             'description' => $methodData['documentation'],
-            'operationId' => $this->typeProcessor->getOperationName($tagName, $methodData[Converter::KEY_METHOD]) .
-                ucfirst($methodName)
+            'operationId' => $operationId,
         ];
 
-        $parameters = $this->generateMethodParameters($httpMethodData);
+        $parameters = $this->generateMethodParameters($httpMethodData, $operationId);
         if ($parameters) {
             $pathInfo['parameters'] = $parameters;
         }
@@ -265,11 +268,12 @@ class Generator extends AbstractSchemaGenerator
      * Generate parameters based on method data
      *
      * @param array $httpMethodData
+     * @param string $operationId
      * @return array
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      */
-    private function generateMethodParameters($httpMethodData)
+    private function generateMethodParameters($httpMethodData, $operationId)
     {
         $bodySchema = [];
         $parameters = [];
@@ -335,7 +339,7 @@ class Generator extends AbstractSchemaGenerator
 
         if ($bodySchema) {
             $bodyParam = [];
-            $bodyParam['name'] = '$body';
+            $bodyParam['name'] = $operationId . 'Body';
             $bodyParam['in'] = 'body';
             $bodyParam['schema'] = $bodySchema;
             $parameters[] = $bodyParam;
diff --git a/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php b/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php
index 9883c3a2766e9668960fae48e0e441f280d8d274..611517df51657a8ae788d57e8110db815f73b242 100644
--- a/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php
+++ b/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php
@@ -223,7 +223,7 @@ class GeneratorTest extends \PHPUnit\Framework\TestCase
                     ]
                 ],
                 // @codingStandardsIgnoreStart
-                '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"post":{"tags":["testModule5AllSoapAndRestV2"],"description":"Add new item.","operationId":"' . self::OPERATION_NAME . 'Post","parameters":[{"name":"$body","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}'
+                '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"post":{"tags":["testModule5AllSoapAndRestV2"],"description":"Add new item.","operationId":"' . self::OPERATION_NAME . 'Post","parameters":[{"name":"operationNamePostBody","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}'
                 // @codingStandardsIgnoreEnd
             ],
             [
diff --git a/app/code/Magento/WishlistAnalytics/composer.json b/app/code/Magento/WishlistAnalytics/composer.json
index 20f414c00c320f4e5709f1ea1f490741a7c17012..11bd71276427ca0d26950768a31a3d67b94242ac 100644
--- a/app/code/Magento/WishlistAnalytics/composer.json
+++ b/app/code/Magento/WishlistAnalytics/composer.json
@@ -7,7 +7,7 @@
         "magento/module-wishlist": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.2.0-dev",
+    "version": "100.2.0",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/design/frontend/Magento/luma/composer.json b/app/design/frontend/Magento/luma/composer.json
index 7251ba69b0f3c8e12f4c92082f6c248572850630..b5db1aa32b4a1252b1f09a5aeca9924504ce9d7c 100644
--- a/app/design/frontend/Magento/luma/composer.json
+++ b/app/design/frontend/Magento/luma/composer.json
@@ -7,7 +7,7 @@
         "magento/framework": "101.0.*"
     },
     "type": "magento2-theme",
-    "version": "100.2.0",
+    "version": "100.2.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/etc/di.xml b/app/etc/di.xml
index 71168ab5220f781490d22e019bea285935457cec..e17505e78da311b5451ea8cb4ac7a4566ff7c91c 100755
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -1337,4 +1337,11 @@
             <argument name="defaultExceptionMessageFactory" xsi:type="object">Magento\Framework\Message\ExceptionMessageFactory</argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\Mview\View\Subscription">
+        <arguments>
+            <argument name="ignoredUpdateColumns" xsi:type="array">
+                <item name="updated_at" xsi:type="string">updated_at</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/bin/.htaccess b/bin/.htaccess
index 896fbc5a341ea313ff3abd503808842757678c1d..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/bin/.htaccess
+++ b/bin/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/composer.json b/composer.json
index 07f6146ff8f733bdd96337fb22e1b68623f79c9e..be9457595726163f6a84d21c6e0454298dd78cee 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/magento2ce",
     "description": "Magento 2 (Open Source)",
     "type": "project",
-    "version": "2.2.1-dev",
+    "version": "2.2.2-dev",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
@@ -42,7 +42,7 @@
         "composer/composer": "1.4.1",
         "monolog/monolog": "^1.17",
         "oyejorge/less.php": "~1.7.0",
-        "pelago/emogrifier": "0.1.1",
+        "pelago/emogrifier": "1.2.0",
         "tubalmartin/cssmin": "4.1.0",
         "magento/magento-composer-installer": ">=0.1.11",
         "braintree/braintree_php": "3.25.0",
@@ -84,43 +84,43 @@
     "replace": {
         "magento/module-marketplace": "100.2.0",
         "magento/module-admin-notification": "100.2.0",
-        "magento/module-advanced-pricing-import-export": "100.2.0",
-        "magento/module-analytics": "100.2.0-dev",
+        "magento/module-advanced-pricing-import-export": "100.2.1",
+        "magento/module-analytics": "100.2.0",
         "magento/module-authorization": "100.2.0",
         "magento/module-authorizenet": "100.2.0",
-        "magento/module-backend": "100.2.0",
+        "magento/module-backend": "100.2.1",
         "magento/module-backup": "100.2.0",
-        "magento/module-braintree": "100.2.0",
-        "magento/module-bundle": "100.2.0",
+        "magento/module-braintree": "100.2.1",
+        "magento/module-bundle": "100.2.1",
         "magento/module-bundle-import-export": "100.2.0",
         "magento/module-cache-invalidate": "100.2.0",
         "magento/module-captcha": "100.2.0",
-        "magento/module-catalog": "102.0.0",
-        "magento/module-catalog-analytics": "100.2.0-dev",
-        "magento/module-catalog-import-export": "100.2.0",
-        "magento/module-catalog-inventory": "100.2.0",
-        "magento/module-catalog-rule": "101.0.0",
+        "magento/module-catalog": "102.0.1",
+        "magento/module-catalog-analytics": "100.2.0",
+        "magento/module-catalog-import-export": "100.2.1",
+        "magento/module-catalog-inventory": "100.2.1",
+        "magento/module-catalog-rule": "101.0.1",
         "magento/module-catalog-rule-configurable": "100.2.0",
-        "magento/module-catalog-search": "100.2.0",
-        "magento/module-catalog-url-rewrite": "100.2.0",
+        "magento/module-catalog-search": "100.2.1",
+        "magento/module-catalog-url-rewrite": "100.2.1",
         "magento/module-catalog-widget": "100.2.0",
-        "magento/module-checkout": "100.2.0",
+        "magento/module-checkout": "100.2.1",
         "magento/module-checkout-agreements": "100.2.0",
-        "magento/module-cms": "102.0.0",
+        "magento/module-cms": "102.0.1",
         "magento/module-cms-url-rewrite": "100.2.0",
-        "magento/module-config": "101.0.0",
+        "magento/module-config": "101.0.1",
         "magento/module-configurable-import-export": "100.2.0",
-        "magento/module-configurable-product": "100.2.0",
+        "magento/module-configurable-product": "100.2.1",
         "magento/module-configurable-product-sales": "100.2.0",
         "magento/module-contact": "100.2.0",
         "magento/module-cookie": "100.2.0",
         "magento/module-cron": "100.2.0",
         "magento/module-currency-symbol": "100.2.0",
-        "magento/module-customer": "101.0.0",
-        "magento/module-customer-analytics": "100.2.0-dev",
+        "magento/module-customer": "101.0.1",
+        "magento/module-customer-analytics": "100.2.0",
         "magento/module-customer-import-export": "100.2.0",
-        "magento/module-deploy": "100.2.0",
-        "magento/module-developer": "100.2.0",
+        "magento/module-deploy": "100.2.1",
+        "magento/module-developer": "100.2.1",
         "magento/module-dhl": "100.2.0",
         "magento/module-directory": "100.2.0",
         "magento/module-downloadable": "100.2.0",
@@ -131,11 +131,11 @@
         "magento/module-fedex": "100.2.0",
         "magento/module-gift-message": "100.2.0",
         "magento/module-google-adwords": "100.2.0",
-        "magento/module-google-analytics": "100.2.0",
+        "magento/module-google-analytics": "100.2.1",
         "magento/module-google-optimizer": "100.2.0",
         "magento/module-grouped-import-export": "100.2.0",
         "magento/module-grouped-product": "100.2.0",
-        "magento/module-import-export": "100.2.0",
+        "magento/module-import-export": "100.2.1",
         "magento/module-indexer": "100.2.0",
         "magento/module-instant-purchase": "100.2.0",
         "magento/module-integration": "100.2.0",
@@ -153,39 +153,39 @@
         "magento/module-persistent": "100.2.0",
         "magento/module-product-alert": "100.2.0",
         "magento/module-product-video": "100.2.0",
-        "magento/module-quote": "101.0.0",
-        "magento/module-quote-analytics": "100.2.0-dev",
+        "magento/module-quote": "101.0.1",
+        "magento/module-quote-analytics": "100.2.0",
         "magento/module-release-notification": "100.2.0",
-        "magento/module-reports": "100.2.0",
+        "magento/module-reports": "100.2.1",
         "magento/module-require-js": "100.2.0",
-        "magento/module-review": "100.2.0",
-        "magento/module-review-analytics": "100.2.0-dev",
+        "magento/module-review": "100.2.1",
+        "magento/module-review-analytics": "100.2.0",
         "magento/module-robots": "100.2.0",
         "magento/module-rss": "100.2.0",
         "magento/module-rule": "100.2.0",
-        "magento/module-sales": "101.0.0",
-        "magento/module-sales-analytics": "100.2.0-dev",
+        "magento/module-sales": "101.0.1",
+        "magento/module-sales-analytics": "100.2.0",
         "magento/module-sales-inventory": "100.2.0",
         "magento/module-sales-rule": "101.0.0",
         "magento/module-sales-sequence": "100.2.0",
         "magento/module-sample-data": "100.2.0",
-        "magento/module-search": "100.2.0",
+        "magento/module-search": "100.2.1",
         "magento/module-security": "100.2.0",
         "magento/module-send-friend": "100.2.0",
-        "magento/module-shipping": "100.2.0",
-        "magento/module-signifyd": "100.2.0",
-        "magento/module-sitemap": "100.2.0",
-        "magento/module-store": "100.2.0",
-        "magento/module-swagger": "100.2.0",
+        "magento/module-shipping": "100.2.1",
+        "magento/module-signifyd": "100.2.1",
+        "magento/module-sitemap": "100.2.1",
+        "magento/module-store": "100.2.1",
+        "magento/module-swagger": "100.2.1",
         "magento/module-swatches": "100.2.0",
         "magento/module-swatches-layered-navigation": "100.2.0",
-        "magento/module-tax": "100.2.0",
+        "magento/module-tax": "100.2.1",
         "magento/module-tax-import-export": "100.2.0",
-        "magento/module-theme": "100.2.0",
-        "magento/module-translation": "100.2.0",
-        "magento/module-ui": "101.0.0",
+        "magento/module-theme": "100.2.1",
+        "magento/module-translation": "100.2.1",
+        "magento/module-ui": "101.0.1",
         "magento/module-ups": "100.2.0",
-        "magento/module-url-rewrite": "101.0.0",
+        "magento/module-url-rewrite": "101.0.1",
         "magento/module-user": "101.0.0",
         "magento/module-usps": "100.2.0",
         "magento/module-variable": "100.2.0",
@@ -196,10 +196,10 @@
         "magento/module-weee": "100.2.0",
         "magento/module-widget": "101.0.0",
         "magento/module-wishlist": "101.0.0",
-        "magento/module-wishlist-analytics": "100.2.0-dev",
+        "magento/module-wishlist-analytics": "100.2.0",
         "magento/theme-adminhtml-backend": "100.2.0",
         "magento/theme-frontend-blank": "100.2.0",
-        "magento/theme-frontend-luma": "100.2.0",
+        "magento/theme-frontend-luma": "100.2.1",
         "magento/language-de_de": "100.2.0",
         "magento/language-en_us": "100.2.0",
         "magento/language-es_es": "100.2.0",
@@ -207,7 +207,7 @@
         "magento/language-nl_nl": "100.2.0",
         "magento/language-pt_br": "100.2.0",
         "magento/language-zh_hans_cn": "100.2.0",
-        "magento/framework": "101.0.0",
+        "magento/framework": "101.0.1",
         "trentrichardson/jquery-timepicker-addon": "1.4.3",
         "components/jquery": "1.11.0",
         "blueimp/jquery-file-upload": "5.6.14",
diff --git a/composer.lock b/composer.lock
index 95b0874999035bfac01fa594cd9be2a1d6b32ba1..c126da645a6defe360a25b31ddfddb133f99c1a2 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": "99d9f3e6dd367aa12805bfbf64342ffe",
-    "content-hash": "77b4e986abaee3aada29cd9aa9ff9531",
+    "hash": "923fde043cfee16a442bb4e85cc032c6",
+    "content-hash": "da93a2422778d99a80c69037a53d447a",
     "packages": [
         {
             "name": "braintree/braintree_php",
@@ -960,27 +960,31 @@
         },
         {
             "name": "pelago/emogrifier",
-            "version": "v0.1.1",
+            "version": "V1.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/jjriv/emogrifier.git",
-                "reference": "ed72bcd6a3c7014862ff86d026193667a172fedf"
+                "reference": "a1db453bb504597d821efcc04b21c79a6021e00c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/jjriv/emogrifier/zipball/ed72bcd6a3c7014862ff86d026193667a172fedf",
-                "reference": "ed72bcd6a3c7014862ff86d026193667a172fedf",
+                "url": "https://api.github.com/repos/jjriv/emogrifier/zipball/a1db453bb504597d821efcc04b21c79a6021e00c",
+                "reference": "a1db453bb504597d821efcc04b21c79a6021e00c",
                 "shasum": ""
             },
             "require": {
-                "ext-mbstring": "*",
-                "php": ">=5.4.0"
+                "php": ">=5.4.0,<=7.1.99"
             },
             "require-dev": {
-                "phpunit/phpunit": "~4.6.0",
-                "squizlabs/php_codesniffer": "~2.3.0"
+                "phpunit/phpunit": "4.8.27",
+                "squizlabs/php_codesniffer": "2.6.0"
             },
             "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3.x-dev"
+                }
+            },
             "autoload": {
                 "psr-4": {
                     "Pelago\\": "Classes/"
@@ -1012,7 +1016,7 @@
             ],
             "description": "Converts CSS styles into inline style attributes in your HTML code",
             "homepage": "http://www.pelagodesign.com/sidecar/emogrifier/",
-            "time": "2015-05-15 11:37:51"
+            "time": "2017-03-02 12:51:48"
         },
         {
             "name": "phpseclib/phpseclib",
@@ -1530,16 +1534,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v2.8.28",
+            "version": "v2.8.29",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "f81549d2c5fdee8d711c9ab3c7e7362353ea5853"
+                "reference": "89143ce2b463515a75b5f5e9650e6ecfb2684158"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/f81549d2c5fdee8d711c9ab3c7e7362353ea5853",
-                "reference": "f81549d2c5fdee8d711c9ab3c7e7362353ea5853",
+                "url": "https://api.github.com/repos/symfony/console/zipball/89143ce2b463515a75b5f5e9650e6ecfb2684158",
+                "reference": "89143ce2b463515a75b5f5e9650e6ecfb2684158",
                 "shasum": ""
             },
             "require": {
@@ -1587,7 +1591,7 @@
             ],
             "description": "Symfony Console Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-01 21:00:16"
+            "time": "2017-11-07 14:08:47"
         },
         {
             "name": "symfony/debug",
@@ -1648,16 +1652,16 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.8.28",
+            "version": "v2.8.29",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "7fe089232554357efb8d4af65ce209fc6e5a2186"
+                "reference": "b59aacf238fadda50d612c9de73b74751872a903"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7fe089232554357efb8d4af65ce209fc6e5a2186",
-                "reference": "7fe089232554357efb8d4af65ce209fc6e5a2186",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b59aacf238fadda50d612c9de73b74751872a903",
+                "reference": "b59aacf238fadda50d612c9de73b74751872a903",
                 "shasum": ""
             },
             "require": {
@@ -1704,20 +1708,20 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-01 21:00:16"
+            "time": "2017-11-05 15:25:56"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "90bc45abf02ae6b7deb43895c1052cb0038506f1"
+                "reference": "77db266766b54db3ee982fe51868328b887ce15c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/90bc45abf02ae6b7deb43895c1052cb0038506f1",
-                "reference": "90bc45abf02ae6b7deb43895c1052cb0038506f1",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/77db266766b54db3ee982fe51868328b887ce15c",
+                "reference": "77db266766b54db3ee982fe51868328b887ce15c",
                 "shasum": ""
             },
             "require": {
@@ -1753,20 +1757,20 @@
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-03 13:33:10"
+            "time": "2017-11-07 14:12:55"
         },
         {
             "name": "symfony/finder",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "773e19a491d97926f236942484cb541560ce862d"
+                "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/773e19a491d97926f236942484cb541560ce862d",
-                "reference": "773e19a491d97926f236942484cb541560ce862d",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
+                "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
                 "shasum": ""
             },
             "require": {
@@ -1802,7 +1806,7 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-02 06:42:24"
+            "time": "2017-11-05 15:47:03"
         },
         {
             "name": "symfony/polyfill-mbstring",
@@ -1865,16 +1869,16 @@
         },
         {
             "name": "symfony/process",
-            "version": "v2.8.28",
+            "version": "v2.8.29",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "26c9fb02bf06bd6b90f661a5bd17e510810d0176"
+                "reference": "d25449e031f600807949aab7cadbf267712f4eee"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/26c9fb02bf06bd6b90f661a5bd17e510810d0176",
-                "reference": "26c9fb02bf06bd6b90f661a5bd17e510810d0176",
+                "url": "https://api.github.com/repos/symfony/process/zipball/d25449e031f600807949aab7cadbf267712f4eee",
+                "reference": "d25449e031f600807949aab7cadbf267712f4eee",
                 "shasum": ""
             },
             "require": {
@@ -1910,7 +1914,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-01 21:00:16"
+            "time": "2017-11-05 15:25:56"
         },
         {
             "name": "tedivm/jshrink",
@@ -4079,16 +4083,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v2.2.9",
+            "version": "v2.2.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
-                "reference": "eace538b022a2b7db59ef7b5460cb8c66cb20b50"
+                "reference": "b0e0f1d3d0b36a728768f9c44b074b22eb4b4c64"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/eace538b022a2b7db59ef7b5460cb8c66cb20b50",
-                "reference": "eace538b022a2b7db59ef7b5460cb8c66cb20b50",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/b0e0f1d3d0b36a728768f9c44b074b22eb4b4c64",
+                "reference": "b0e0f1d3d0b36a728768f9c44b074b22eb4b4c64",
                 "shasum": ""
             },
             "require": {
@@ -4160,7 +4164,7 @@
                 }
             ],
             "description": "A tool to automatically fix PHP code style",
-            "time": "2017-11-02 12:46:49"
+            "time": "2017-11-09 13:20:53"
         },
         {
             "name": "gecko-packages/gecko-php-unit",
@@ -5872,16 +5876,16 @@
         },
         {
             "name": "symfony/config",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "4ab62407bff9cd97c410a7feaef04c375aaa5cfd"
+                "reference": "8d2649077dc54dfbaf521d31f217383d82303c5f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/4ab62407bff9cd97c410a7feaef04c375aaa5cfd",
-                "reference": "4ab62407bff9cd97c410a7feaef04c375aaa5cfd",
+                "url": "https://api.github.com/repos/symfony/config/zipball/8d2649077dc54dfbaf521d31f217383d82303c5f",
+                "reference": "8d2649077dc54dfbaf521d31f217383d82303c5f",
                 "shasum": ""
             },
             "require": {
@@ -5930,20 +5934,20 @@
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-04 18:56:58"
+            "time": "2017-11-07 14:16:22"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "8ebad929aee3ca185b05f55d9cc5521670821ad1"
+                "reference": "50cdc753c61a4268608226647b0ce72e33a4a2b1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8ebad929aee3ca185b05f55d9cc5521670821ad1",
-                "reference": "8ebad929aee3ca185b05f55d9cc5521670821ad1",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/50cdc753c61a4268608226647b0ce72e33a4a2b1",
+                "reference": "50cdc753c61a4268608226647b0ce72e33a4a2b1",
                 "shasum": ""
             },
             "require": {
@@ -6000,20 +6004,20 @@
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-04 17:15:30"
+            "time": "2017-11-07 14:12:55"
         },
         {
             "name": "symfony/options-resolver",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/options-resolver.git",
-                "reference": "ee4e22978fe885b54ee5da8c7964f0a5301abfb6"
+                "reference": "623d9c210a137205f7e6e98166105625402cbb2f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ee4e22978fe885b54ee5da8c7964f0a5301abfb6",
-                "reference": "ee4e22978fe885b54ee5da8c7964f0a5301abfb6",
+                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/623d9c210a137205f7e6e98166105625402cbb2f",
+                "reference": "623d9c210a137205f7e6e98166105625402cbb2f",
                 "shasum": ""
             },
             "require": {
@@ -6054,7 +6058,7 @@
                 "configuration",
                 "options"
             ],
-            "time": "2017-07-29 21:54:42"
+            "time": "2017-11-05 15:47:03"
         },
         {
             "name": "symfony/polyfill-php54",
@@ -6286,16 +6290,16 @@
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v3.3.10",
+            "version": "v3.3.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git",
-                "reference": "170edf8b3247d7b6779eb6fa7428f342702ca184"
+                "reference": "1e93c3139ef6c799831fe03efd0fb1c7aecb3365"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/170edf8b3247d7b6779eb6fa7428f342702ca184",
-                "reference": "170edf8b3247d7b6779eb6fa7428f342702ca184",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e93c3139ef6c799831fe03efd0fb1c7aecb3365",
+                "reference": "1e93c3139ef6c799831fe03efd0fb1c7aecb3365",
                 "shasum": ""
             },
             "require": {
@@ -6331,7 +6335,7 @@
             ],
             "description": "Symfony Stopwatch Component",
             "homepage": "https://symfony.com",
-            "time": "2017-10-02 06:42:24"
+            "time": "2017-11-10 19:02:53"
         },
         {
             "name": "theseer/fdomdocument",
diff --git a/dev/.htaccess b/dev/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/dev/.htaccess
+++ b/dev/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JsonGenerationFromDataObjectTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JsonGenerationFromDataObjectTest.php
index 67068e3a11aa9093ea8fac4997f52668b5ff5f64..9a3fac9e8739ff60e322ef807c6a2699a1fa7e23 100644
--- a/dev/tests/api-functional/testsuite/Magento/Webapi/JsonGenerationFromDataObjectTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JsonGenerationFromDataObjectTest.php
@@ -10,6 +10,7 @@ namespace Magento\Webapi;
 
 use Magento\TestFramework\Helper\Bootstrap;
 use Magento\Framework\App\ProductMetadataInterface;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
  * Test REST schema generation mechanisms.
@@ -34,10 +35,10 @@ class JsonGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\W
     {
         $this->_markTestAsRestOnly("JSON generation tests are intended to be executed for REST adapter only.");
 
-        $this->storeCode = Bootstrap::getObjectManager()->get(\Magento\Store\Model\StoreManagerInterface::class)
+        $this->storeCode = Bootstrap::getObjectManager()->get(StoreManagerInterface::class)
             ->getStore()->getCode();
 
-        $this->productMetadata =  Bootstrap::getObjectManager()->get(\Magento\Framework\App\ProductMetadataInterface::class);
+        $this->productMetadata =  Bootstrap::getObjectManager()->get(ProductMetadataInterface::class);
 
         parent::setUp();
     }
@@ -197,7 +198,7 @@ class JsonGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\W
                                 'required' => true
                             ],
                             [
-                                'name' => '$body',
+                                'name' => 'testModule5AllSoapAndRestV1NestedUpdatePutBody',
                                 'in' => 'body',
                                 'schema' => [
                                     'required' => [
diff --git a/dev/tests/functional/.htaccess.sample b/dev/tests/functional/.htaccess.sample
index d089eb3c4f848b6c247eedc8746747faab4d3e8d..67c2f3fe2d027314bbfa03a1ae5167f356c32262 100644
--- a/dev/tests/functional/.htaccess.sample
+++ b/dev/tests/functional/.htaccess.sample
@@ -1,6 +1,11 @@
 ##############################################
 ## Allow access to command.php, website.php, export.php, pathChecker.php, locales.php, deleteMagentoGeneratedCode.php and log.php
     <FilesMatch "command.php|website.php|export.php|pathChecker.php|deleteMagentoGeneratedCode.php|log.php|locales.php">
-         order allow,deny
-         allow from all
+        <IfVersion < 2.4>
+            order allow,deny
+            allow from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all granted
+        </IfVersion>
     </FilesMatch>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerBackendEntity.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerBackendEntity.xml
index 4692d21575813e13b38da4f3fcd55b0cd8d4933b..5990157d6c5ea581d74b189f08ec6713c3484777 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerBackendEntity.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerBackendEntity.xml
@@ -8,7 +8,6 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\Customer\Test\TestCase\CreateExistingCustomerBackendEntity" summary="Create Existing Customer from Backend" ticketId="MAGETWO-43685">
         <variation name="CreateExistingCustomerBackendEntity1" summary="Create existing customer on Backend.">
-            <data name="tag" xsi:type="string">stable:no</data>
             <data name="customer/dataset" xsi:type="string">default</data>
             <constraint name="Magento\Customer\Test\Constraint\AssertCustomerBackendDuplicateErrorMessage" />
         </variation>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LoginCustomerOnFrontendStep.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LoginCustomerOnFrontendStep.php
index dc5d6076731c65c7e79b0753ac677ba543215dca..7e4dee70726797493155fd5fd91cc47129a0f2f3 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LoginCustomerOnFrontendStep.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LoginCustomerOnFrontendStep.php
@@ -75,6 +75,8 @@ class LoginCustomerOnFrontendStep implements TestStepInterface
         $this->cmsIndex->getCmsPageBlock()->waitPageInit();
         $this->customerAccountLogin->getLoginBlock()->login($this->customer);
         $this->cmsIndex->getCmsPageBlock()->waitPageInit();
+        $this->cmsIndex->getLinksBlock()->openLink('My Account');
+        $this->cmsIndex->getCmsPageBlock()->waitPageInit();
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.xml b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.xml
index 9d1c356136130a2bae37d118295e5765663e3cac..2b407e3d39200506957077bb033bccfc470f8e92 100644
--- a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.xml
@@ -42,7 +42,6 @@
             <constraint name="Magento\Install\Test\Constraint\AssertRewritesEnabled" />
         </variation>
         <variation name="InstallTestVariation5" summary="Install with enabled secure urls">
-            <data name="tag" xsi:type="string">stable:no</data>
             <data name="user/dataset" xsi:type="string">default</data>
             <data name="install/httpsFront" xsi:type="string">Use HTTPS for Magento Storefront</data>
             <data name="install/httpsAdmin" xsi:type="string">Use HTTPS for Magento Admin</data>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Install/Test/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aea0106d1ca16b7b80b03b8fe3a4599d4f2bfe7d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/etc/di.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
+    <preference for="Magento\Config\Test\Handler\ConfigData\ConfigDataInterface" type="Magento\Config\Test\Handler\ConfigData\Curl" />
+    <preference for="Magento\Integration\Test\Handler\Integration\IntegrationInterface" type="Magento\Integration\Test\Handler\Integration\Curl" />
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
index 91de39b384c354f23a55d848345019510968eadb..98e3f9e38382d89a0dc3002865580b8a31ab670e 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
@@ -8,7 +8,6 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\UrlRewrite\Test\TestCase\CreateProductWithSeveralWebsitesUrlRewriteTest" summary="Test product url rewrites when it is created in several websites">
         <variation name="CreateSimpleProductEntityWithSeveralWebsites" summary="Create product with several websites and check URL Rewites" ticketId="MAGETWO-27238">
-            <data name="tag" xsi:type="string">stable:no</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/sku" xsi:type="string">simple_sku_%isolation%</data>
diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Controller/Adminhtml/Payment/GetClientTokenTest.php b/dev/tests/integration/testsuite/Magento/Braintree/Controller/Adminhtml/Payment/GetClientTokenTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7546f20a42de9d30b6bf59ed3e2fa764de8ed8a6
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Braintree/Controller/Adminhtml/Payment/GetClientTokenTest.php
@@ -0,0 +1,151 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Controller\Adminhtml\Payment;
+
+use Braintree\Configuration;
+use Magento\Backend\Model\Session\Quote;
+use Magento\Braintree\Gateway\Config\Config;
+use Magento\Braintree\Model\Adapter\BraintreeAdapter;
+use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Serialize\SerializerInterface;
+use Magento\Store\Api\StoreRepositoryInterface;
+use Magento\TestFramework\TestCase\AbstractBackendController;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
+class GetClientTokenTest extends AbstractBackendController
+{
+    /**
+     * @var Quote
+     */
+    private $quoteSession;
+
+    /**
+     * @var ObjectManager|MockObject $stubObjectManager
+     */
+    private $stubObjectManager;
+
+    /**
+     * @inheritdoc
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->quoteSession = $this->_objectManager->get(Quote::class);
+
+        $this->stubObjectManager = $this->getMockBuilder(ObjectManager::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $adapterFactory = new BraintreeAdapterFactory(
+            $this->stubObjectManager,
+            $this->_objectManager->get(Config::class)
+        );
+
+        $this->_objectManager->addSharedInstance($adapterFactory, BraintreeAdapterFactory::class);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function tearDown()
+    {
+        $this->_objectManager->removeSharedInstance(BraintreeAdapterFactory::class);
+        parent::tearDown();
+    }
+
+    /**
+     * Checks if client token will retrieved from Braintree initialized with default scope.
+     *
+     * @magentoDataFixture Magento/Braintree/_files/payment_configuration.php
+     * @magentoAppArea adminhtml
+     */
+    public function testExecute()
+    {
+        $this->perform(
+            'def_merchant_id',
+            'def_public_key',
+            'def_private_key'
+        );
+    }
+
+    /**
+     * Checks if client token will be retrieved from Braintree initialized per store.
+     *
+     * @magentoDataFixture Magento/Braintree/_files/payment_configuration.php
+     * @magentoAppArea adminhtml
+     */
+    public function testExecuteWithStoreConfiguration()
+    {
+        /** @var StoreRepositoryInterface $storeRepository */
+        $storeRepository = $this->_objectManager->get(StoreRepositoryInterface::class);
+        $store = $storeRepository->get('test');
+        $this->quoteSession->setStoreId($store->getId());
+
+        $this->perform(
+            'store_merchant_id',
+            'store_public_key',
+            'def_private_key' // should be read from default scope
+        );
+    }
+
+    /**
+     * Checks if client token will be retrieved from Braintree initialized per website.
+     *
+     * @magentoDataFixture Magento/Braintree/_files/payment_configuration.php
+     * @magentoAppArea adminhtml
+     */
+    public function testExecuteWithWebsiteConfiguration()
+    {
+        /** @var StoreRepositoryInterface $storeRepository */
+        $storeRepository = $this->_objectManager->get(StoreRepositoryInterface::class);
+        $store = $storeRepository->get('fixture_second_store');
+        $this->quoteSession->setStoreId($store->getId());
+
+        $this->perform(
+            'website_merchant_id',
+            'def_public_key', // should be read from default scope
+            'website_private_key'
+        );
+    }
+
+    private function perform($merchantId, $publicKey, $privateKey)
+    {
+        $args = [
+            'merchantId' => $merchantId,
+            'publicKey' => $publicKey,
+            'privateKey' => $privateKey,
+            'environment' => 'sandbox'
+        ];
+
+        $adapter = $this->getMockBuilder(BraintreeAdapter::class)
+            ->setConstructorArgs($args)
+            ->setMethods(['generate'])
+            ->getMock();
+        $adapter->method('generate')
+            ->willReturn('client_token');
+
+        $this->stubObjectManager->method('create')
+            ->with(BraintreeAdapter::class, $args)
+            ->willReturn($adapter);
+
+        $this->dispatch('backend/braintree/payment/getClientToken');
+
+        /** @var SerializerInterface $serializer */
+        $serializer = $this->_objectManager->get(SerializerInterface::class);
+        $decoded = $serializer->unserialize($this->getResponse()->getBody());
+        $this->performAsserts($decoded['clientToken'], $merchantId, $publicKey, $privateKey);
+    }
+
+    private function performAsserts($clientToken, $merchantId, $publicKey, $privateKey)
+    {
+        self::assertEquals('client_token', $clientToken);
+        self::assertEquals(Configuration::merchantId(), $merchantId);
+        self::assertEquals(Configuration::publicKey(), $publicKey);
+        self::assertEquals(Configuration::privateKey(), $privateKey);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration.php b/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration.php
new file mode 100644
index 0000000000000000000000000000000000000000..da87ad5311d9217b909088ff7d304c4869901618
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Config\Model\Config;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\Encryption\EncryptorInterface;
+use Magento\Store\Model\ScopeInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+
+$objectManager = Bootstrap::getObjectManager();
+
+/** @var EncryptorInterface $encryptor */
+$encryptor = $objectManager->get(EncryptorInterface::class);
+
+$processConfigData = function (Config $config, array $data) {
+    foreach ($data as $key => $value) {
+        $config->setDataByPath($key, $value);
+        $config->save();
+    }
+};
+
+// save payment configuration for the default scope
+$configData = [
+    'payment/braintree/merchant_id' => 'def_merchant_id',
+    'payment/braintree/public_key' => $encryptor->encrypt('def_public_key'),
+    'payment/braintree/private_key' => $encryptor->encrypt('def_private_key'),
+];
+/** @var Config $defConfig */
+$defConfig = $objectManager->create(Config::class);
+$defConfig->setScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT);
+$processConfigData($defConfig, $configData);
+
+// save payment configuration per store
+require __DIR__ . '/../../Store/_files/store.php';
+$storeConfigData = [
+    'payment/braintree/merchant_id' => 'store_merchant_id',
+    'payment/braintree/public_key' => $encryptor->encrypt('store_public_key'),
+];
+/** @var Config $storeConfig */
+$storeConfig = $objectManager->create(Config::class);
+$storeConfig->setScope(ScopeInterface::SCOPE_STORES);
+$storeConfig->setStore('test');
+$processConfigData($storeConfig, $storeConfigData);
+
+// save payment website config data
+require __DIR__ . '/../../Store/_files/second_website_with_two_stores.php';
+$websiteConfigData = [
+    'payment/braintree/merchant_id' => 'website_merchant_id',
+    'payment/braintree/private_key' => $encryptor->encrypt('website_private_key'),
+];
+/** @var Config $websiteConfig */
+$websiteConfig = $objectManager->create(Config::class);
+$websiteConfig->setScope(ScopeInterface::SCOPE_WEBSITES);
+$websiteConfig->setWebsite($websiteId);
+$processConfigData($websiteConfig, $websiteConfigData);
diff --git a/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration_rollback.php b/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c0391769b09317bbd9a7c6a34d7751b038e949b
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Braintree/_files/payment_configuration_rollback.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\Config\Storage\WriterInterface;
+use Magento\Store\Api\StoreRepositoryInterface;
+use Magento\Store\Api\WebsiteRepositoryInterface;
+use Magento\Store\Model\ScopeInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+
+$objectManager = Bootstrap::getObjectManager();
+
+$deleteConfigData = function (WriterInterface $writer, $scope, $scopeId) {
+    $configData = [
+        'payment/braintree/merchant_id',
+        'payment/braintree/public_key',
+        'payment/braintree/private_key',
+    ];
+    foreach ($configData as $path) {
+        $writer->delete($path, $scope, $scopeId);
+    }
+};
+
+/** @var WriterInterface $configWriter */
+$configWriter = $objectManager->get(WriterInterface::class);
+$deleteConfigData($configWriter, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null);
+
+/** @var StoreRepositoryInterface $storeRepository */
+$storeRepository = $objectManager->get(StoreRepositoryInterface::class);
+$store = $storeRepository->get('test');
+$deleteConfigData($configWriter, ScopeInterface::SCOPE_STORES, $store->getId());
+
+/** @var WebsiteRepositoryInterface $websiteRepository */
+$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
+$website = $websiteRepository->get('test');
+$deleteConfigData($configWriter, ScopeInterface::SCOPE_WEBSITES, $website->getId());
+
+require __DIR__ . '/../../Store/_files/second_website_with_two_stores_rollback.php';
+require __DIR__ . '/../../Store/_files/store_rollback.php';
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/CategoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cea50218638cb0399af257c50f70c2a64b14fb7d
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/CategoryTest.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Model\Indexer\Product;
+
+use Magento\Catalog\Model\Category;
+use Magento\Catalog\Model\Product;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
+use Magento\Indexer\Model\Indexer;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @magentoDataFixture Magento/Catalog/_files/indexer_catalog_product_categories.php
+ * @magentoDataFixture Magento/Catalog/_files/indexer_catalog_products.php
+ * @magentoDbIsolation enabled
+ * @magentoAppIsolation enabled
+ */
+class CategoryTest extends TestCase
+{
+    const DEFAULT_ROOT_CATEGORY = 2;
+
+    /**
+     * @var Indexer
+     */
+    private $indexer;
+
+    /**
+     * @var ProductResource
+     */
+    private $productResource;
+
+    protected function setUp()
+    {
+        /** @var Indexer indexer */
+        $this->indexer = Bootstrap::getObjectManager()->create(
+            Indexer::class
+        );
+        $this->indexer->load('catalog_product_category');
+        /** @var ProductResource $productResource */
+        $this->productResource = Bootstrap::getObjectManager()->get(
+            ProductResource::class
+        );
+    }
+
+    /**
+     * Check that given product is only visible in given categories.
+     *
+     * @param Product $product
+     * @param Category[] $categoriesIn Categories the product is supposed
+     *                                 to be in.
+     * @param Category[]   $categories Whole list of categories.
+     *
+     * @return void
+     */
+    private function assertProductIn(
+        Product $product,
+        array $categoriesIn,
+        array $categories
+    ) {
+        foreach ($categories as $category) {
+            $visible = in_array($category, $categoriesIn, true);
+            $this->assertEquals(
+                $visible,
+                (bool)$this->productResource->canBeShowInCategory(
+                    $product,
+                    $category->getId()
+                ),
+                'Product "' .$product->getName() .'" is'
+                .($visible? '' : ' not') .' supposed to be in category "'
+                .$category->getName() .'"'
+            );
+        }
+    }
+
+    /**
+     * @magentoAppArea adminhtml
+     */
+    public function testReindexAll()
+    {
+        //Category #1 is base category for this case, Category #2 is non-anchor
+        //sub-category of Category #1, Category #3 is anchor sub-category of
+        //Category #2, Category #4 is anchor sub-category of Category #1
+        //Products are not yet assigned to categories
+        $categories = $this->loadCategories(4);
+        $products = $this->loadProducts(3);
+
+        //Leaving Product #1 unassigned, Product #2 is assigned to Category #3,
+        //Product #3 assigned to Category #3 and #4.
+        $products[0]->setCategoryIds(null);
+        $this->productResource->save($products[0]);
+        $products[1]->setCategoryIds([$categories[2]->getId()]);
+        $this->productResource->save($products[1]);
+        $products[2]->setCategoryIds([
+            $categories[2]->getId(),
+            $categories[3]->getId(),
+        ]);
+        $this->productResource->save($products[2]);
+        //Reindexing
+        $this->clearIndex();
+        $this->indexer->reindexAll();
+
+        //Checking that Category #1 shows only Product #2 and #3 since
+        //Product #1 is not assigned to any category, Product #2 is assigned to
+        //it's sub-subcategory and Product #3 is assigned to a sub-subcategory
+        //and a subcategory.
+        //Category #2 doesn't have any products on display because while it's
+        //sub-category has products it's a non-anchor category.
+        //Category #3 has 2 products directly assigned to it.
+        //Category #4 only has 1 product directly assigned to it.
+        $this->assertProductIn($products[0], [], $categories);
+        $this->assertProductIn(
+            $products[1],
+            [$categories[0],$categories[2]],
+            $categories
+        );
+        $this->assertProductIn(
+            $products[2],
+            [$categories[0], $categories[2], $categories[3]],
+            $categories
+        );
+
+        //Reassigning products a bit
+        $products[0]->setCategoryIds([$categories[0]->getId()]);
+        $this->productResource->save($products[0]);
+        $products[1]->setCategoryIds([]);
+        $this->productResource->save($products[1]);
+        $products[2]->setCategoryIds([
+            $categories[1]->getId(),
+            $categories[2]->getId(),
+            $categories[3]->getId(),
+        ]);
+        $this->productResource->save($products[2]);
+        //Reindexing
+        $this->clearIndex();
+        $this->indexer->reindexAll();
+        //Checking that Category #1 now also shows Product #1 because it was
+        //directly assigned to it and not showing Product #2 because it was
+        //unassigned from Category #3.
+        //Category #2 now shows Product #3 because it was directly assigned
+        //to it.
+        //Category #3 now shows only Product #3 because Product #2
+        //was unassigned.
+        //Category #4 still shows only Product #3.
+        $this->assertProductIn($products[0], [$categories[0]], $categories);
+        $this->assertProductIn($products[1], [], $categories);
+        $this->assertProductIn($products[2], $categories, $categories);
+
+        $this->clearIndex();
+    }
+
+    /**
+     * Load categories from the fixture.
+     *
+     * @param int $limit
+     * @param int $offset
+     * @return Category[]
+     */
+    private function loadCategories(int $limit, int $offset = 0): array
+    {
+        /** @var Category $category */
+        $category = Bootstrap::getObjectManager()->create(
+            Category::class
+        );
+
+        $result = $category
+            ->getCollection()
+            ->addAttributeToSelect('name')
+            ->getItems();
+        $result = array_slice($result, 2);
+
+        return array_slice($result, $offset, $limit);
+    }
+
+    /**
+     * Load products from the fixture.
+     *
+     * @param int $limit
+     * @param int $offset
+     * @return Product[]
+     */
+    private function loadProducts(int $limit, int $offset = 0): array
+    {
+        /** @var Product[] $result */
+        $result = [];
+        $ids = range($offset + 1, $offset + $limit);
+        foreach ($ids as $id) {
+            /** @var \Magento\Catalog\Model\Product $product */
+            $product = Bootstrap::getObjectManager()->create(
+                Product::class
+            );
+            $result[] = $product->load($id);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Clear index data.
+     */
+    private function clearIndex()
+    {
+        $this->productResource->getConnection()->delete(
+            $this->productResource->getTable('catalog_category_product_index')
+        );
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_category_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_category_rollback.php
index faa4fd6f4575ef7a64525fd4319a9d3e950d14d3..51a8fc6b7e978ebf26323ad114ed75c39c8edd84 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_category_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_category_rollback.php
@@ -16,7 +16,7 @@ $registry->register('isSecureArea', true);
 /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
 $collection = $objectManager->create(\Magento\Catalog\Model\ResourceModel\Category\Collection::class);
 $collection
-    ->addAttributeToFilter('level', 2)
+    ->addAttributeToFilter('level', ['gteq' => 2])
     ->load()
     ->delete();
 
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories.php
new file mode 100644
index 0000000000000000000000000000000000000000..075422d5f0d787e533469a453551052bba4747c1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var $category \Magento\Catalog\Model\Category */
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+/** @var \Magento\Catalog\Model\Category $categoryFirst */
+$categoryFirst = $objectManager->create(\Magento\Catalog\Model\Category::class);
+$categoryFirst->setName('Category 1')
+    ->setPath('1/2')
+    ->setLevel(2)
+    ->setAvailableSortBy('name')
+    ->setIsActive(true)
+    ->setPosition(1)
+    ->setDefaultSortBy('name')
+    ->setIsAnchor(true)
+    ->save();
+
+/** @var \Magento\Catalog\Model\Category $categorySecond */
+$categorySecond = $objectManager->create(\Magento\Catalog\Model\Category::class);
+$categorySecond->setName('Category 2')
+    ->setPath($categoryFirst->getPath())
+    ->setLevel(3)
+    ->setAvailableSortBy('name')
+    ->setIsActive(true)
+    ->setPosition(1)
+    ->setDefaultSortBy('name')
+    ->setIsAnchor(false)
+    ->save();
+
+/** @var \Magento\Catalog\Model\Category $categoryThird */
+$categoryThird = $objectManager->create(\Magento\Catalog\Model\Category::class);
+$categoryThird->setName('Category 3')
+    ->setPath($categorySecond->getPath())
+    ->setLevel(4)
+    ->setAvailableSortBy('name')
+    ->setIsActive(true)
+    ->setPosition(1)
+    ->setDefaultSortBy('name')
+    ->setIsAnchor(true)
+    ->save();
+
+/** @var \Magento\Catalog\Model\Category $categoryFourth */
+$categoryFourth = $objectManager->create(\Magento\Catalog\Model\Category::class);
+$categoryFourth->setName('Category 4')
+    ->setPath($categoryFirst->getPath())
+    ->setLevel(3)
+    ->setAvailableSortBy('name')
+    ->setIsActive(true)
+    ->setPosition(2)
+    ->setDefaultSortBy('name')
+    ->setIsAnchor(true)
+    ->save();
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..755f324b18cb2851b4f96d28087fd36608bc2ded
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/indexer_catalog_product_categories_rollback.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var \Magento\Framework\ObjectManagerInterface $objectManager */
+$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\Model\ResourceModel\Product\Collection $collection */
+$collection = $objectManager->create(
+    \Magento\Catalog\Model\ResourceModel\Category\Collection::class
+);
+$collection
+    ->addAttributeToFilter('level', ['gteq' => 2])
+    ->load()
+    ->delete();
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Config/Block/System/Config/_files/test_config.xml b/dev/tests/integration/testsuite/Magento/Config/Block/System/Config/_files/test_config.xml
index ab530e01f8b6a49cecdad4f86e45ba58ac98c37e..2fd972939117b20f6a51b70b1769a32b462c152f 100644
--- a/dev/tests/integration/testsuite/Magento/Config/Block/System/Config/_files/test_config.xml
+++ b/dev/tests/integration/testsuite/Magento/Config/Block/System/Config/_files/test_config.xml
@@ -10,7 +10,7 @@
         <test_section>
             <test_group>
                  <test_field_encrypted backend_model="Magento\Config\Model\Config\Backend\Encrypted">{ENCRYPTED_VALUE}</test_field_encrypted>
-                 <test_field_serialized backend_model="Magento\Config\Model\Config\Backend\Serialized">["value1","value2"]</test_field_serialized>
+                 <test_field_serialized>["value1","value2"]</test_field_serialized>
                  <test_field>test config value</test_field>
             </test_group>
         </test_section>
diff --git a/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php
index b8dbfec59845b17d95fd20e8a53da53e62d21f1f..2d76632cae0b759397228ffef012637bb6ded44a 100644
--- a/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php
+++ b/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php
@@ -24,7 +24,7 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractController
         $this->assertRedirect($this->stringContains('contact/index'));
         $this->assertSessionMessages(
             $this->contains(
-                "Thanks for contacting us with your comments and questions. We'll respond to you very soon."
+                "Thanks for contacting us with your comments and questions. We&#039;ll respond to you very soon."
             ),
             \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
         );
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
index fd3755fa6ea5cfcaa079f64caa56d89c600e9170..a01006a06a2e3b1beb98ba29b64b8ee0db6530db 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
@@ -10,12 +10,20 @@ namespace Magento\Customer\Controller;
 
 use Magento\Customer\Api\CustomerRepositoryInterface;
 use Magento\Customer\Api\Data\CustomerInterface;
+use Magento\Customer\Model\Account\Redirect;
+use Magento\Customer\Model\Session;
 use Magento\Framework\Api\FilterBuilder;
 use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\Config\Value;
+use Magento\Framework\App\Http;
 use Magento\Framework\Data\Form\FormKey;
 use Magento\Framework\Message\MessageInterface;
 use Magento\Store\Model\ScopeInterface;
 use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Request;
+use Magento\TestFramework\Response;
+use Zend\Stdlib\Parameters;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -30,9 +38,9 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
      */
     protected function login($customerId)
     {
-        /** @var \Magento\Customer\Model\Session $session */
+        /** @var Session $session */
         $session = Bootstrap::getObjectManager()
-            ->get(\Magento\Customer\Model\Session::class);
+            ->get(Session::class);
         $session->loginById($customerId);
     }
 
@@ -130,8 +138,8 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
         $this->assertFalse((bool)preg_match('/' . $token . '/m', $text));
         $this->assertRedirect($this->stringContains('customer/account/createpassword'));
 
-        /** @var \Magento\Customer\Model\Session $customer */
-        $session = Bootstrap::getObjectManager()->get(\Magento\Customer\Model\Session::class);
+        /** @var Session $customer */
+        $session = Bootstrap::getObjectManager()->get(Session::class);
         $this->assertEquals($token, $session->getRpToken());
         $this->assertEquals($customer->getId(), $session->getRpCustomerId());
         $this->assertNotContains($token, $response->getHeader('Location')->getFieldValue());
@@ -151,8 +159,8 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
         $customer->changeResetPasswordLinkToken($token);
         $customer->save();
 
-        /** @var \Magento\Customer\Model\Session $customer */
-        $session = Bootstrap::getObjectManager()->get(\Magento\Customer\Model\Session::class);
+        /** @var Session $customer */
+        $session = Bootstrap::getObjectManager()->get(Session::class);
         $session->setRpToken($token);
         $session->setRpCustomerId($customer->getId());
 
@@ -652,6 +660,50 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
         );
     }
 
+    /**
+     * Test redirect customer to account dashboard after logging in.
+     *
+     * @param bool|null $redirectDashboard
+     * @param string $redirectUrl
+     * @magentoDbIsolation enabled
+     * @magentoAppIsolation enabled
+     * @magentoDataFixture Magento/Customer/_files/customer.php
+     * @dataProvider loginPostRedirectDataProvider
+     */
+    public function testLoginPostRedirect($redirectDashboard, string $redirectUrl)
+    {
+        if (isset($redirectDashboard)) {
+            $this->_objectManager->get(ScopeConfigInterface::class)->setValue('customer/startup/redirect_dashboard', $redirectDashboard);
+        }
+
+        $this->_objectManager->get(Redirect::class)->setRedirectCookie('test');
+
+        $configValue = $this->_objectManager->create(Value::class);
+        $configValue->load('web/unsecure/base_url', 'path');
+        $baseUrl = $configValue->getValue() ?: 'http://localhost/';
+
+        $request = $this->prepareRequest();
+        $app = $this->_objectManager->create(Http::class, ['_request' => $request]);
+        $response = $app->launch();
+
+        $this->assertResponseRedirect($response, $baseUrl . $redirectUrl);
+        $this->assertTrue($this->_objectManager->get(Session::class)->isLoggedIn());
+    }
+
+    /**
+     * Data provider for testLoginPostRedirect.
+     *
+     * @return array
+     */
+    public function loginPostRedirectDataProvider()
+    {
+        return [
+            [null, 'index.php/'],
+            [0, 'index.php/'],
+            [1, 'index.php/customer/account/'],
+        ];
+    }
+
     /**
      * @return void
      */
@@ -717,4 +769,40 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
 
         return $customer;
     }
+
+    /**
+     * Prepare request for customer login.
+     *
+     * @return Request
+     */
+    private function prepareRequest()
+    {
+        $post = new Parameters([
+            'form_key' => $this->_objectManager->get(FormKey::class)->getFormKey(),
+            'login' => [
+                'username' => 'customer@example.com',
+                'password' => 'password'
+            ]
+        ]);
+        $request = $this->getRequest();
+        $formKey = $this->_objectManager->get(FormKey::class);
+        $request->setParam('form_key', $formKey->getFormKey());
+        $request->setMethod(Request::METHOD_POST);
+        $request->setRequestUri('customer/account/loginPost/');
+        $request->setPost($post);
+        return $request;
+    }
+
+    /**
+     * Assert response is redirect.
+     *
+     * @param Response $response
+     * @param string $redirectUrl
+     * @return void
+     */
+    private function assertResponseRedirect(Response $response, string $redirectUrl)
+    {
+        $this->assertTrue($response->isRedirect());
+        $this->assertSame($redirectUrl, $response->getHeader('Location')->getUri());
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/Controller/Adminhtml/Downloadable/FileTest.php b/dev/tests/integration/testsuite/Magento/Downloadable/Controller/Adminhtml/Downloadable/FileTest.php
deleted file mode 100644
index 4d19e973556c034ebce2f89d82cbe183d85c4439..0000000000000000000000000000000000000000
--- a/dev/tests/integration/testsuite/Magento/Downloadable/Controller/Adminhtml/Downloadable/FileTest.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-namespace Magento\Downloadable\Controller\Adminhtml\Downloadable;
-
-/**
- * Magento\Downloadable\Controller\Adminhtml\Downloadable\File
- *
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- * @magentoAppArea adminhtml
- */
-class FileTest extends \Magento\TestFramework\TestCase\AbstractBackendController
-{
-    public function testUploadAction()
-    {
-        copy(dirname(__DIR__) . '/_files/sample.txt', dirname(__DIR__) . '/_files/sample.tmp');
-        $_FILES = [
-            'samples' => [
-                'name' => 'sample.txt',
-                'type' => 'text/plain',
-                'tmp_name' => dirname(__DIR__) . '/_files/sample.tmp',
-                'error' => 0,
-                'size' => 0,
-            ],
-        ];
-
-        $this->dispatch('backend/admin/downloadable_file/upload/type/samples');
-        $body = $this->getResponse()->getBody();
-        $result = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            \Magento\Framework\Json\Helper\Data::class
-        )->jsonDecode(
-            $body
-        );
-        $this->assertEquals(0, $result['error']);
-    }
-}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/cache/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/cache/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/cache/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/cache/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/cache/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/cache/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/cache/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/cache/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/cache/.htaccess b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/cache/.htaccess
index 14249c50bd7605225950b2d372f352a2dba9252a..118789f3d955b474b963edb3afff24b2a829de96 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/cache/.htaccess
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/cache/.htaccess
@@ -1 +1,7 @@
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Css/PreProcessor/Adapter/CssInlinerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Css/PreProcessor/Adapter/CssInlinerTest.php
index f1468f718df619c3922da42203921cdbe8a2d44e..63c14b4293f7b108ca90b4a5f3097b3a82614c39 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Css/PreProcessor/Adapter/CssInlinerTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Css/PreProcessor/Adapter/CssInlinerTest.php
@@ -76,12 +76,10 @@ class CssInlinerTest extends \PHPUnit\Framework\TestCase
         $emogrifier->setHtml($html);
         $result = $emogrifier->emogrify();
         /**
-         * Tests a bug in the library where there's no spaces to CSS string before passing to Emogrifier
-         * to fix known parsing issue with library.
-         * This test should will fail when this bug is fixed in the library and we should fix the adapter.
-         * https://github.com/jjriv/emogrifier/issues/370
+         * This test was implemented for the issue which existed in the older version of Emogrifier.
+         * Test was updated, as the library got updated as well.
          */
-        $this->assertNotContains($cssExpected, $result);
+        $this->assertContains($cssExpected, $result);
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/PageCache/Block/System/Config/Form/Field/ExportTest.php b/dev/tests/integration/testsuite/Magento/PageCache/Block/System/Config/Form/Field/ExportTest.php
index 8abe1e9711d998f8b0b677da258f85fddb96453a..19e6bf450e01cb7e3cc09ca5dd7f898b9a41d8c6 100644
--- a/dev/tests/integration/testsuite/Magento/PageCache/Block/System/Config/Form/Field/ExportTest.php
+++ b/dev/tests/integration/testsuite/Magento/PageCache/Block/System/Config/Form/Field/ExportTest.php
@@ -15,6 +15,8 @@ class ExportTest extends \Magento\TestFramework\TestCase\AbstractBackendControll
      * @covers \Magento\PageCache\Block\System\Config\Form\Field\Export::_getElementHtml
      * @covers \Magento\PageCache\Block\System\Config\Form\Field\Export\Varnish5::getVarnishVersion
      * @covers \Magento\PageCache\Block\System\Config\Form\Field\Export\Varnish4::getVarnishVersion
+     * @magentoAppIsolation enabled
+     * @magentoDbIsolation enabled
      */
     public function testExportButtons()
     {
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/ExpressTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/ExpressTest.php
index 157999224d7b8a506d479edcb6d5fca68f07b7a2..95e3abbfe6ff15d69624458e5dc8c128ed8df809 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/ExpressTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/ExpressTest.php
@@ -142,6 +142,8 @@ class ExpressTest extends \Magento\TestFramework\TestCase\AbstractController
      * Test return action with configurable product.
      *
      * @magentoDataFixture Magento/Paypal/_files/quote_express_configurable.php
+     * @magentoDbIsolation enabled
+     * @magentoAppIsolation enabled
      */
     public function testReturnAction()
     {
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/configurable_attribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..12f63993cb2d31858423ad8a9c8a346fa87760f0
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/configurable_attribute.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright © Magento, Inc. 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' => 0,
+            'is_visible_in_advanced_search' => 0,
+            'is_comparable' => 0,
+            'is_filterable' => 0,
+            'is_filterable_in_search' => 0,
+            '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/Paypal/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/product_configurable.php
new file mode 100644
index 0000000000000000000000000000000000000000..7851abd965d8c4884dcd4d634efe9e59ebd70887
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/product_configurable.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright © Magento, Inc. 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;
+
+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 = [101, 201];
+array_shift($options); //remove the first option which is empty
+
+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' => 1
+        ]);
+
+    $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(1);
+    $stockItem->save();
+
+    $attributeValues[] = [
+        'label' => 'test',
+        'attribute_id' => $attribute->getId(),
+        'value_index' => $option->getValue(),
+    ];
+    $associatedProductIds[] = $product->getId();
+}
+
+/** @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(100)
+    ->setAttributeSetId($attributeSetId)
+    ->setWebsiteIds([1])
+    ->setName('Configurable Product')
+    ->setSku('configurable_express')
+    ->setVisibility(Visibility::VISIBILITY_BOTH)
+    ->setStatus(Status::STATUS_ENABLED)
+    ->setStockData([
+        'use_config_manage_stock' => 1,
+        'is_in_stock' => 1
+    ]);
+
+$productRepository->save($product);
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_configurable.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_configurable.php
index b3f14b188a32a75732e2e99f389ec35cdb7585e1..cf90172368d5cc6d4c5323e663e46e8095c11eac 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_configurable.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_configurable.php
@@ -11,7 +11,7 @@ use Magento\Quote\Model\Quote\Address;
 use Magento\Quote\Model\Quote\Address\Rate;
 use Magento\TestFramework\Helper\Bootstrap;
 
-require __DIR__ . '/../../../Magento/ConfigurableProduct/_files/product_configurable.php';
+require __DIR__ . '/product_configurable.php';
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = Bootstrap::getObjectManager();
@@ -19,7 +19,7 @@ $objectManager = Bootstrap::getObjectManager();
 /** @var $product \Magento\Catalog\Model\Product */
 /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
 $productRepository = $objectManager->create(ProductRepositoryInterface::class);
-$product = $productRepository->get('configurable');
+$product = $productRepository->get('configurable_express');
 
 /** @var $options Collection */
 $options = $objectManager->create(Collection::class);
@@ -27,8 +27,8 @@ $option = $options->setAttributeFilter($attribute->getId())->getFirstItem();
 
 $requestInfo = new \Magento\Framework\DataObject(
     [
-        'product' => 2,
-        'selected_configurable_option' => 2,
+        'product' => 1,
+        'selected_configurable_option' => 1,
         'qty' => 1,
         'super_attribute' => [
             $attribute->getId() => $option->getId()
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/GridAsyncInsertTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/GridAsyncInsertTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..726057cb86bb7b9e9f481668c8c5e47eea8c40a4
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/GridAsyncInsertTest.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Model;
+
+use Magento\Framework\Api\SearchCriteria;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Sales\Api\Data\OrderInterface;
+use Magento\Sales\Api\OrderRepositoryInterface;
+use Magento\Sales\Model\ResourceModel\Grid as AbstractGrid;
+use Magento\Sales\Model\ResourceModel\Order\Grid;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\ObjectManager;
+
+class GridAsyncInsertTest extends \PHPUnit\Framework\TestCase
+{
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * @var GridAsyncInsert
+     */
+    private $gridAsyncInsert;
+
+    /**
+     * @var AdapterInterface
+     */
+    private $connection;
+
+    /**
+     * @var OrderRepositoryInterface
+     */
+    private $orderRepository;
+
+    /**
+     * @var AbstractGrid
+     */
+    private $grid;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+
+        /** @var ResourceConnection $resourceConnection */
+        $resourceConnection = $this->objectManager->get(ResourceConnection::class);
+        $this->connection = $resourceConnection->getConnection('sales');
+        $this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class);
+        $this->grid = $this->objectManager->get(Grid::class);
+
+        $this->gridAsyncInsert = $this->objectManager->create(
+            GridAsyncInsert::class,
+            [
+                'entityGrid' => $this->grid
+            ]
+        );
+    }
+
+    /**
+     * Checks a case when order's grid should be updated asynchronously.
+     *
+     * @magentoConfigFixture default/dev/grid/async_indexing 1
+     * @magentoDataFixture Magento/Sales/_files/order.php
+     */
+    public function testExecuteAsyncUpdateOrderGrid()
+    {
+        $order = $this->getOrder('100000001');
+        $this->performUpdateAssertions($order);
+
+        // to un-sync main table and grid table need to wait at least one second
+        sleep(1);
+        $order->setStatus('complete');
+        $this->orderRepository->save($order);
+
+        $gridRow = $this->getGridRow($order->getEntityId());
+        self::assertNotEquals($order->getStatus(), $gridRow['status']);
+
+        $this->gridAsyncInsert->asyncInsert();
+        $this->performUpdateAssertions($order);
+    }
+
+    /**
+     * Loads order entity by provided order increment ID.
+     *
+     * @param string $incrementId
+     * @return OrderInterface
+     */
+    private function getOrder(string $incrementId) : OrderInterface
+    {
+        /** @var SearchCriteria $searchCriteria */
+        $searchCriteria = $this->objectManager->get(SearchCriteriaBuilder::class)
+            ->addFilter('increment_id', $incrementId)
+            ->create();
+
+        $items = $this->orderRepository->getList($searchCriteria)
+            ->getItems();
+
+        return array_pop($items);
+    }
+
+    /**
+     * Gets row from `sales_order_grid` table by order's ID.
+     *
+     * @param int $entityId
+     * @return array
+     */
+    private function getGridRow(int $entityId) : array
+    {
+        $tableName = $this->grid->getGridTable();
+        $select = $this->connection->select()
+            ->from($tableName)
+            ->where($tableName . '.entity_id = ?', $entityId);
+
+        return $this->connection->fetchRow($select);
+    }
+
+    /**
+     * Perform assertions for updating grid test.
+     *
+     * @param OrderInterface $order
+     */
+    private function performUpdateAssertions(OrderInterface $order)
+    {
+        $gridRow = $this->getGridRow($order->getEntityId());
+
+        self::assertEquals($order->getStatus(), $gridRow['status']);
+        self::assertEquals($order->getUpdatedAt(), $gridRow['updated_at']);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Theme/Model/Config/Processor/DesignThemeTest.php b/dev/tests/integration/testsuite/Magento/Theme/Model/Config/Processor/DesignThemeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..01c8ebca57ac2dcb97e0c9f04c7b5396047046e6
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Theme/Model/Config/Processor/DesignThemeTest.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Theme\Model\Config\Processor;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+class DesignThemeTest extends \PHPUnit\Framework\TestCase
+{
+    /**
+     * Verifies that empty 'design/theme/theme_id' config value is processed without errors.
+     */
+    public function testProcessWithEmptyThemeId()
+    {
+        $designTheme = Bootstrap::getObjectManager()->create(DesignTheme::class);
+
+        $config = [
+            'default' => [
+                'design' => ['theme' => ['theme_id' => '']],
+            ],
+        ];
+
+        $this->assertEquals($config, $designTheme->process($config));
+    }
+}
diff --git a/generated/.htaccess b/generated/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/generated/.htaccess
+++ b/generated/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/lib/.htaccess b/lib/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/lib/.htaccess
+++ b/lib/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/CssInliner.php b/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/CssInliner.php
index 342283c312293fdb16ee642ca28eb9fec09a6dcd..7164e68c709fb81630dfe230d440f080f6712a8e 100644
--- a/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/CssInliner.php
+++ b/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/CssInliner.php
@@ -41,13 +41,7 @@ class CssInliner
      */
     public function setCss($css)
     {
-        /**
-         * Adds space to CSS string before passing to Emogrifier to fix known parsing issue with library.
-         * https://github.com/jjriv/emogrifier/issues/370
-         */
-        $cssWithAddedSpaces = preg_replace('#([\{\}>])#i', ' $1 ', $css);
-
-        $this->emogrifier->setCss($cssWithAddedSpaces);
+        $this->emogrifier->setCss($css);
     }
 
     /**
diff --git a/lib/internal/Magento/Framework/CurrencyInterface.php b/lib/internal/Magento/Framework/CurrencyInterface.php
index 4dbde431041fc8d66a012cfd01f22b97d7fb7adf..44a7d3b90081e16742391320eb73726dd315c626 100644
--- a/lib/internal/Magento/Framework/CurrencyInterface.php
+++ b/lib/internal/Magento/Framework/CurrencyInterface.php
@@ -240,7 +240,7 @@ interface CurrencyInterface
      * Returns the set service class
      *
      * @return \Zend_Currency_CurrencyInterface
-     * @deprecated
+     * @deprecated 101.0.1
      * @see \Magento\Directory\Model\Currency\Import\ImportInterface
      */
     public function getService();
@@ -250,7 +250,7 @@ interface CurrencyInterface
      *
      * @param string|\Zend_Currency_CurrencyInterface $service Service class
      * @return \Zend_Currency_CurrencyInterface
-     * @deprecated
+     * @deprecated 101.0.1
      * @see \Magento\Directory\Model\Currency\Import\ImportInterface
      */
     public function setService($service);
diff --git a/lib/internal/Magento/Framework/Module/Setup/Migration.php b/lib/internal/Magento/Framework/Module/Setup/Migration.php
index 467ee6146ade74c3c39311b38dfe381149800e3b..604a98f1c0dd3c04b0b81bfb73a46e488cc8bb07 100644
--- a/lib/internal/Magento/Framework/Module/Setup/Migration.php
+++ b/lib/internal/Magento/Framework/Module/Setup/Migration.php
@@ -703,7 +703,7 @@ class Migration
      * @return string|int|float|bool|array|null
      * @throws \InvalidArgumentException
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     * @deprecated
+     * @deprecated 101.0.1
      * @see \Magento\Framework\Module\Setup\Migration::jsonDecode
      */
     protected function _jsonDecode($encodedValue, $objectDecodeType = 1)
diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/ViewTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/ViewTest.php
index 0c32665a54219c2b1b84b29297865948d22a96a3..3fd8ea93c9bbe8985e9fa3349f4a396d71358f4e 100644
--- a/lib/internal/Magento/Framework/Mview/Test/Unit/ViewTest.php
+++ b/lib/internal/Magento/Framework/Mview/Test/Unit/ViewTest.php
@@ -263,7 +263,6 @@ class ViewTest extends \PHPUnit\Framework\TestCase
         $currentVersionId = 3;
         $lastVersionId = 1;
         $listId = [2, 3];
-        $defaultBatchSize = 1000;
 
         $this->stateMock->expects($this->any())
             ->method('getViewId')
@@ -297,7 +296,7 @@ class ViewTest extends \PHPUnit\Framework\TestCase
             'getList'
         )->with(
             $lastVersionId,
-            $lastVersionId + $defaultBatchSize
+            $currentVersionId
         )->will(
             $this->returnValue($listId)
         );
@@ -327,7 +326,6 @@ class ViewTest extends \PHPUnit\Framework\TestCase
         $currentVersionId = 3;
         $lastVersionId = 1;
         $listId = [2, 3];
-        $defaultBatchSize = 1000;
 
         $this->stateMock->expects($this->any())
             ->method('getViewId')
@@ -360,7 +358,7 @@ class ViewTest extends \PHPUnit\Framework\TestCase
             'getList'
         )->with(
             $lastVersionId,
-            $lastVersionId + $defaultBatchSize
+            $currentVersionId
         )->will(
             $this->returnValue($listId)
         );
diff --git a/lib/internal/Magento/Framework/Mview/View.php b/lib/internal/Magento/Framework/Mview/View.php
index b489dd7d59e4347ef8aadd3c0cec22c8dc14f755..1f1bde6bb021c28205894de82a16ff7e391fae76 100644
--- a/lib/internal/Magento/Framework/Mview/View.php
+++ b/lib/internal/Magento/Framework/Mview/View.php
@@ -21,6 +21,11 @@ class View extends \Magento\Framework\DataObject implements ViewInterface
      */
     const DEFAULT_BATCH_SIZE = 1000;
 
+    /**
+     * Max versions to load from database at a time
+     */
+    private static $maxVersionQueryBatch = 100000;
+
     /**
      * @var string
      */
@@ -272,14 +277,19 @@ class View extends \Magento\Framework\DataObject implements ViewInterface
             try {
                 $this->getState()->setStatus(View\StateInterface::STATUS_WORKING)->save();
 
+                $versionBatchSize = self::$maxVersionQueryBatch;
                 $batchSize = isset($this->changelogBatchSize[$this->getChangelog()->getViewId()])
                     ? $this->changelogBatchSize[$this->getChangelog()->getViewId()]
                     : self::DEFAULT_BATCH_SIZE;
 
-                for ($versionFrom = $lastVersionId; $versionFrom < $currentVersionId; $versionFrom += $batchSize) {
-                    $ids = $this->getChangelog()->getList($versionFrom, $versionFrom + $batchSize);
+                for ($versionFrom = $lastVersionId; $versionFrom < $currentVersionId; $versionFrom += $versionBatchSize) {
+                    // Don't go past the current version for atomicy.
+                    $versionTo = min($currentVersionId, $versionFrom + $versionBatchSize);
+                    $ids = $this->getChangelog()->getList($versionFrom, $versionTo);
 
-                    if (!empty($ids)) {
+                    // We run the actual indexer in batches.  Chunked AFTER loading to avoid duplicates in separate chunks.
+                    $chunks = array_chunk($ids, $batchSize);
+                    foreach ($chunks as $ids) {
                         $action->execute($ids);
                     }
                 }
diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php
index e621909ec99b6cc881699b586ea72ed435efabb6..4f5c65c799be8b9fcd852d7391990d3d2db61376 100644
--- a/lib/internal/Magento/Framework/Mview/View/Subscription.php
+++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php
@@ -10,6 +10,8 @@ namespace Magento\Framework\Mview\View;
 
 use Magento\Framework\App\ResourceConnection;
 use Magento\Framework\DB\Ddl\Trigger;
+use Magento\Framework\DB\Ddl\TriggerFactory;
+use Magento\Framework\Mview\ViewInterface;
 
 class Subscription implements SubscriptionInterface
 {
@@ -21,12 +23,12 @@ class Subscription implements SubscriptionInterface
     protected $connection;
 
     /**
-     * @var \Magento\Framework\DB\Ddl\TriggerFactory
+     * @var TriggerFactory
      */
     protected $triggerFactory;
 
     /**
-     * @var \Magento\Framework\Mview\View\CollectionInterface
+     * @var CollectionInterface
      */
     protected $viewCollection;
 
@@ -57,21 +59,31 @@ class Subscription implements SubscriptionInterface
      */
     protected $resource;
 
+    /**
+     * List of columns that can be updated in a subscribed table
+     * without creating a new change log entry
+     *
+     * @var array
+     */
+    private $ignoredUpdateColumns = [];
+
     /**
      * @param ResourceConnection $resource
-     * @param \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory
-     * @param \Magento\Framework\Mview\View\CollectionInterface $viewCollection
-     * @param \Magento\Framework\Mview\ViewInterface $view
+     * @param TriggerFactory $triggerFactory
+     * @param CollectionInterface $viewCollection
+     * @param ViewInterface $view
      * @param string $tableName
      * @param string $columnName
+     * @param array $ignoredUpdateColumns
      */
     public function __construct(
         ResourceConnection $resource,
-        \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory,
-        \Magento\Framework\Mview\View\CollectionInterface $viewCollection,
-        \Magento\Framework\Mview\ViewInterface $view,
+        TriggerFactory $triggerFactory,
+        CollectionInterface $viewCollection,
+        ViewInterface $view,
         $tableName,
-        $columnName
+        $columnName,
+        array $ignoredUpdateColumns = []
     ) {
         $this->connection = $resource->getConnection();
         $this->triggerFactory = $triggerFactory;
@@ -80,12 +92,13 @@ class Subscription implements SubscriptionInterface
         $this->tableName = $tableName;
         $this->columnName = $columnName;
         $this->resource = $resource;
+        $this->ignoredUpdateColumns = $ignoredUpdateColumns;
     }
 
     /**
-     * Create subsciption
+     * Create subscription
      *
-     * @return \Magento\Framework\Mview\View\SubscriptionInterface
+     * @return SubscriptionInterface
      */
     public function create()
     {
@@ -102,7 +115,7 @@ class Subscription implements SubscriptionInterface
 
             // Add statements for linked views
             foreach ($this->getLinkedViews() as $view) {
-                /** @var \Magento\Framework\Mview\ViewInterface $view */
+                /** @var ViewInterface $view */
                 $trigger->addStatement($this->buildStatement($event, $view->getChangelog()));
             }
 
@@ -116,7 +129,7 @@ class Subscription implements SubscriptionInterface
     /**
      * Remove subscription
      *
-     * @return \Magento\Framework\Mview\View\SubscriptionInterface
+     * @return SubscriptionInterface
      */
     public function remove()
     {
@@ -131,7 +144,7 @@ class Subscription implements SubscriptionInterface
 
             // Add statements for linked views
             foreach ($this->getLinkedViews() as $view) {
-                /** @var \Magento\Framework\Mview\ViewInterface $view */
+                /** @var ViewInterface $view */
                 $trigger->addStatement($this->buildStatement($event, $view->getChangelog()));
             }
 
@@ -154,10 +167,10 @@ class Subscription implements SubscriptionInterface
     protected function getLinkedViews()
     {
         if (!$this->linkedViews) {
-            $viewList = $this->viewCollection->getViewsByStateMode(\Magento\Framework\Mview\View\StateInterface::MODE_ENABLED);
+            $viewList = $this->viewCollection->getViewsByStateMode(StateInterface::MODE_ENABLED);
 
             foreach ($viewList as $view) {
-                /** @var \Magento\Framework\Mview\ViewInterface $view */
+                /** @var ViewInterface $view */
                 // Skip the current view
                 if ($view->getId() == $this->getView()->getId()) {
                     continue;
@@ -175,35 +188,58 @@ class Subscription implements SubscriptionInterface
     }
 
     /**
-     * Build trigger statement for INSER, UPDATE, DELETE events
+     * Build trigger statement for INSERT, UPDATE, DELETE events
      *
      * @param string $event
-     * @param \Magento\Framework\Mview\View\ChangelogInterface $changelog
+     * @param ChangelogInterface $changelog
      * @return string
      */
     protected function buildStatement($event, $changelog)
     {
         switch ($event) {
             case Trigger::EVENT_INSERT:
+                $trigger = "INSERT IGNORE INTO %s (%s) VALUES (NEW.%s);";
+                break;
+
             case Trigger::EVENT_UPDATE:
-                return sprintf(
-                    "INSERT IGNORE INTO %s (%s) VALUES (NEW.%s);",
-                    $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())),
-                    $this->connection->quoteIdentifier($changelog->getColumnName()),
-                    $this->connection->quoteIdentifier($this->getColumnName())
-                );
+                $trigger = "INSERT IGNORE INTO %s (%s) VALUES (NEW.%s);";
+
+                if ($this->connection->isTableExists($this->getTableName())
+                    && $describe = $this->connection->describeTable($this->getTableName())
+                ) {
+                    $columnNames = array_column($describe, 'COLUMN_NAME');
+                    $columnNames = array_diff($columnNames, $this->ignoredUpdateColumns);
+                    if ($columnNames) {
+                        $columns = [];
+                        foreach ($columnNames as $columnName) {
+                            $columns[] = sprintf(
+                                'NEW.%1$s != OLD.%1$s',
+                                $this->connection->quoteIdentifier($columnName)
+                            );
+                        }
+                        $trigger = sprintf(
+                            "IF (%s) THEN %s END IF;",
+                            implode(' OR ', $columns),
+                            $trigger
+                        );
+                    }
+                }
+                break;
 
             case Trigger::EVENT_DELETE:
-                return sprintf(
-                    "INSERT IGNORE INTO %s (%s) VALUES (OLD.%s);",
-                    $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())),
-                    $this->connection->quoteIdentifier($changelog->getColumnName()),
-                    $this->connection->quoteIdentifier($this->getColumnName())
-                );
+                $trigger = "INSERT IGNORE INTO %s (%s) VALUES (OLD.%s);";
+                break;
 
             default:
                 return '';
         }
+
+        return sprintf(
+            $trigger,
+            $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())),
+            $this->connection->quoteIdentifier($changelog->getColumnName()),
+            $this->connection->quoteIdentifier($this->getColumnName())
+        );
     }
 
     /**
@@ -225,7 +261,7 @@ class Subscription implements SubscriptionInterface
     /**
      * Retrieve View related to subscription
      *
-     * @return \Magento\Framework\Mview\ViewInterface
+     * @return ViewInterface
      * @codeCoverageIgnore
      */
     public function getView()
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime.php b/lib/internal/Magento/Framework/Stdlib/DateTime.php
index 36db84860b373c6bd9bda49a2c49954b2fd557be..5a1902426e7ae2291307d4f8314f0996f4f97318 100644
--- a/lib/internal/Magento/Framework/Stdlib/DateTime.php
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime.php
@@ -79,7 +79,7 @@ class DateTime
      * @param int $time
      * @return string The given time in given format
      *
-     * @deprecated
+     * @deprecated 101.0.1
      * @see Use Intl library for datetime handling: http://php.net/manual/en/book.intl.php
      *
      * @codeCoverageIgnore
@@ -95,7 +95,7 @@ class DateTime
      * @param string $timeStr
      * @return int
      *
-     * @deprecated
+     * @deprecated 101.0.1
      * @see Use Intl library for datetime handling: http://php.net/manual/en/book.intl.php
      *
      * @codeCoverageIgnore
diff --git a/lib/internal/Magento/Framework/View/Asset/Bundle.php b/lib/internal/Magento/Framework/View/Asset/Bundle.php
index bdaf13ddbbb27a7b00c62383d1760a27f565ab6d..80f35f9d57075a96f1669616697d37672f488e6b 100644
--- a/lib/internal/Magento/Framework/View/Asset/Bundle.php
+++ b/lib/internal/Magento/Framework/View/Asset/Bundle.php
@@ -212,7 +212,11 @@ class Bundle
         $assetContentType = $asset->getContentType();
         $assetKey = $this->getAssetKey($asset);
         if (!isset($this->assetsContent[$assetContextCode][$assetContentType][$assetKey])) {
-            $this->assetsContent[$assetContextCode][$assetContentType][$assetKey] = utf8_encode($asset->getContent());
+            $content = $asset->getContent();
+            if (mb_detect_encoding($content) !== "UTF-8") {
+                $content = mb_convert_encoding($content, "UTF-8");
+            }
+            $this->assetsContent[$assetContextCode][$assetContentType][$assetKey] = $content;
         }
 
         return $this->assetsContent[$assetContextCode][$assetContentType][$assetKey];
diff --git a/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php b/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php
index c2e7c324d1282bade8951bac5633152ba7e4eaea..7cd9a167809a2543efc3ce29acffa0af5ab91dd8 100644
--- a/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php
+++ b/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php
@@ -14,7 +14,7 @@ class Json implements \Magento\Framework\Webapi\Rest\Request\DeserializerInterfa
 {
     /**
      * @var \Magento\Framework\Json\Decoder
-     * @deprecated
+     * @deprecated 101.0.1
      */
     protected $decoder;
 
diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json
index 55d6e55d4977f7c8a02debdd44fd3ee5fa350dfd..aee3e0442c2592d00979bff9206972d3650996f2 100644
--- a/lib/internal/Magento/Framework/composer.json
+++ b/lib/internal/Magento/Framework/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/framework",
     "description": "N/A",
     "type": "magento2-library",
-    "version": "101.0.0",
+    "version": "101.0.1",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
@@ -21,7 +21,7 @@
         "lib-libxml": "*",
         "ext-xsl": "*",
         "symfony/process": "~2.1",
-        "colinmollenhour/php-redis-session-abstract": "~1.2.2",
+        "colinmollenhour/php-redis-session-abstract": "1.3.4",
         "composer/composer": "1.4.1",
         "monolog/monolog": "^1.17",
         "oyejorge/less.php": "~1.7.0",
diff --git a/phpserver/.htaccess b/phpserver/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/phpserver/.htaccess
+++ b/phpserver/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/pub/.htaccess b/pub/.htaccess
index 047ba279f86515fcaf678d38e157f642092f76f5..8ba04ff4415f359e50ec91618b6c61bd5cbaaf05 100644
--- a/pub/.htaccess
+++ b/pub/.htaccess
@@ -190,8 +190,13 @@
 ## Deny access to release notes to prevent disclosure of the installed Magento version
 
     <Files RELEASE_NOTES.txt>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
 
 # For 404s and 403s that aren't handled by the application, show plain 404 response
@@ -207,8 +212,13 @@ ErrorDocument 403 /errors/404.php
 ###########################################
 ## Deny access  to cron.php
     <Files cron.php>
-        order allow,deny
-        deny from all
+        <IfVersion < 2.4>
+            order allow,deny
+            deny from all
+        </IfVersion>
+        <IfVersion >= 2.4>
+            Require all denied
+        </IfVersion>
     </Files>
 
 <IfModule mod_headers.c>
diff --git a/pub/media/customer/.htaccess b/pub/media/customer/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/pub/media/customer/.htaccess
+++ b/pub/media/customer/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/pub/media/downloadable/.htaccess b/pub/media/downloadable/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/pub/media/downloadable/.htaccess
+++ b/pub/media/downloadable/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/pub/media/import/.htaccess b/pub/media/import/.htaccess
index 93169e4eb44ffa5e6251f3532bb1902854703f07..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/pub/media/import/.htaccess
+++ b/pub/media/import/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/pub/media/theme_customization/.htaccess b/pub/media/theme_customization/.htaccess
index ae8ddd114d94ebf5b20f70f8bcd988aa9fab4511..2b93da6b4c0792595ff0778ff7b669241b52cedc 100644
--- a/pub/media/theme_customization/.htaccess
+++ b/pub/media/theme_customization/.htaccess
@@ -1,5 +1,10 @@
 Options -Indexes
 <Files ~ "\.xml$">
-    Order allow,deny
-    Deny from all
+    <IfVersion < 2.4>
+        order allow,deny
+        deny from all
+    </IfVersion>
+    <IfVersion >= 2.4>
+        Require all denied
+    </IfVersion>
 </Files>
diff --git a/setup/config/.htaccess b/setup/config/.htaccess
index 281d5c33db37cd1cc887dbb2d36897b897835071..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/setup/config/.htaccess
+++ b/setup/config/.htaccess
@@ -1,2 +1,8 @@
-order allow,deny
-deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/setup/performance-toolkit/.htaccess b/setup/performance-toolkit/.htaccess
index 281d5c33db37cd1cc887dbb2d36897b897835071..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/setup/performance-toolkit/.htaccess
+++ b/setup/performance-toolkit/.htaccess
@@ -1,2 +1,8 @@
-order allow,deny
-deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/setup/src/.htaccess b/setup/src/.htaccess
index 281d5c33db37cd1cc887dbb2d36897b897835071..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/setup/src/.htaccess
+++ b/setup/src/.htaccess
@@ -1,2 +1,8 @@
-order allow,deny
-deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php
index e3ab070bd8fbaba2c433d0410b7757d7b421aa9d..7e5b0c162a393161c38d6d09c5fdfd0352354d7f 100644
--- a/setup/src/Magento/Setup/Model/ConfigGenerator.php
+++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php
@@ -47,7 +47,7 @@ class ConfigGenerator
 
     /**
      * @var Random
-     * @deprecated since 100.2.0
+     * @deprecated 100.2.0
      */
     protected $random;
 
diff --git a/setup/view/.htaccess b/setup/view/.htaccess
index 281d5c33db37cd1cc887dbb2d36897b897835071..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/setup/view/.htaccess
+++ b/setup/view/.htaccess
@@ -1,2 +1,8 @@
-order allow,deny
-deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/var/.htaccess b/var/.htaccess
index 896fbc5a341ea313ff3abd503808842757678c1d..707c26b075e166bccee3cea4f8a52e7fe34269c1 100755
--- a/var/.htaccess
+++ b/var/.htaccess
@@ -1,2 +1,8 @@
-Order deny,allow
-Deny from all
\ No newline at end of file
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+
diff --git a/vendor/.htaccess b/vendor/.htaccess
index cb24fd7fc0b3a0e46f6cad19e834117476bd0341..707c26b075e166bccee3cea4f8a52e7fe34269c1 100644
--- a/vendor/.htaccess
+++ b/vendor/.htaccess
@@ -1,2 +1,8 @@
-Order allow,deny
-Deny from all
+<IfVersion < 2.4>
+    order allow,deny
+    deny from all
+</IfVersion>
+<IfVersion >= 2.4>
+    Require all denied
+</IfVersion>
+