diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/system.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/system.xml index 1e1f4e86fa3dc..ad0ff68192af4 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/system.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/system.xml @@ -28,13 +28,11 @@ Magento\Config\Model\Config\Source\Yesno - + Magento\CatalogUrlRewrite\Model\TableCleaner Magento\Config\Model\Config\Source\Yesno - - Warning! Turning this option off will result in permanent removal of category/product URL rewrites without an ability to restore them.]]> - + Warning! Turning this option off will result in permanent removal of category/product URL rewrites without an ability to restore them.]]> generate_category_product_rewrites diff --git a/app/code/Magento/CatalogUrlRewrite/i18n/en_US.csv b/app/code/Magento/CatalogUrlRewrite/i18n/en_US.csv index 0f21e8ddf9fc9..1dddaa458a16c 100644 --- a/app/code/Magento/CatalogUrlRewrite/i18n/en_US.csv +++ b/app/code/Magento/CatalogUrlRewrite/i18n/en_US.csv @@ -5,5 +5,6 @@ "Product URL Suffix","Product URL Suffix" "Use Categories Path for Product URLs","Use Categories Path for Product URLs" "Create Permanent Redirect for URLs if URL Key Changed","Create Permanent Redirect for URLs if URL Key Changed" -"Generate "category/product" URL Rewrites","Generate "category/product" URL Rewrites" +"Generate ""category/product"" URL Rewrites","Generate ""category/product"" URL Rewrites" "URL key ""%1"" matches a reserved endpoint name (%2). Use another URL key.","URL key ""%1"" matches a reserved endpoint name (%2). Use another URL key." +"Warning! Turning this option off will result in permanent removal of category/product URL rewrites without an ability to restore them.","Warning! Turning this option off will result in permanent removal of category/product URL rewrites without an ability to restore them." diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php index 03cf4b1bdddec..0611a2df641e7 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php @@ -17,6 +17,7 @@ use Magento\Customer\Model\Data\CustomerSecureFactory; use Magento\Customer\Model\Delegation\Data\NewOperation; use Magento\Customer\Model\Delegation\Storage as DelegatedStorage; +use Magento\Customer\Model\ResourceModel\Customer\Collection; use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; @@ -31,6 +32,8 @@ /** * Customer repository. * + * CRUD operations for customer entity + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) */ @@ -187,8 +190,7 @@ public function save(CustomerInterface $customer, $passwordHash = null) { /** @var NewOperation|null $delegatedNewOperation */ $delegatedNewOperation = !$customer->getId() ? $this->delegatedStorage->consumeNewOperation() : null; - $prevCustomerData = null; - $prevCustomerDataArr = null; + $prevCustomerData = $prevCustomerDataArr = null; if ($customer->getId()) { $prevCustomerData = $this->getById($customer->getId()); $prevCustomerDataArr = $prevCustomerData->__toArray(); @@ -214,6 +216,7 @@ public function save(CustomerInterface $customer, $passwordHash = null) $prevCustomerData ? $prevCustomerData->getStoreId() : $this->storeManager->getStore()->getId() ); } + $this->setCustomerGroupId($customerModel, $customerArr, $prevCustomerDataArr); // Need to use attribute set or future updates can cause data loss if (!$customerModel->getAttributeSetId()) { $customerModel->setAttributeSetId(CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER); @@ -452,4 +455,18 @@ private function setValidationFlag($customerArray, $customerModel) $customerModel->setData('ignore_validation_flag', true); } } + + /** + * Set customer group id + * + * @param Customer $customerModel + * @param array $customerArr + * @param array $prevCustomerDataArr + */ + private function setCustomerGroupId($customerModel, $customerArr, $prevCustomerDataArr) + { + if (!isset($customerArr['group_id']) && $prevCustomerDataArr && isset($prevCustomerDataArr['group_id'])) { + $customerModel->setGroupId($prevCustomerDataArr['group_id']); + } + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php index 8032399e14881..015213847e7ee 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php @@ -211,6 +211,7 @@ public function testSave() 'setFirstFailure', 'setLockExpires', 'save', + 'setGroupId' ] ); @@ -245,9 +246,15 @@ public function testSave() $this->customer->expects($this->atLeastOnce()) ->method('getId') ->willReturn($customerId); - $this->customer->expects($this->atLeastOnce()) + $this->customer->expects($this->at(4)) ->method('__toArray') ->willReturn([]); + $this->customer->expects($this->at(3)) + ->method('__toArray') + ->willReturn(['group_id' => 1]); + $customerModel->expects($this->once()) + ->method('setGroupId') + ->with(1); $this->customerRegistry->expects($this->atLeastOnce()) ->method('retrieve') ->with($customerId) diff --git a/app/code/Magento/Payment/Model/Info.php b/app/code/Magento/Payment/Model/Info.php index 3b7f93be776ee..3ca9b072e8321 100644 --- a/app/code/Magento/Payment/Model/Info.php +++ b/app/code/Magento/Payment/Model/Info.php @@ -38,7 +38,7 @@ class Info extends AbstractExtensibleModel implements InfoInterface * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory - * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, + * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource @@ -188,6 +188,7 @@ public function getAdditionalInformation($key = null) */ public function unsAdditionalInformation($key = null) { + $this->_initAdditionalInformation(); if ($key && isset($this->_additionalInformation[$key])) { unset($this->_additionalInformation[$key]); return $this->setData('additional_information', $this->_additionalInformation); diff --git a/app/code/Magento/Sales/Model/Order/Payment/Info.php b/app/code/Magento/Sales/Model/Order/Payment/Info.php index fee846fe6a62c..479d96b5842d9 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Info.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Info.php @@ -192,6 +192,7 @@ public function getAdditionalInformation($key = null) */ public function unsAdditionalInformation($key = null) { + $this->initAdditionalInformation(); if ($key && isset($this->additionalInformation[$key])) { unset($this->additionalInformation[$key]); return $this->setData('additional_information', $this->additionalInformation); diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 9e33b86ea8215..103ba9d3fb4b7 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -7,6 +7,12 @@ namespace Magento\Ups\Model; +use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\Directory\Helper\Data; +use Magento\Directory\Model\CountryFactory; +use Magento\Directory\Model\CurrencyFactory; +use Magento\Directory\Model\RegionFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Async\CallbackDeferred; use Magento\Framework\DataObject; @@ -15,16 +21,30 @@ use Magento\Framework\HTTP\AsyncClient\Request; use Magento\Framework\HTTP\AsyncClientInterface; use Magento\Framework\HTTP\ClientFactory; +use Magento\Framework\Locale\FormatInterface; use Magento\Framework\Xml\Security; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Quote\Model\Quote\Address\RateResult\Error; +use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory as RateErrorFactory; +use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory as RateMethodFactory; +use Magento\Sales\Model\Order\Shipment as OrderShipment; use Magento\Shipping\Model\Carrier\AbstractCarrierOnline; use Magento\Shipping\Model\Carrier\CarrierInterface; use Magento\Shipping\Model\Rate\Result; use Magento\Shipping\Model\Rate\Result\ProxyDeferredFactory; +use Magento\Shipping\Model\Rate\ResultFactory as RateFactory; use Magento\Shipping\Model\Simplexml\Element; +use Magento\Shipping\Model\Simplexml\ElementFactory; +use Magento\Shipping\Model\Tracking\Result\ErrorFactory as TrackErrorFactory; +use Magento\Shipping\Model\Tracking\Result\StatusFactory as TrackStatusFactory; +use Magento\Shipping\Model\Tracking\ResultFactory as TrackFactory; +use Magento\Store\Model\ScopeInterface; use Magento\Ups\Helper\Config; use Magento\Shipping\Model\Shipment\Request as Shipment; +use Psr\Log\LoggerInterface; +use RuntimeException; +use Throwable; +use Zend_Http_Client; /** * UPS shipping implementation @@ -117,12 +137,12 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface protected $_customizableContainerTypes = ['CP', 'CSP']; /** - * @var \Magento\Framework\Locale\FormatInterface + * @var FormatInterface */ protected $_localeFormat; /** - * @var \Psr\Log\LoggerInterface + * @var LoggerInterface */ protected $_logger; @@ -149,22 +169,22 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface private $deferredProxyFactory; /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory - * @param \Psr\Log\LoggerInterface $logger + * @param ScopeConfigInterface $scopeConfig + * @param RateErrorFactory $rateErrorFactory + * @param LoggerInterface $logger * @param Security $xmlSecurity - * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory - * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory - * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory - * @param \Magento\Shipping\Model\Tracking\ResultFactory $trackFactory - * @param \Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory - * @param \Magento\Shipping\Model\Tracking\Result\StatusFactory $trackStatusFactory - * @param \Magento\Directory\Model\RegionFactory $regionFactory - * @param \Magento\Directory\Model\CountryFactory $countryFactory - * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory - * @param \Magento\Directory\Helper\Data $directoryData - * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry - * @param \Magento\Framework\Locale\FormatInterface $localeFormat + * @param ElementFactory $xmlElFactory + * @param RateFactory $rateFactory + * @param RateMethodFactory $rateMethodFactory + * @param TrackFactory $trackFactory + * @param TrackErrorFactory $trackErrorFactory + * @param TrackStatusFactory $trackStatusFactory + * @param RegionFactory $regionFactory + * @param CountryFactory $countryFactory + * @param CurrencyFactory $currencyFactory + * @param Data $directoryData + * @param StockRegistryInterface $stockRegistry + * @param FormatInterface $localeFormat * @param Config $configHelper * @param ClientFactory $httpClientFactory * @param array $data @@ -175,27 +195,27 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory, - \Psr\Log\LoggerInterface $logger, + ScopeConfigInterface $scopeConfig, + RateErrorFactory $rateErrorFactory, + LoggerInterface $logger, Security $xmlSecurity, - \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory, - \Magento\Shipping\Model\Rate\ResultFactory $rateFactory, - \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory, - \Magento\Shipping\Model\Tracking\ResultFactory $trackFactory, - \Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory, - \Magento\Shipping\Model\Tracking\Result\StatusFactory $trackStatusFactory, - \Magento\Directory\Model\RegionFactory $regionFactory, - \Magento\Directory\Model\CountryFactory $countryFactory, - \Magento\Directory\Model\CurrencyFactory $currencyFactory, - \Magento\Directory\Helper\Data $directoryData, - \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, - \Magento\Framework\Locale\FormatInterface $localeFormat, + ElementFactory $xmlElFactory, + RateFactory $rateFactory, + RateMethodFactory $rateMethodFactory, + TrackFactory $trackFactory, + TrackErrorFactory $trackErrorFactory, + TrackStatusFactory $trackStatusFactory, + RegionFactory $regionFactory, + CountryFactory $countryFactory, + CurrencyFactory $currencyFactory, + Data $directoryData, + StockRegistryInterface $stockRegistry, + FormatInterface $localeFormat, Config $configHelper, ClientFactory $httpClientFactory, array $data = [], ?AsyncClientInterface $asyncHttpClient = null, - ?ProxyDeferredFactory $proxyDeferredFactory + ?ProxyDeferredFactory $proxyDeferredFactory = null ) { parent::__construct( $scopeConfig, @@ -265,7 +285,7 @@ public function setRequest(RateRequest $request) { $this->_request = $request; - $rowRequest = new \Magento\Framework\DataObject(); + $rowRequest = new DataObject(); if ($request->getLimitMethod()) { $rowRequest->setAction($this->configHelper->getCode('action', 'single')); @@ -300,8 +320,8 @@ public function setRequest(RateRequest $request) $origCountry = $request->getOrigCountry(); } else { $origCountry = $this->_scopeConfig->getValue( - \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + OrderShipment::XML_PATH_STORE_COUNTRY_ID, + ScopeInterface::SCOPE_STORE, $request->getStoreId() ); } @@ -312,8 +332,8 @@ public function setRequest(RateRequest $request) $origRegionCode = $request->getOrigRegionCode(); } else { $origRegionCode = $this->_scopeConfig->getValue( - \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_REGION_ID, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + OrderShipment::XML_PATH_STORE_REGION_ID, + ScopeInterface::SCOPE_STORE, $request->getStoreId() ); } @@ -327,8 +347,8 @@ public function setRequest(RateRequest $request) } else { $rowRequest->setOrigPostal( $this->_scopeConfig->getValue( - \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + OrderShipment::XML_PATH_STORE_ZIP, + ScopeInterface::SCOPE_STORE, $request->getStoreId() ) ); @@ -339,8 +359,8 @@ public function setRequest(RateRequest $request) } else { $rowRequest->setOrigCity( $this->_scopeConfig->getValue( - \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_CITY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + OrderShipment::XML_PATH_STORE_CITY, + ScopeInterface::SCOPE_STORE, $request->getStoreId() ) ); @@ -516,7 +536,7 @@ protected function _getCgiQuotes() if (!$url) { $url = $this->_defaultCgiGatewayUrl; } - $client = new \Zend_Http_Client(); + $client = new Zend_Http_Client(); $client->setUri($url); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setParameterGet($params); @@ -525,7 +545,7 @@ protected function _getCgiQuotes() $debugData['result'] = $responseBody; $this->_setCachedQuotes($params, $responseBody); - } catch (\Throwable $e) { + } catch (Throwable $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; $responseBody = ''; } @@ -727,7 +747,7 @@ protected function _getXmlQuotes() {$shipperStateProvince} - +
{$params['19_destPostal']} @@ -743,7 +763,7 @@ protected function _getXmlQuotes() $xmlParams .= << - +
{$params['15_origPostal']} @@ -1056,7 +1076,7 @@ protected function setXMLAccessRequest() * Get cgi tracking * * @param string[] $trackings - * @return \Magento\Shipping\Model\Tracking\ResultFactory + * @return TrackFactory */ protected function _getCgiTracking($trackings) { @@ -1321,13 +1341,13 @@ public function getAllowedMethods() /** * Form XML for shipment request * - * @param \Magento\Framework\DataObject $request + * @param DataObject $request * @return string * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - protected function _formShipmentRequest(\Magento\Framework\DataObject $request) + protected function _formShipmentRequest(DataObject $request) { $packageParams = $request->getPackageParams(); $height = $packageParams->getHeight(); @@ -1339,7 +1359,7 @@ protected function _formShipmentRequest(\Magento\Framework\DataObject $request) $itemsDesc = []; $itemsShipment = $request->getPackageItems(); foreach ($itemsShipment as $itemShipment) { - $item = new \Magento\Framework\DataObject(); + $item = new DataObject(); $item->setData($itemShipment); $itemsDesc[] = $item->getName(); } @@ -1533,7 +1553,7 @@ protected function _formShipmentRequest(\Magento\Framework\DataObject $request) * Send and process shipment accept request * * @param Element $shipmentConfirmResponse - * @return \Magento\Framework\DataObject + * @return DataObject * @deprecated New asynchronous methods introduced. * @see requestToShipment */ @@ -1559,18 +1579,18 @@ protected function _sendShipmentAcceptRequest(Element $shipmentConfirmResponse) $xmlResponse = $deferredResponse->get()->getBody(); $debugData['result'] = $xmlResponse; $this->_setCachedQuotes($xmlRequest, $xmlResponse); - } catch (\Throwable $e) { + } catch (Throwable $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; $xmlResponse = ''; } try { $response = $this->_xmlElFactory->create(['data' => $xmlResponse]); - } catch (\Throwable $e) { + } catch (Throwable $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; } - $result = new \Magento\Framework\DataObject(); + $result = new DataObject(); if (isset($response->Error)) { $result->setErrors((string)$response->Error->ErrorDescription); } else { @@ -1609,7 +1629,7 @@ public function getShipAcceptUrl() * @param DataObject[] $packages * @return string[] Quote IDs. * @throws LocalizedException - * @throws \RuntimeException + * @throws RuntimeException */ private function requestQuotes(array $packages): array { @@ -1640,13 +1660,13 @@ private function requestQuotes(array $packages): array try { /** @var Element $response */ $response = $this->_xmlElFactory->create(['data' => $httpResponse->getBody()]); - } catch (\Throwable $e) { - throw new \RuntimeException($e->getMessage()); + } catch (Throwable $e) { + throw new RuntimeException($e->getMessage()); } if (isset($response->Response->Error) && in_array($response->Response->Error->ErrorSeverity, ['Hard', 'Transient']) ) { - throw new \RuntimeException((string)$response->Response->Error->ErrorDescription); + throw new RuntimeException((string)$response->Response->Error->ErrorDescription); } $ids[] = $response->ShipmentDigest; @@ -1661,7 +1681,7 @@ private function requestQuotes(array $packages): array * @param string[] $quoteIds * @return DataObject[] * @throws LocalizedException - * @throws \RuntimeException + * @throws RuntimeException */ private function requestShipments(array $quoteIds): array { @@ -1697,11 +1717,11 @@ private function requestShipments(array $quoteIds): array try { /** @var Element $response */ $response = $this->_xmlElFactory->create(['data' => $httpResponse->getBody()]); - } catch (\Throwable $e) { - throw new \RuntimeException($e->getMessage()); + } catch (Throwable $e) { + throw new RuntimeException($e->getMessage()); } if (isset($response->Error)) { - throw new \RuntimeException((string)$response->Error->ErrorDescription); + throw new RuntimeException((string)$response->Error->ErrorDescription); } else { $shippingLabelContent = (string)$response->ShipmentResults->PackageResults->LabelImage->GraphicImage; $trackingNumber = (string)$response->ShipmentResults->PackageResults->TrackingNumber; @@ -1726,7 +1746,7 @@ private function requestShipments(array $quoteIds): array protected function _doShipmentRequest(DataObject $request) { $this->_prepareShipmentRequest($request); - $result = new \Magento\Framework\DataObject(); + $result = new DataObject(); $rawXmlRequest = $this->_formShipmentRequest($request); $this->setXMLAccessRequest(); $xmlRequest = $this->_xmlAccessRequest . $rawXmlRequest; @@ -1747,14 +1767,14 @@ protected function _doShipmentRequest(DataObject $request) $xmlResponse = $deferredResponse->get()->getBody(); $debugData['result'] = $xmlResponse; $this->_setCachedQuotes($xmlRequest, $xmlResponse); - } catch (\Throwable $e) { + } catch (Throwable $e) { $debugData['result'] = ['code' => $e->getCode(), 'error' => $e->getMessage()]; } } try { $response = $this->_xmlElFactory->create(['data' => $xmlResponse]); - } catch (\Throwable $e) { + } catch (Throwable $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; $result->setErrors($e->getMessage()); } @@ -1827,7 +1847,7 @@ public function requestToShipment($request) $labels = $this->requestShipments($quoteIds); } catch (LocalizedException $exception) { return new DataObject(['errors' => [$exception->getMessage()]]); - } catch (\RuntimeException $exception) { + } catch (RuntimeException $exception) { return new DataObject(['errors' => __('Failed to send items')]); } // phpcs:enable @@ -1848,11 +1868,11 @@ public function returnOfShipment($request) /** * Return container types of carrier * - * @param \Magento\Framework\DataObject|null $params + * @param DataObject|null $params * @return array|bool * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function getContainerTypes(\Magento\Framework\DataObject $params = null) + public function getContainerTypes(DataObject $params = null) { if ($params === null) { return $this->_getAllowedContainers($params); @@ -1932,10 +1952,10 @@ public function getContainerTypesFilter() /** * Return delivery confirmation types of carrier * - * @param \Magento\Framework\DataObject|null $params + * @param DataObject|null $params * @return array|bool */ - public function getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params = null) + public function getDeliveryConfirmationTypes(DataObject $params = null) { $countryRecipient = $params != null ? $params->getCountryRecipient() : null; $deliveryConfirmationTypes = []; diff --git a/app/code/Magento/Wishlist/Controller/Index/Send.php b/app/code/Magento/Wishlist/Controller/Index/Send.php index 54aa53d829db5..283400a6f94ea 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Send.php +++ b/app/code/Magento/Wishlist/Controller/Index/Send.php @@ -25,9 +25,8 @@ use Magento\Customer\Model\Customer; /** - * Class Send + * Class Send Email Wishlist Controller * - * @package Magento\Wishlist\Controller\Index * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Send extends \Magento\Wishlist\Controller\AbstractIndex implements Action\HttpPostActionInterface @@ -204,7 +203,7 @@ public function execute() $error = __('Please enter an email address.'); } else { if (count($emails) > $emailsLeft) { - $error = __('This wish list can be shared %1 more times.', $emailsLeft); + $error = __('Maximum of %1 emails can be sent.', $emailsLeft); } else { foreach ($emails as $index => $email) { $email = trim($email); @@ -319,7 +318,6 @@ protected function addLayoutHandles(ResultLayout $resultLayout) * * @param int $wishlistId * @param \Magento\Framework\View\Result\Layout $resultLayout - * @return mixed */ protected function getRssLink($wishlistId, ResultLayout $resultLayout) { diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php index 47148f7878134..c70c2a1a6a9b6 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php @@ -5,7 +5,10 @@ */ namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Captcha\Helper\Data as CaptchaHelper; +use Magento\Captcha\Model\DefaultModel as CaptchaModel; use Magento\Customer\Model\Data\Customer as CustomerData; +use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context as ActionContext; use Magento\Framework\App\RequestInterface; use Magento\Framework\Controller\Result\Redirect as ResultRedirect; @@ -14,15 +17,13 @@ use Magento\Framework\Event\ManagerInterface as EventManagerInterface; use Magento\Framework\Mail\TransportInterface; use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Phrase; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\UrlInterface; use Magento\Framework\View\Result\Layout as ResultLayout; use Magento\Store\Model\Store; use Magento\Wishlist\Controller\Index\Send; use Magento\Wishlist\Controller\WishlistProviderInterface; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Captcha\Helper\Data as CaptchaHelper; -use Magento\Captcha\Model\DefaultModel as CaptchaModel; -use Magento\Customer\Model\Session; /** * @SuppressWarnings(PHPMD.TooManyFields) @@ -212,7 +213,12 @@ protected function setUp() ); } - public function testExecuteNoFormKeyValidated() + /** + * Verify execute method without Form Key validated + * + * @return void + */ + public function testExecuteNoFormKeyValidated(): void { $this->formKeyValidator->expects($this->once()) ->method('validate') @@ -228,8 +234,43 @@ public function testExecuteNoFormKeyValidated() } /** - * @expectedException \Magento\Framework\Exception\NotFoundException - * @expectedExceptionMessage Page not found. + * Verify execute with no emails left + * + * @return void + */ + public function testExecuteWithNoEmailLeft(): void + { + $expectedMessage = new Phrase('Maximum of %1 emails can be sent.', [0]); + + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->request->expects($this->at(0)) + ->method('getPost') + ->with('emails') + ->willReturn('some.Email@gmail.com', 'some.email2@gmail.com'); + $this->request->expects($this->at(1)) + ->method('getPost') + ->with('message'); + $wishlist = $this->createMock(\Magento\Wishlist\Model\Wishlist::class); + $this->wishlistProvider->expects($this->once()) + ->method('getWishlist') + ->willReturn($wishlist); + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/share') + ->willReturnSelf(); + $this->messageManager->expects($this->once()) + ->method('addErrorMessage') + ->with($expectedMessage); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + /** + * Execute method with no wishlist available */ public function testExecuteNoWishlistAvailable() { @@ -241,6 +282,8 @@ public function testExecuteNoWishlistAvailable() $this->wishlistProvider->expects($this->once()) ->method('getWishlist') ->willReturn(null); + $this->expectException(\Magento\Framework\Exception\NotFoundException::class); + $this->expectExceptionMessage('Page not found'); $this->model->execute(); } diff --git a/app/design/frontend/Magento/luma/Magento_Newsletter/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Newsletter/web/css/source/_module.less index 5d44a32b9391b..a72f31d72ce48 100644 --- a/app/design/frontend/Magento/luma/Magento_Newsletter/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Newsletter/web/css/source/_module.less @@ -81,6 +81,13 @@ .block.newsletter { max-width: 44%; width: max-content; + + .form.subscribe { + > .field, + > .actions { + float: left; + } + } } } diff --git a/app/etc/di.xml b/app/etc/di.xml index dfbf4f2373ac5..308ec1ef4d6ed 100644 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -1453,6 +1453,7 @@ \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Primary \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Foreign \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Index + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Json @@ -1480,6 +1481,7 @@ \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Json \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Index \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\Internal \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\Internal @@ -1593,6 +1595,7 @@ Magento\Framework\Setup\SchemaListenerDefinition\TimestampDefinition Magento\Framework\Setup\SchemaListenerDefinition\DateDefinition Magento\Framework\Setup\SchemaListenerDefinition\BooleanDefinition + Magento\Framework\Setup\SchemaListenerDefinition\JsonDefinition diff --git a/dev/tests/integration/testsuite/Magento/Payment/Model/PaymentInfoTest.php b/dev/tests/integration/testsuite/Magento/Payment/Model/PaymentInfoTest.php new file mode 100644 index 0000000000000..3d037ceb17044 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Payment/Model/PaymentInfoTest.php @@ -0,0 +1,63 @@ +_objectManager = Bootstrap::getObjectManager(); + $this->_order = $this->_objectManager->create( + Order::class + ); + $this->_quote = $this->_objectManager->create( + Quote::class + ); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Payment/_files/payment_info.php + */ + public function testUnsetPaymentInformation() + { + $order = $this->_order->loadByIncrementId('100000001'); + /** @var \Magento\Sales\Model\Order\Payment $paymentOrder */ + $paymentOrder = $order->getPayment(); + $paymentOrder->unsAdditionalInformation('testing'); + + $quote = $this->_quote->load('reserved_order_id', 'reserved_order_id'); + /** @var \Magento\Quote\Model\Quote\Payment $paymentQuote */ + $paymentQuote = $quote->getPayment(); + $paymentQuote->unsAdditionalInformation('testing'); + + $this->assertFalse($paymentOrder->hasAdditionalInformation('testing')); + $this->assertFalse($paymentQuote->hasAdditionalInformation('testing')); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Payment/_files/payment_info.php b/dev/tests/integration/testsuite/Magento/Payment/_files/payment_info.php new file mode 100644 index 0000000000000..bf40cb6b99820 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Payment/_files/payment_info.php @@ -0,0 +1,83 @@ + 'guest', + 'lastname' => 'guest', + 'email' => 'customer@example.com', + 'street' => 'street', + 'city' => 'Los Angeles', + 'region' => 'CA', + 'postcode' => '1', + 'country_id' => 'US', + 'telephone' => '1' +]; +$billingAddress = $objectManager->create( + Address::class, + ['data' => $addressData] +); +$billingAddress->setAddressType('billing'); +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +/** @var Payment $paymentOrder */ +$paymentOrder = $objectManager->create( + Payment::class +); + +$paymentOrder->setMethod(Config::METHOD_WPP_EXPRESS); +$paymentOrder->setAdditionalInformation('testing', 'testing additional data'); + +$amount = 100; + +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setCustomerEmail('co@co.co') + ->setIncrementId('100000001') + ->setSubtotal($amount) + ->setBaseSubtotal($amount) + ->setBaseGrandTotal($amount) + ->setGrandTotal($amount) + ->setBaseCurrencyCode('USD') + ->setCustomerIsGuest(true) + ->setStoreId(1) + ->setEmailSent(true) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setPayment($paymentOrder); +$order->save(); + + + +/** @var Quote $quote */ +$quote = $objectManager->create(Quote::class); +$quote->setStoreId(1) + ->setIsActive(true) + ->setIsMultiShipping(false) + ->setReservedOrderId('reserved_order_id'); + +$quote->getPayment() + ->setMethod(Config::METHOD_WPP_EXPRESS) + ->setAdditionalInformation('testing', 'testing additional data'); + +$quote->collectTotals(); + + +/** @var CartRepositoryInterface $repository */ +$repository = $objectManager->get(CartRepositoryInterface::class); +$repository->save($quote); diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/Definition/Columns/Json.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/Definition/Columns/Json.php new file mode 100644 index 0000000000000..b25b70674e0d0 --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/Definition/Columns/Json.php @@ -0,0 +1,74 @@ +nullable = $nullable; + $this->resourceConnection = $resourceConnection; + $this->comment = $comment; + } + + /** + * @inheritdoc + */ + public function toDefinition(ElementInterface $column) + { + return sprintf( + '%s %s %s %s', + $this->resourceConnection->getConnection()->quoteIdentifier($column->getName()), + $column->getType(), + $this->nullable->toDefinition($column), + $this->comment->toDefinition($column) + ); + } + + /** + * Returns an array of column definitions + * + * @param array $data + * @return array + */ + public function fromDefinition(array $data) + { + return $data; + } +} diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Columns/Json.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Columns/Json.php new file mode 100644 index 0000000000000..0f1e785730d38 --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Columns/Json.php @@ -0,0 +1,69 @@ +nullable = $nullable; + } + + /** + * Check whether column can be nullable. + * + * @return bool + */ + public function isNullable() + { + return $this->nullable; + } + + /** + * @inheritdoc + */ + public function getDiffSensitiveParams() + { + return [ + 'type' => $this->getType(), + 'nullable' => $this->isNullable(), + 'comment' => $this->getComment() + ]; + } +} diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Factories/Json.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Factories/Json.php new file mode 100644 index 0000000000000..5c9c88bb4fe26 --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Factories/Json.php @@ -0,0 +1,52 @@ +objectManager = $objectManager; + $this->className = $className; + } + + /** + * Create element using definition data array. + * + * @param array $data + * @return \Magento\Framework\Setup\Declaration\Schema\Dto\ElementInterface|mixed + */ + public function create(array $data) + { + return $this->objectManager->create($this->className, $data); + } +} diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd index e3c54413f810b..bb9136d8a9ae6 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd @@ -20,6 +20,7 @@ + diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/types/texts/json.xsd b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/types/texts/json.xsd new file mode 100644 index 0000000000000..690f84a5ef43f --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/types/texts/json.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + Well formatted Json object + + + + + + + diff --git a/lib/internal/Magento/Framework/Setup/SchemaListenerDefinition/JsonDefinition.php b/lib/internal/Magento/Framework/Setup/SchemaListenerDefinition/JsonDefinition.php new file mode 100644 index 0000000000000..04866dde943f4 --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/SchemaListenerDefinition/JsonDefinition.php @@ -0,0 +1,25 @@ + $definition['type'], + 'name' => $definition['name'], + 'nullable' => $definition['nullable'] ?? true + ]; + } +}