Search

Mar 29, 2023

Magento 2 composer commands

Install B2B module

composer require magento/extension-b2b
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:clean

Install sample data M2.3

bin/magento sampledata:deploy
bin/magento setup:upgrade

Upgrade composer form v1 to v2

composer self-update --2
sudo composer self-update 2.1.14

You can go back at any time by using 
composer self-update --1
or 
Use: composer self-update --rollback 

This command allows Composer to rebuild the mapping to project files so that they load faster.

composer dump-autoload -o --apcu

Show Magento version List 

composer show magento/product-enterprise-edition 2.3.* --all | grep -m 1 versions
composer show magento/product-enterprise-edition --all | grep -m 1 versions
composer show magento/magento-cloud-metapackage --all | grep -m 1 versions
composer show mageplaza/magento-2-french-language-pack --all | grep -m 1 versions

Create M2 project

composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.1.18 <install-directory-name>

composer create-project --repository-url=https://repo.magento.com/ magento/project-enterprise-edition=2.4.0 <install-directory-name>

composer create-project --repository-url=https://repo.magento.com/ magento/project-enterprise-edition=2.4.3-p1 <install-directory-name>

composer create-project --repository-url=https://repo.magento.com/ magento/project-enterprise-edition=2.4.5-p1 <install-directory-name>

Upgrade M2 

For CE
sudo composer require magento/product-community-edition 2.2.4 --no-update

For EE
sudo composer require magento/product-enterprise-edition 2.4.3-p1 --no-update

For Cloud
sudo composer require magento/product-enterprise-edition 2.4.3-p1 --no-update
sudo composer require "magento/magento-cloud-metapackage":">=2.4.3 <2.4.4" --no-update
sudo composer install

Apply Patch for Adobe Commerce & Magento Open Source

Install the latest quality patches package: ./composer require magento/quality-patches
Apply the patch: ./vendor/bin/magento-patches apply ACSD-45520
Clean the cache: ./bin/magento cache:clean
ACSD-45520: Swatch options not selected on product detail page

Update ece-tools 

sudo composer update magento/ece-tools --with-dependencies
composer require magento/quality-patches

View path in magento version

./vendor/bin/magento-patches status 

Apply individual patches

./vendor/bin/magento-patches apply MAGETWO-XXXX
./vendor/bin/magento-patches apply MAGETWO-XXXX MAGETWO-YYYY

Revert all applied patches:

./vendor/bin/magento-patches revert MAGETWO-XXXX
php ./vendor/bin/ece-patches revert
./vendor/bin/magento-patches revert --all

Add MDVA-ID to Magento Cloud

stage:
  global:
    SCD_ON_DEMAND: true
  deploy:
    MYSQL_USE_SLAVE_CONNECTION: true
    CRON_CONSUMERS_RUNNER:
      cron_run: true
      consumers: []
  build:
    QUALITY_PATCHES:
      - MDVA-34023
      - MDVA-12304
      - MDVA-30232
      - MDVA-28656
      - MDVA-30106
      - MDVA-23764

Magento 2: Discard subsequent rules not working in Catalog Price Rule

Step by step:

0. Create rules:

1. Rule 1: USFlat20
    Apply as fixed amount: 20$
    Priority: 0
    Discard subsequent rules: No

2. Rule 2: USFlat10
    Apply as fixed amount: 10$
    Priority: 1
    Discard subsequent rules: Yes

3. Actual result: 
We've used the 'Discard subsequent rules' feature in Rule 2 but it doesn't seem to work.


CAUSE:

Let's analyze the situation from the screencast you provided:
You have two rules:
    + USFlat20 with priority 0 for -20$ and discard subsequent rules set to No
    + USFlat10 with priority 1 for -10$ and discard subsequent rules set to Yes

The test product is $74.38. Now how rules are applied:
    1. Get the list of rules ordered by priority in ascending order -> 1. USFlat20, 2. USFlat10
    2. Apply discount from the first rule -> USFlat20: 74.38 - 20 = 54.38
    3. Discard subsequent rules? -> No
    4. Apply discount from the second rule -> USFlat10: 54.38 - 10 = 44.38
    5. Discard subsequent rules? -> Yes
    6. End

As you can see the final price is now $44.38 and this is exactly what is visible in the screencast.

Now if we switch priorities for the above rules:
    + USFlat20 with priority 1 for -20$ and discard subsequent rules set to No
    + USFlat10 with priority 0 for -10$ and discard subsequent rules set to Yes

Again test product is $74.38, and rules are applied like this:
    1. Get the list of rules ordered by priority in ascending order -> 1. USFlat10, 2. USFlat20
    2. Apply discount from the first rule -> USFlat10: 74.38 - 10 = 64.38
    3. Discard subsequent rules? -> Yes
    4. End

In such a setup, the final price is $64.38.

This behavior is described in the documentation price-rules-catalog-create

Magento 2: Adding link Vimeo not working

Steps to reproduce: 

1. Log in to the Admin. 

2. To edit an existing product go to CATALOG > Products > Edit or to create a new product go to CATALOG > Products > Edit > Add Product . 

3. Click the Images And Videos tab in the Product page. 

4. Click Add Video and add a Vimeo video's URL. 

5. Expected result: The new video is found and saved. 

Actuals result: Error: "Video not Found" is displayed.


SOLUTION FOR M2 CLOUD:

1. Install the latest QPT package: 

    composer update magento/ece-tools --with-dependencies

2. Add MDVA-35092 to .magento.env.yaml file

    Example:

stage:
  build:
    QUALITY_PATCHES:
      - MDVA-35092


SOLUTION 2:

Follow the patch

diff --git a/vendor/magento/module-product-video/etc/csp_whitelist.xml
b/vendor/magento/module-product-video/etc/csp_whitelist.xml
new file mode 100644
index 00000000000..2e091440330
--- /dev/null
+++ b/vendor/magento/module-product-video/etc/csp_whitelist.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
+    <policies>
+        <policy id="script-src">
+            <values>
+                <value id="youtube_cdn" type="host">s.ytimg.com</value>
+                <value id="google_video" type="host">www.googleapis.com</value>
+                <value id="vimeo" type="host">vimeo.com</value>
+                <value id="www_vimeo" type="host">www.vimeo.com</value>
+                <value id="vimeo_cdn" type="host">*.vimeocdn.com</value>
+            </values>
+        </policy>
+        <policy id="img-src">
+            <values>
+                <value id="vimeo_cdn" type="host">*.vimeocdn.com</value>
+            </values>
+        </policy>
+        <policy id="frame-src">
+            <values>
+                <value id="player_vimeo" type="host">player.vimeo.com</value>
+            </values>
+        </policy>
+    </policies>
+</csp_whitelist>
diff --git a/vendor/magento/module-product-video/view/adminhtml/web/js/get-video-information.js b/vendor/magento/module-product-video/view/adminhtml/web/js/get-video-information.js
index 653434f1008..3b166b044e1 100644
--- a/vendor/magento/module-product-video/view/adminhtml/web/js/get-video-information.js
+++ b/vendor/magento/module-product-video/view/adminhtml/web/js/get-video-information.js
@@ -492,20 +492,20 @@ define([
                     var tmp,
                         respData;
 
-                    if (data.length < 1) {
+                    if (!data) {
                         this._onRequestError($.mage.__('Video not found'));
 
                         return null;
                     }
-                    tmp = data[0];
+                    tmp = data;
                     respData = {
                         duration: this._formatVimeoDuration(tmp.duration),
-                        channel: tmp['user_name'],
-                        channelId: tmp['user_url'],
+                        channel: tmp['author_name'],
+                        channelId: tmp['author_url'],
                         uploaded: tmp['upload_date'],
                         title: tmp.title,
                         description: tmp.description.replace(/(&nbsp;|<([^>]+)>)/ig, ''),
-                        thumbnail: tmp['thumbnail_large'],
+                        thumbnail: tmp['thumbnail_url'],
                         videoId: videoInfo.id,
                         videoProvider: videoInfo.type
                     };
@@ -534,10 +534,11 @@ define([
                     );
                 } else if (type === 'vimeo') {
                     $.ajax({
-                        url: 'https://www.vimeo.com/api/v2/video/' + id + '.json',
+                        url: 'https://vimeo.com/api/oembed.json',
                         dataType: 'jsonp',
                         data: {
-                            format: 'json'
+                            format: 'json',
+                            url: 'https://vimeo.com/' + id
                         },
                         timeout: 5000,
                         success:  $.proxy(_onVimeoLoaded, self),
diff --git a/vendor/magento/framework/File/Uploader.php b/vendor/magento/framework/File/Uploader.php
index c0126acf700..69ae2616c2d 100644
--- a/vendor/magento/framework/File/Uploader.php
+++ b/vendor/magento/framework/File/Uploader.php
@@ -6,7 +6,11 @@
 namespace Magento\Framework\File;
 
 use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\FileSystemException;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\DriverInterface;
+use Magento\Framework\Filesystem\DriverPool;
 use Magento\Framework\Validation\ValidationException;
 
 /**
@@ -144,15 +148,13 @@ class Uploader
 
     /**
      * Maximum Image Width resolution in pixels. For image resizing on client side
-     * @deprecated
-     * @see \Magento\Framework\Image\Adapter\UploadConfigInterface::getMaxWidth()
+     * @deprecated @see \Magento\Framework\Image\Adapter\UploadConfigInterface::getMaxWidth()
      */
     const MAX_IMAGE_WIDTH = 1920;
 
     /**
      * Maximum Image Height resolution in pixels. For image resizing on client side
-     * @deprecated
-     * @see \Magento\Framework\Image\Adapter\UploadConfigInterface::getMaxHeight()
+     * @deprecated @see \Magento\Framework\Image\Adapter\UploadConfigInterface::getMaxHeight()
      */
     const MAX_IMAGE_HEIGHT = 1200;
 
@@ -169,21 +171,32 @@ class Uploader
      */
     private $directoryList;
 
+    /**
+     * @var DriverPool|null
+     */
+    private $driverPool;
+
+    /**
+     * @var DriverInterface|null
+     */
+    private $fileDriver;
+
     /**
      * Init upload
      *
      * @param string|array $fileId
      * @param \Magento\Framework\File\Mime|null $fileMime
      * @param DirectoryList|null $directoryList
+     * @param DriverPool|null $driverPool
      * @throws \DomainException
      */
     public function __construct(
         $fileId,
         Mime $fileMime = null,
-        DirectoryList $directoryList = null
+        DirectoryList $directoryList = null,
+        DriverPool $driverPool = null
     ) {
-        $this->directoryList= $directoryList ?: \Magento\Framework\App\ObjectManager::getInstance()
-            ->get(DirectoryList::class);
+        $this->directoryList= $directoryList ?: ObjectManager::getInstance()->get(DirectoryList::class);
 
         $this->_setUploadFileId($fileId);
         if (!file_exists($this->_file['tmp_name'])) {
@@ -192,7 +205,8 @@ class Uploader
         } else {
             $this->_fileExists = true;
         }
-        $this->fileMime = $fileMime ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Mime::class);
+        $this->fileMime = $fileMime ?: ObjectManager::getInstance()->get(Mime::class);
+        $this->driverPool = $driverPool;
     }
 
     /**
@@ -230,7 +244,7 @@ class Uploader
             $this->setAllowCreateFolders(true);
             $this->_dispretionPath = static::getDispersionPath($fileName);
             $destinationFile .= $this->_dispretionPath;
-            $this->_createDestinationFolder($destinationFile);
+            $this->createDestinationFolder($destinationFile);
         }
 
         if ($this->_allowRenameFiles) {
@@ -275,13 +289,11 @@ class Uploader
      * @return void
      * @throws FileSystemException
      */
-    private function validateDestination($destinationFolder)
+    private function validateDestination(string $destinationFolder): void
     {
         if ($this->_allowCreateFolders) {
-            $this->_createDestinationFolder($destinationFolder);
-        }
-
-        if (!is_writable($destinationFolder)) {
+            $this->createDestinationFolder($destinationFolder);
+        } elseif (!$this->getFileDriver()->isWritable($destinationFolder)) {
             throw new FileSystemException(__('Destination folder is not writable or does not exists.'));
         }
     }
@@ -655,7 +667,7 @@ class Uploader
      * @return \Magento\Framework\File\Uploader
      * @throws FileSystemException
      */
-    private function _createDestinationFolder($destinationFolder)
+    private function createDestinationFolder(string $destinationFolder)
     {
         if (!$destinationFolder) {
             return $this;
@@ -665,11 +677,13 @@ class Uploader
             $destinationFolder = substr($destinationFolder, 0, -1);
         }
 
-        if (!(@is_dir($destinationFolder)
-            || @mkdir($destinationFolder, 0777, true)
-        )) {
-            throw new FileSystemException(__('Unable to create directory %1.', $destinationFolder));
+        if (!$this->getFileDriver()->isDirectory($destinationFolder)) {
+            $result = $this->getFileDriver()->createDirectory($destinationFolder);
+            if (!$result) {
+                throw new FileSystemException(__('Unable to create directory %1.', $destinationFolder));
+            }
         }
+
         return $this;
     }
 
@@ -681,20 +695,22 @@ class Uploader
      */
     public static function getNewFileName($destinationFile)
     {
+        /** @var Filesystem $fileSystem */
+        $fileSystem = ObjectManager::getInstance()->get(Filesystem::class);
+        $local = $fileSystem->getDirectoryRead(DirectoryList::ROOT);
+
+        $fileExists = function ($path) use ($local) {
+            return $local->isExist($path);
+        };
+
         $fileInfo = pathinfo($destinationFile);
-        if (file_exists($destinationFile)) {
-            $index = 1;
-            $baseName = $fileInfo['filename'] . '.' . $fileInfo['extension'];
-            while (file_exists($fileInfo['dirname'] . '/' . $baseName)) {
-                $baseName = $fileInfo['filename'] . '_' . $index . '.' . $fileInfo['extension'];
-                $index++;
-            }
-            $destFileName = $baseName;
-        } else {
-            return $fileInfo['basename'];
+        $index = 1;
+        while ($fileExists($fileInfo['dirname'] . '/' . $fileInfo['basename'])) {
+            $fileInfo['basename'] = $fileInfo['filename'] . '_' . ($index++);
+            $fileInfo['basename'] .= isset($fileInfo['extension']) ? '.' . $fileInfo['extension'] : '';
         }
 
-        return $destFileName;
+        return $fileInfo['basename'];
     }
 
     /**
@@ -732,4 +748,20 @@ class Uploader
         }
         return $dispersionPath;
     }
+
+    /**
+     * Get driver for file
+     *
+     * @deprecated
+     * @return DriverInterface
+     */
+    private function getFileDriver(): DriverInterface
+    {
+        if (!$this->fileDriver) {
+            $this->driverPool = $this->driverPool ?: ObjectManager::getInstance()->get(DriverPool::class);
+            $this->fileDriver = $this->driverPool->getDriver(DriverPool::FILE);
+        }
+
+        return $this->fileDriver;
+    }
 }
diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js
index ddf5a7f000d..62abff99e3b 100644
--- a/lib/web/fotorama/fotorama.js
+++ b/lib/web/fotorama/fotorama.js
@@ -858,13 +858,16 @@ fotoramaVersion = '4.6.4';
             dataFrame.thumbsReady = true;
         } else if (video.type === 'vimeo') {
             $.ajax({
-                url: getProtocol() + 'vimeo.com/api/v2/video/' + video.id + '.json',
+                url: getProtocol() + 'vimeo.com/api/oembed.json',
+                data: {
+                    url: 'https://vimeo.com/' + video.id
+                },
                 dataType: 'jsonp',
                 success: function (json) {
                     dataFrame.thumbsReady = true;
                     updateData(data, {
-                        img: json[0].thumbnail_large,
-                        thumb: json[0].thumbnail_small
+                        img: json[0].thumbnail_url,
+                        thumb: json[0].thumbnail_url
                     }, dataFrame.i, fotorama);
                 }
             });


Viewing customer shopping cart in admin shows all products in catalog when there is no active quote

Steps to reproduce: 

View a customer in the admin for whom there is no active quote. 

Click on the 'Shopping Cart' tab. 

Expected result: Nothing shows in the grid, as there is no active quote for which to show items.

Actual result: All products added to Magento show, giving the false impression that this is the contents of the customer's basket, whereas actually it's the contents of the catalog.


Solution 1: 

We're using Magento ver 2.3.4-p2, and found a fix in 2.4.x: 26437


Solution 2: 

Follow the patch for m2.3.5

diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..ec4bd93ee4f 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -105,14 +105,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();


Solution 3: 

Follow the patch for m2.3.5

diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..656a78d1165 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -5,37 +5,51 @@
  */
 namespace Magento\Customer\Block\Adminhtml\Edit\Tab;
 
-use Magento\Catalog\Model\Product;
+use Magento\Backend\Block\Template\Context;
+use Magento\Backend\Block\Widget\Form;
+use Magento\Backend\Block\Widget\Grid\Extended;
+use Magento\Backend\Helper\Data;
+use Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item;
+use Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction;
 use Magento\Customer\Controller\RegistryConstants;
-use Magento\Directory\Model\Currency;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\CollectionFactory;
+use Magento\Framework\Data\FormFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Registry;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\System\Store as SystemStore;
 
 /**
  * Adminhtml customer orders grid block
  *
  * @api
  * @since 100.0.2
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
+class Cart extends Extended
 {
     /**
      * Core registry
      *
-     * @var \Magento\Framework\Registry
+     * @var Registry
      */
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Data\CollectionFactory
+     * @var CollectionFactory
      */
     protected $_dataCollectionFactory;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\Quote
+     * @var Quote
      */
     protected $quote = null;
 
@@ -45,32 +59,46 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_parentTemplate;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
+    /**
+     * @var SystemStore
+     */
+    private $systemStore;
+    /**
+     * @var FormFactory
+     */
+    private $formFactory;
 
     /**
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param \Magento\Backend\Helper\Data $backendHelper
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Framework\Data\CollectionFactory $dataCollectionFactory
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param Context $context
+     * @param Data $backendHelper
+     * @param CartRepositoryInterface $quoteRepository
+     * @param CollectionFactory $dataCollectionFactory
+     * @param Registry $coreRegistry
+     * @param QuoteFactory $quoteFactory
      * @param array $data
+     * @param SystemStore|null $systemStore
+     * @param FormFactory|null $formFactory
      */
     public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        \Magento\Backend\Helper\Data $backendHelper,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory,
-        array $data = []
+        Context $context,
+        Data $backendHelper,
+        CartRepositoryInterface $quoteRepository,
+        CollectionFactory $dataCollectionFactory,
+        Registry $coreRegistry,
+        QuoteFactory $quoteFactory,
+        array $data = [],
+        ?SystemStore $systemStore = null,
+        ?FormFactory $formFactory = null
     ) {
         $this->_dataCollectionFactory = $dataCollectionFactory;
         $this->_coreRegistry = $coreRegistry;
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->systemStore = $systemStore ?? ObjectManager::getInstance()->get(SystemStore::class);
+        $this->formFactory = $formFactory ?? ObjectManager::getInstance()->get(FormFactory::class);
         parent::__construct($context, $backendHelper, $data);
     }
 
@@ -92,8 +120,11 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
      */
     protected function _prepareGrid()
     {
-        $this->setId('customer_cart_grid' . $this->getWebsiteId());
+        $this->setId('customer_cart_grid');
         parent::_prepareGrid();
+        if (!$this->_storeManager->isSingleStoreMode()) {
+            $this->prepareWebsiteFilter();
+        }
     }
 
     /**
@@ -105,14 +136,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();
@@ -130,7 +160,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Product'),
                 'index' => 'name',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item::class
+                'renderer' => Item::class
             ]
         );
 
@@ -168,7 +198,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Action'),
                 'index' => 'quote_item_id',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction::class,
+                'renderer' => Multiaction::class,
                 'filter' => false,
                 'sortable' => false,
                 'actions' => [
@@ -246,10 +276,59 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
 
             try {
                 $this->quote = $this->quoteRepository->getForCustomer($customerId, $storeIds);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            } catch (NoSuchEntityException $e) {
                 $this->quote = $this->quoteFactory->create()->setSharedStoreIds($storeIds);
             }
         }
         return $this->quote;
     }
+
+    /**
+     * Add website filter block to the layout
+     *
+     * @return void
+     */
+    private function prepareWebsiteFilter(): void
+    {
+        $form = $this->formFactory->create();
+        $form->addField(
+            'website_filter',
+            'select',
+            [
+                'name' => 'website_id',
+                'values' => $this->systemStore->getWebsiteOptionHash(),
+                'value' => $this->getWebsiteId() ?? $this->_storeManager->getWebsite()->getId(),
+                'no_span' => true,
+                'onchange' => "{$this->getJsObjectName()}.loadByElement(this);",
+            ]
+        );
+        /**
+         * @var Form $formWidget
+         */
+        $formWidget = $this->getLayout()->createBlock(Form::class);
+        $formWidget->setForm($form);
+        $formWidget->setTemplate('Magento_Customer::tab/cart_website_filter_form.phtml');
+        $this->setChild(
+            'website_filter_block',
+            $formWidget
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getMainButtonsHtml()
+    {
+        return $this->getWebsiteFilterHtml() . parent::getMainButtonsHtml();
+    }
+
+    /**
+     * Generate website filter
+     *
+     * @return string
+     */
+    private function getWebsiteFilterHtml(): string
+    {
+        return $this->getChildHtml('website_filter_block');
+    }
 }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
index 4008635cd7c..910f4e94b90 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
@@ -5,84 +5,116 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\ForwardFactory;
 use Magento\Customer\Api\AccountManagementInterface;
 use Magento\Customer\Api\AddressRepositoryInterface;
 use Magento\Customer\Api\CustomerRepositoryInterface;
 use Magento\Customer\Api\Data\AddressInterfaceFactory;
 use Magento\Customer\Api\Data\CustomerInterfaceFactory;
+use Magento\Customer\Controller\Adminhtml\Index as BaseAction;
+use Magento\Customer\Helper\View;
 use Magento\Customer\Model\Address\Mapper;
-use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Customer\Model\AddressFactory;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\Metadata\FormFactory;
 use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\App\Action\HttpGetActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Math\Random;
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\Framework\Registry;
+use Magento\Framework\View\Result\Layout;
+use Magento\Framework\View\Result\LayoutFactory;
+use Magento\Framework\View\Result\PageFactory;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
+ * Admin customer shopping cart controller
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  * @deprecated 101.0.0
  */
-class Cart extends \Magento\Customer\Controller\Adminhtml\Index
+class Cart extends BaseAction implements HttpGetActionInterface, HttpPostActionInterface
 {
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     private $quoteFactory;
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
 
     /**
      * Constructor
      *
-     * @param \Magento\Backend\App\Action\Context $context
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
-     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
-     * @param \Magento\Customer\Model\AddressFactory $addressFactory
-     * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory
-     * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
-     * @param \Magento\Customer\Helper\View $viewHelper
-     * @param \Magento\Framework\Math\Random $random
+     * @param Context $context
+     * @param Registry $coreRegistry
+     * @param FileFactory $fileFactory
+     * @param CustomerFactory $customerFactory
+     * @param AddressFactory $addressFactory
+     * @param FormFactory $formFactory
+     * @param SubscriberFactory $subscriberFactory
+     * @param View $viewHelper
+     * @param Random $random
      * @param CustomerRepositoryInterface $customerRepository
-     * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
+     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
      * @param Mapper $addressMapper
      * @param AccountManagementInterface $customerAccountManagement
      * @param AddressRepositoryInterface $addressRepository
      * @param CustomerInterfaceFactory $customerDataFactory
      * @param AddressInterfaceFactory $addressDataFactory
      * @param \Magento\Customer\Model\Customer\Mapper $customerMapper
-     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
+     * @param DataObjectProcessor $dataObjectProcessor
      * @param DataObjectHelper $dataObjectHelper
      * @param ObjectFactory $objectFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory
-     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
-     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
-     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
-     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
-     * @param \Magento\Quote\Model\QuoteFactory|null $quoteFactory
+     * @param LayoutFactory $resultLayoutFactory
+     * @param PageFactory $resultPageFactory
+     * @param ForwardFactory $resultForwardFactory
+     * @param JsonFactory $resultJsonFactory
+     * @param QuoteFactory|null $quoteFactory
+     * @param StoreManagerInterface|null $storeManager
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
-        \Magento\Backend\App\Action\Context $context,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
-        \Magento\Customer\Model\CustomerFactory $customerFactory,
-        \Magento\Customer\Model\AddressFactory $addressFactory,
-        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
-        \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory,
-        \Magento\Customer\Helper\View $viewHelper,
-        \Magento\Framework\Math\Random $random,
+        Context $context,
+        Registry $coreRegistry,
+        FileFactory $fileFactory,
+        CustomerFactory $customerFactory,
+        AddressFactory $addressFactory,
+        FormFactory $formFactory,
+        SubscriberFactory $subscriberFactory,
+        View $viewHelper,
+        Random $random,
         CustomerRepositoryInterface $customerRepository,
-        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+        ExtensibleDataObjectConverter $extensibleDataObjectConverter,
         Mapper $addressMapper,
         AccountManagementInterface $customerAccountManagement,
         AddressRepositoryInterface $addressRepository,
         CustomerInterfaceFactory $customerDataFactory,
         AddressInterfaceFactory $addressDataFactory,
         \Magento\Customer\Model\Customer\Mapper $customerMapper,
-        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
+        DataObjectProcessor $dataObjectProcessor,
         DataObjectHelper $dataObjectHelper,
         ObjectFactory $objectFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
-        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
-        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory = null
+        LayoutFactory $resultLayoutFactory,
+        PageFactory $resultPageFactory,
+        ForwardFactory $resultForwardFactory,
+        JsonFactory $resultJsonFactory,
+        QuoteFactory $quoteFactory = null,
+        ?StoreManagerInterface $storeManager = null
     ) {
         parent::__construct(
             $context,
@@ -111,13 +143,14 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
             $resultForwardFactory,
             $resultJsonFactory
         );
-        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(\Magento\Quote\Model\QuoteFactory::class);
+        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(QuoteFactory::class);
+        $this->storeManager = $storeManager ?? $this->_objectManager->get(StoreManagerInterface::class);
     }
 
     /**
      * Handle and then get cart grid contents
      *
-     * @return \Magento\Framework\View\Result\Layout
+     * @return Layout
      */
     public function execute()
     {
@@ -127,16 +160,17 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
         // delete an item from cart
         $deleteItemId = $this->getRequest()->getPost('delete');
         if ($deleteItemId) {
-            /** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
-            $quoteRepository = $this->_objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
-            /** @var \Magento\Quote\Model\Quote $quote */
+            /** @var CartRepositoryInterface $quoteRepository */
+            $quoteRepository = $this->_objectManager->create(CartRepositoryInterface::class);
+            /** @var Quote $quote */
             try {
-                $quote = $quoteRepository->getForCustomer($customerId);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+                $storeIds = $this->storeManager->getWebsite($websiteId)->getStoreIds();
+                $quote = $quoteRepository->getForCustomer($customerId, $storeIds);
+            } catch (NoSuchEntityException $e) {
                 $quote = $this->quoteFactory->create();
             }
             $quote->setWebsite(
-                $this->_objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getWebsite($websiteId)
+                $this->storeManager->getWebsite($websiteId)
             );
             $item = $quote->getItemById($deleteItemId);
             if ($item && $item->getId()) {
diff --git a/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
new file mode 100644
index 00000000000..ec903fa978f
--- /dev/null
+++ b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var $block \Magento\Backend\Block\Widget\Form */
+?>
+<?= $block->getFormHtml() ?>
+<?= $block->getChildHtml('form_after') ?>


SOLUTION 4:

diff --git a/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php b/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
index 1cc08ee961e..384b1ffd20d 100644
--- a/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
+++ b/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
@@ -35,7 +35,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
     /**
      * Product type code
      */
-    const TYPE_CODE = 'configurable';
+    public const TYPE_CODE = 'configurable';
 
     /**
      * Cache key for Used Product Attribute Ids
@@ -102,51 +102,45 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      */
     protected $_canConfigure = true;
 
+    /**
+     * Local cache
+     *
+     * @var array
+     */
+    protected $isSaleableBySku = [];
+
     /**
      * @var \Magento\Framework\App\Config\ScopeConfigInterface
      */
     protected $_scopeConfig;
 
     /**
-     * Catalog product type configurable
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable
      */
     protected $_catalogProductTypeConfigurable;
 
     /**
-     * Attribute collection factory
-     *
-     * @var
-     * \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory
+     * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory
      */
     protected $_attributeCollectionFactory;
 
     /**
-     * Product collection factory
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\CollectionFactory
      */
     protected $_productCollectionFactory;
 
     /**
-     * Configurable attribute factory
-     *
      * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory
      * @since 100.1.0
      */
     protected $configurableAttributeFactory;
 
     /**
-     * Eav attribute factory
-     *
      * @var \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory
      */
     protected $_eavAttributeFactory;
 
     /**
-     * Type configurable factory
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\ConfigurableFactory
      * @since 100.1.0
      */
@@ -183,8 +177,6 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
     private $customerSession;
 
     /**
-     * Product factory
-     *
      * @var ProductInterfaceFactory
      */
     private $productFactory;
@@ -585,7 +577,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      * @param  \Magento\Catalog\Model\Product $product
      * @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
      */
-    public function getUsedProductCollection($product)
+    protected function getLinkedProductCollection($product)
     {
         $collection = $this->_productCollectionFactory->create()->setFlag(
             'product_children',
@@ -600,6 +592,17 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
         return $collection;
     }
 
+    /**
+     * Retrieve related products collection. Extension point for listing
+     *
+     * @param  \Magento\Catalog\Model\Product $product
+     * @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
+     */
+    public function getUsedProductCollection($product)
+    {
+        return $this->getLinkedProductCollection($product);
+    }
+
     /**
      * Before save process
      *
@@ -744,15 +747,30 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      */
     public function isSalable($product)
     {
+        $storeId = $this->getStoreFilter($product);
+        if ($storeId instanceof \Magento\Store\Model\Store) {
+            $storeId = $storeId->getId();
+        }
+        if ($storeId === null && $product->getStoreId()) {
+            $storeId = $product->getStoreId();
+        }
+
+        $sku = $product->getSku();
+        if (isset($this->isSaleableBySku[$storeId][$sku])) {
+            return $this->isSaleableBySku[$storeId][$sku];
+        }
+
         $salable = parent::isSalable($product);
 
         if ($salable !== false) {
-            $collection = $this->getUsedProductCollection($product);
-            $collection->addStoreFilter($this->getStoreFilter($product));
+            $collection = $this->getLinkedProductCollection($product);
+            $collection->addStoreFilter($storeId);
             $collection = $this->salableProcessor->process($collection);
             $salable = 0 !== $collection->getSize();
         }
 
+        $this->isSaleableBySku[$storeId][$sku] = $salable;
+
         return $salable;
     }
 
diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..656a78d1165 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -5,37 +5,51 @@
  */
 namespace Magento\Customer\Block\Adminhtml\Edit\Tab;
 
-use Magento\Catalog\Model\Product;
+use Magento\Backend\Block\Template\Context;
+use Magento\Backend\Block\Widget\Form;
+use Magento\Backend\Block\Widget\Grid\Extended;
+use Magento\Backend\Helper\Data;
+use Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item;
+use Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction;
 use Magento\Customer\Controller\RegistryConstants;
-use Magento\Directory\Model\Currency;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\CollectionFactory;
+use Magento\Framework\Data\FormFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Registry;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\System\Store as SystemStore;
 
 /**
  * Adminhtml customer orders grid block
  *
  * @api
  * @since 100.0.2
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
+class Cart extends Extended
 {
     /**
      * Core registry
      *
-     * @var \Magento\Framework\Registry
+     * @var Registry
      */
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Data\CollectionFactory
+     * @var CollectionFactory
      */
     protected $_dataCollectionFactory;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\Quote
+     * @var Quote
      */
     protected $quote = null;
 
@@ -45,32 +59,46 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_parentTemplate;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
+    /**
+     * @var SystemStore
+     */
+    private $systemStore;
+    /**
+     * @var FormFactory
+     */
+    private $formFactory;
 
     /**
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param \Magento\Backend\Helper\Data $backendHelper
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Framework\Data\CollectionFactory $dataCollectionFactory
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param Context $context
+     * @param Data $backendHelper
+     * @param CartRepositoryInterface $quoteRepository
+     * @param CollectionFactory $dataCollectionFactory
+     * @param Registry $coreRegistry
+     * @param QuoteFactory $quoteFactory
      * @param array $data
+     * @param SystemStore|null $systemStore
+     * @param FormFactory|null $formFactory
      */
     public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        \Magento\Backend\Helper\Data $backendHelper,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory,
-        array $data = []
+        Context $context,
+        Data $backendHelper,
+        CartRepositoryInterface $quoteRepository,
+        CollectionFactory $dataCollectionFactory,
+        Registry $coreRegistry,
+        QuoteFactory $quoteFactory,
+        array $data = [],
+        ?SystemStore $systemStore = null,
+        ?FormFactory $formFactory = null
     ) {
         $this->_dataCollectionFactory = $dataCollectionFactory;
         $this->_coreRegistry = $coreRegistry;
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->systemStore = $systemStore ?? ObjectManager::getInstance()->get(SystemStore::class);
+        $this->formFactory = $formFactory ?? ObjectManager::getInstance()->get(FormFactory::class);
         parent::__construct($context, $backendHelper, $data);
     }
 
@@ -92,8 +120,11 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
      */
     protected function _prepareGrid()
     {
-        $this->setId('customer_cart_grid' . $this->getWebsiteId());
+        $this->setId('customer_cart_grid');
         parent::_prepareGrid();
+        if (!$this->_storeManager->isSingleStoreMode()) {
+            $this->prepareWebsiteFilter();
+        }
     }
 
     /**
@@ -105,14 +136,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();
@@ -130,7 +160,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Product'),
                 'index' => 'name',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item::class
+                'renderer' => Item::class
             ]
         );
 
@@ -168,7 +198,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Action'),
                 'index' => 'quote_item_id',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction::class,
+                'renderer' => Multiaction::class,
                 'filter' => false,
                 'sortable' => false,
                 'actions' => [
@@ -246,10 +276,59 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
 
             try {
                 $this->quote = $this->quoteRepository->getForCustomer($customerId, $storeIds);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            } catch (NoSuchEntityException $e) {
                 $this->quote = $this->quoteFactory->create()->setSharedStoreIds($storeIds);
             }
         }
         return $this->quote;
     }
+
+    /**
+     * Add website filter block to the layout
+     *
+     * @return void
+     */
+    private function prepareWebsiteFilter(): void
+    {
+        $form = $this->formFactory->create();
+        $form->addField(
+            'website_filter',
+            'select',
+            [
+                'name' => 'website_id',
+                'values' => $this->systemStore->getWebsiteOptionHash(),
+                'value' => $this->getWebsiteId() ?? $this->_storeManager->getWebsite()->getId(),
+                'no_span' => true,
+                'onchange' => "{$this->getJsObjectName()}.loadByElement(this);",
+            ]
+        );
+        /**
+         * @var Form $formWidget
+         */
+        $formWidget = $this->getLayout()->createBlock(Form::class);
+        $formWidget->setForm($form);
+        $formWidget->setTemplate('Magento_Customer::tab/cart_website_filter_form.phtml');
+        $this->setChild(
+            'website_filter_block',
+            $formWidget
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getMainButtonsHtml()
+    {
+        return $this->getWebsiteFilterHtml() . parent::getMainButtonsHtml();
+    }
+
+    /**
+     * Generate website filter
+     *
+     * @return string
+     */
+    private function getWebsiteFilterHtml(): string
+    {
+        return $this->getChildHtml('website_filter_block');
+    }
 }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
index 2603ac193e0..c57b53a56db 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
@@ -8,11 +8,13 @@ namespace Magento\Customer\Controller\Adminhtml\Cart\Product\Composite;
 
 use Magento\Backend\App\Action;
 use Magento\Framework\Exception\LocalizedException;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote\Item;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Quote\Model\ResourceModel\QuoteItemRetriever;
 
 /**
  * Catalog composite product configuration controller
- *
- * @author      Magento Core Team <core@magentocommerce.com>
  */
 abstract class Cart extends \Magento\Backend\App\Action
 {
@@ -21,7 +23,7 @@ abstract class Cart extends \Magento\Backend\App\Action
      *
      * @see _isAllowed()
      */
-    const ADMIN_RESOURCE = 'Magento_Customer::manage';
+    public const ADMIN_RESOURCE = 'Magento_Customer::manage';
 
     /**
      * Customer we're working with
@@ -40,32 +42,39 @@ abstract class Cart extends \Magento\Backend\App\Action
     /**
      * Quote item we're working with
      *
-     * @var \Magento\Quote\Model\Quote\Item
+     * @var Item
      */
     protected $_quoteItem = null;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
 
+    /**
+     * @var QuoteItemRetriever
+     */
+    private $quoteItemRetriever;
     /**
      * @param Action\Context $context
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param CartRepositoryInterface $quoteRepository
+     * @param QuoteFactory $quoteFactory
+     * @param QuoteItemRetriever $quoteItemRetriever
      */
     public function __construct(
         Action\Context $context,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory
+        CartRepositoryInterface $quoteRepository,
+        QuoteFactory $quoteFactory,
+        QuoteItemRetriever $quoteItemRetriever
     ) {
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->quoteItemRetriever = $quoteItemRetriever;
         parent::__construct($context);
     }
 
@@ -86,7 +95,9 @@ abstract class Cart extends \Magento\Backend\App\Action
         $websiteId = (int)$this->getRequest()->getParam('website_id');
 
         try {
-            $this->_quote = $this->quoteRepository->getForCustomer($this->_customerId);
+            /** @var Item $quoteItem */
+            $quoteItem = $this->quoteItemRetriever->getById($quoteItemId);
+            $this->_quote = $this->quoteRepository->getForCustomer($this->_customerId, [$quoteItem->getStoreId()]);
         } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
             $this->_quote = $this->quoteFactory->create();
         }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
index 4008635cd7c..910f4e94b90 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
@@ -5,84 +5,116 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\ForwardFactory;
 use Magento\Customer\Api\AccountManagementInterface;
 use Magento\Customer\Api\AddressRepositoryInterface;
 use Magento\Customer\Api\CustomerRepositoryInterface;
 use Magento\Customer\Api\Data\AddressInterfaceFactory;
 use Magento\Customer\Api\Data\CustomerInterfaceFactory;
+use Magento\Customer\Controller\Adminhtml\Index as BaseAction;
+use Magento\Customer\Helper\View;
 use Magento\Customer\Model\Address\Mapper;
-use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Customer\Model\AddressFactory;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\Metadata\FormFactory;
 use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\App\Action\HttpGetActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Math\Random;
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\Framework\Registry;
+use Magento\Framework\View\Result\Layout;
+use Magento\Framework\View\Result\LayoutFactory;
+use Magento\Framework\View\Result\PageFactory;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
+ * Admin customer shopping cart controller
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  * @deprecated 101.0.0
  */
-class Cart extends \Magento\Customer\Controller\Adminhtml\Index
+class Cart extends BaseAction implements HttpGetActionInterface, HttpPostActionInterface
 {
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     private $quoteFactory;
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
 
     /**
      * Constructor
      *
-     * @param \Magento\Backend\App\Action\Context $context
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
-     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
-     * @param \Magento\Customer\Model\AddressFactory $addressFactory
-     * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory
-     * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
-     * @param \Magento\Customer\Helper\View $viewHelper
-     * @param \Magento\Framework\Math\Random $random
+     * @param Context $context
+     * @param Registry $coreRegistry
+     * @param FileFactory $fileFactory
+     * @param CustomerFactory $customerFactory
+     * @param AddressFactory $addressFactory
+     * @param FormFactory $formFactory
+     * @param SubscriberFactory $subscriberFactory
+     * @param View $viewHelper
+     * @param Random $random
      * @param CustomerRepositoryInterface $customerRepository
-     * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
+     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
      * @param Mapper $addressMapper
      * @param AccountManagementInterface $customerAccountManagement
      * @param AddressRepositoryInterface $addressRepository
      * @param CustomerInterfaceFactory $customerDataFactory
      * @param AddressInterfaceFactory $addressDataFactory
      * @param \Magento\Customer\Model\Customer\Mapper $customerMapper
-     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
+     * @param DataObjectProcessor $dataObjectProcessor
      * @param DataObjectHelper $dataObjectHelper
      * @param ObjectFactory $objectFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory
-     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
-     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
-     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
-     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
-     * @param \Magento\Quote\Model\QuoteFactory|null $quoteFactory
+     * @param LayoutFactory $resultLayoutFactory
+     * @param PageFactory $resultPageFactory
+     * @param ForwardFactory $resultForwardFactory
+     * @param JsonFactory $resultJsonFactory
+     * @param QuoteFactory|null $quoteFactory
+     * @param StoreManagerInterface|null $storeManager
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
-        \Magento\Backend\App\Action\Context $context,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
-        \Magento\Customer\Model\CustomerFactory $customerFactory,
-        \Magento\Customer\Model\AddressFactory $addressFactory,
-        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
-        \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory,
-        \Magento\Customer\Helper\View $viewHelper,
-        \Magento\Framework\Math\Random $random,
+        Context $context,
+        Registry $coreRegistry,
+        FileFactory $fileFactory,
+        CustomerFactory $customerFactory,
+        AddressFactory $addressFactory,
+        FormFactory $formFactory,
+        SubscriberFactory $subscriberFactory,
+        View $viewHelper,
+        Random $random,
         CustomerRepositoryInterface $customerRepository,
-        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+        ExtensibleDataObjectConverter $extensibleDataObjectConverter,
         Mapper $addressMapper,
         AccountManagementInterface $customerAccountManagement,
         AddressRepositoryInterface $addressRepository,
         CustomerInterfaceFactory $customerDataFactory,
         AddressInterfaceFactory $addressDataFactory,
         \Magento\Customer\Model\Customer\Mapper $customerMapper,
-        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
+        DataObjectProcessor $dataObjectProcessor,
         DataObjectHelper $dataObjectHelper,
         ObjectFactory $objectFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
-        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
-        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory = null
+        LayoutFactory $resultLayoutFactory,
+        PageFactory $resultPageFactory,
+        ForwardFactory $resultForwardFactory,
+        JsonFactory $resultJsonFactory,
+        QuoteFactory $quoteFactory = null,
+        ?StoreManagerInterface $storeManager = null
     ) {
         parent::__construct(
             $context,
@@ -111,13 +143,14 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
             $resultForwardFactory,
             $resultJsonFactory
         );
-        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(\Magento\Quote\Model\QuoteFactory::class);
+        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(QuoteFactory::class);
+        $this->storeManager = $storeManager ?? $this->_objectManager->get(StoreManagerInterface::class);
     }
 
     /**
      * Handle and then get cart grid contents
      *
-     * @return \Magento\Framework\View\Result\Layout
+     * @return Layout
      */
     public function execute()
     {
@@ -127,16 +160,17 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
         // delete an item from cart
         $deleteItemId = $this->getRequest()->getPost('delete');
         if ($deleteItemId) {
-            /** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
-            $quoteRepository = $this->_objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
-            /** @var \Magento\Quote\Model\Quote $quote */
+            /** @var CartRepositoryInterface $quoteRepository */
+            $quoteRepository = $this->_objectManager->create(CartRepositoryInterface::class);
+            /** @var Quote $quote */
             try {
-                $quote = $quoteRepository->getForCustomer($customerId);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+                $storeIds = $this->storeManager->getWebsite($websiteId)->getStoreIds();
+                $quote = $quoteRepository->getForCustomer($customerId, $storeIds);
+            } catch (NoSuchEntityException $e) {
                 $quote = $this->quoteFactory->create();
             }
             $quote->setWebsite(
-                $this->_objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getWebsite($websiteId)
+                $this->storeManager->getWebsite($websiteId)
             );
             $item = $quote->getItemById($deleteItemId);
             if ($item && $item->getId()) {
diff --git a/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
new file mode 100644
index 00000000000..ec903fa978f
--- /dev/null
+++ b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var $block \Magento\Backend\Block\Widget\Form */
+?>
+<?= $block->getFormHtml() ?>
+<?= $block->getChildHtml('form_after') ?>
diff --git a/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php b/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php
new file mode 100644
index 00000000000..7595bbbf7d8
--- /dev/null
+++ b/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Quote\Model\ResourceModel;
+
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Quote\Model\Quote\Item;
+use Magento\Quote\Model\Quote\ItemFactory;
+
+/**
+ * Class is used to Retrieve Quote Item by id
+ */
+class QuoteItemRetriever
+{
+    /**
+     * @var ItemFactory
+     */
+    private $quoteItemFactory;
+
+    /**
+     * Constructor
+     *
+     * @param ItemFactory $quoteItemFactory
+     */
+    public function __construct(
+        ItemFactory $quoteItemFactory
+    ) {
+        $this->quoteItemFactory = $quoteItemFactory;
+    }
+
+    /**
+     * Retrieve Quote Item Model
+     *
+     * @param int $quoteItemId
+     * @return Item
+     * @throws NoSuchEntityException
+     */
+    public function getById(int $quoteItemId): Item
+    {
+        $quoteItem = $this->quoteItemFactory->create()->load($quoteItemId);
+        if (!$quoteItem->getId()) {
+            // Quote Item does not exist
+            throw new \Magento\Framework\Exception\NoSuchEntityException(
+                __('Invalid Quote Item id %1', $quoteItemId)
+            );
+        }
+
+        return $quoteItem;
+    }
+}
diff --git a/vendor/magento/module-quote/i18n/en_US.csv b/vendor/magento/module-quote/i18n/en_US.csv
index b2417929749..41c47fa0cb1 100644
--- a/vendor/magento/module-quote/i18n/en_US.csv
+++ b/vendor/magento/module-quote/i18n/en_US.csv
@@ -67,3 +67,4 @@ Carts,Carts
 "Invalid state change requested","Invalid state change requested"
 "Validated Country Code","Validated Country Code"
 "Validated Vat Number","Validated Vat Number"
+"Invalid Quote Item id %1","Invalid Quote Item id %1"