diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml index e33151feff889..b9d601238ac73 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml @@ -16,6 +16,9 @@ + + + @@ -148,7 +151,7 @@ - + diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/Address/SaveQuoteAddressToCustomerAddressBook.php b/app/code/Magento/QuoteGraphQl/Model/Cart/Address/SaveQuoteAddressToCustomerAddressBook.php index 5c773d44e6a1d..c87101156327e 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/Address/SaveQuoteAddressToCustomerAddressBook.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/Address/SaveQuoteAddressToCustomerAddressBook.php @@ -12,6 +12,7 @@ use Magento\Customer\Api\Data\AddressInterfaceFactory; use Magento\Customer\Api\Data\RegionInterface; use Magento\Customer\Api\Data\RegionInterfaceFactory; +use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Quote\Model\Quote\Address as QuoteAddress; @@ -89,8 +90,15 @@ public function execute(QuoteAddress $quoteAddress, int $customerId): void $customerAddress->setRegion($region); $this->addressRepository->save($customerAddress); - } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage()), $e); + } catch (InputException $inputException) { + $graphQlInputException = new GraphQlInputException(__($inputException->getMessage())); + $errors = $inputException->getErrors(); + foreach ($errors as $error) { + $graphQlInputException->addError(new GraphQlInputException(__($error->getMessage()))); + } + throw $graphQlInputException; + } catch (LocalizedException $exception) { + throw new GraphQlInputException(__($exception->getMessage()), $exception); } } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php index afc88f026ed62..9cb3d9173ac59 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -15,6 +15,9 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Quote\Model\Quote\Address as QuoteAddress; use Magento\Quote\Model\Quote\AddressFactory as BaseQuoteAddressFactory; +use Magento\Directory\Model\ResourceModel\Region\CollectionFactory as RegionCollectionFactory; +use Magento\Directory\Helper\Data as CountryHelper; +use Magento\Directory\Model\AllowedCountries; /** * Create QuoteAddress @@ -36,36 +39,77 @@ class QuoteAddressFactory */ private $addressHelper; + /** + * @var RegionCollectionFactory + */ + private $regionCollectionFactory; + + /** + * @var CountryHelper + */ + private $countryHelper; + + /** + * @var AllowedCountries + */ + private $allowedCountries; + /** * @param BaseQuoteAddressFactory $quoteAddressFactory * @param GetCustomerAddress $getCustomerAddress * @param AddressHelper $addressHelper + * @param RegionCollectionFactory $regionCollectionFactory + * @param CountryHelper $countryHelper + * @param AllowedCountries $allowedCountries */ public function __construct( BaseQuoteAddressFactory $quoteAddressFactory, GetCustomerAddress $getCustomerAddress, - AddressHelper $addressHelper + AddressHelper $addressHelper, + RegionCollectionFactory $regionCollectionFactory, + CountryHelper $countryHelper, + AllowedCountries $allowedCountries ) { $this->quoteAddressFactory = $quoteAddressFactory; $this->getCustomerAddress = $getCustomerAddress; $this->addressHelper = $addressHelper; + $this->regionCollectionFactory = $regionCollectionFactory; + $this->countryHelper = $countryHelper; + $this->allowedCountries = $allowedCountries; } /** * Create QuoteAddress based on input data * * @param array $addressInput + * * @return QuoteAddress * @throws GraphQlInputException */ public function createBasedOnInputData(array $addressInput): QuoteAddress { $addressInput['country_id'] = ''; - if ($addressInput['country_code']) { + if (isset($addressInput['country_code']) && $addressInput['country_code']) { $addressInput['country_code'] = strtoupper($addressInput['country_code']); $addressInput['country_id'] = $addressInput['country_code']; } + $allowedCountries = $this->allowedCountries->getAllowedCountries(); + if (!in_array($addressInput['country_code'], $allowedCountries, true)) { + throw new GraphQlInputException(__('Country is not available')); + } + $isRegionRequired = $this->countryHelper->isRegionRequired($addressInput['country_code']); + if ($isRegionRequired && !empty($addressInput['region'])) { + $regionCollection = $this->regionCollectionFactory + ->create() + ->addRegionCodeFilter($addressInput['region']) + ->addCountryFilter($addressInput['country_code']); + if ($regionCollection->getSize() === 0) { + throw new GraphQlInputException( + __('Region is not available for the selected country') + ); + } + } $maxAllowedLineCount = $this->addressHelper->getStreetLines(); if (is_array($addressInput['street']) && count($addressInput['street']) > $maxAllowedLineCount) { throw new GraphQlInputException( diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 7c8126194777f..20a3677ef1feb 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -132,6 +132,15 @@ private function createBillingAddress( (int)$context->getUserId() ); } + $errors = $billingAddress->validate(); + + if (true !== $errors) { + $e = new GraphQlInputException(__('Billing address errors')); + foreach ($errors as $error) { + $e->addError(new GraphQlInputException($error)); + } + throw $e; + } return $billingAddress; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php index 6b1296eaf3752..e058913dde1d3 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php @@ -10,6 +10,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Model\Query\ContextInterface; use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Model\Quote\Address; /** * Set single shipping address for a specified shopping cart @@ -52,6 +53,15 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s $shippingAddress = $this->getShippingAddress->execute($context, $shippingAddressInput); + $errors = $shippingAddress->validate(); + + if (true !== $errors) { + $e = new GraphQlInputException(__('Shipping address errors')); + foreach ($errors as $error) { + $e->addError(new GraphQlInputException($error)); + } + throw $e; + } $this->assignShippingAddressToCart->execute($cart, $shippingAddress); } } diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml index 9c57ecf70ebc0..80697fd57736a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml @@ -39,6 +39,12 @@ + + + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml index 248219951a251..85567374e36e4 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml @@ -39,6 +39,12 @@ + + + + + + diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index d2164a6dcc65f..40131e2d76575 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -96,7 +96,7 @@ public function testSetNewBillingAddress() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -174,7 +174,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -370,7 +370,7 @@ public function testSetNewBillingAddressAndFromAddressBookAtSameTime() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -451,7 +451,7 @@ public function testSetNewBillingAddressWithSameAsShippingAndMultishipping() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -644,7 +644,7 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st QUERY; $this->expectExceptionMessage($message); - $this->graphQlMutation($query); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -661,7 +661,55 @@ public function dataProviderSetWithoutRequiredParameters(): array 'missed_cart_id' => [ 'billing_address: {}', 'Required parameter "cart_id" is missing' - ] + ], + 'missed_region' => [ + 'cart_id: "cart_id_value" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + country_code: "US" + telephone: "88776655" + } + }', + '"regionId" is required. Enter and try again.' + ], + 'missed_multiple_fields' => [ + 'cart_id: "cart_id_value" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + country_code: "US" + telephone: "88776655" + } + }', + '"postcode" is required. Enter and try again. +"regionId" is required. Enter and try again.' + ], + 'wrong_required_region' => [ + 'cart_id: "cart_id_value" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + region: "wrong region" + city: "test city" + country_code: "US" + telephone: "88776655" + } + }', + 'Region is not available for the selected country' + ], ]; } @@ -687,7 +735,7 @@ public function testSetNewBillingAddressWithRedundantStreetLine() company: "test company" street: ["test street 1", "test street 2", "test street 3"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -729,7 +777,7 @@ public function testSetBillingAddressWithLowerCaseCountry() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "us" telephone: "88776655" @@ -786,7 +834,7 @@ public function testSetNewBillingAddressWithSaveInAddressBook() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -853,7 +901,7 @@ public function testSetNewBillingAddressWithNotSaveInAddressBook() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -921,7 +969,7 @@ public function testWithInvalidBillingAddressInput() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "USS" telephone: "88776655" @@ -948,10 +996,59 @@ public function testWithInvalidBillingAddressInput() } } QUERY; - $this->expectExceptionMessage('The address failed to save. Verify the address and try again.'); + $this->expectExceptionMessage('Country is not available'); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetShippingAddressesWithNotRequiredRegion() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<graphQlMutation($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); + $cartResponse = $response['setBillingAddressOnCart']['cart']; + self::assertEquals('UA', $cartResponse['billing_address']['country']['code']); + self::assertEquals('Lviv', $cartResponse['billing_address']['region']['label']); + } + /** * Verify the all the whitelisted fields for a New Address Object * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index dbdfb816be010..8d9388c064226 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -99,7 +99,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -164,7 +164,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -328,7 +328,7 @@ public function testSetNewShippingAddressAndFromAddressBookAtSameTime() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -523,11 +523,59 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_city' => [ 'shipping_addresses: [ { address: { save_in_address_book: false } } ]', - 'Field CartAddressInput.city of required type String! was not provided', + 'Field CartAddressInput.city of required type String! was not provided' ], 'missed_cart_id' => [ 'shipping_addresses: {}', - 'Required parameter "cart_id" is missing', + 'Required parameter "cart_id" is missing' + ], + 'missed_region' => [ + 'cart_id: "cart_id_value" + shipping_addresses: [{ + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + country_code: "US" + telephone: "88776655" + } + }]', + '"regionId" is required. Enter and try again.' + ], + 'missed_multiple_fields' => [ + 'cart_id: "cart_id_value" + shipping_addresses: [{ + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + country_code: "US" + telephone: "88776655" + } + }]', + '"postcode" is required. Enter and try again. +"regionId" is required. Enter and try again.' + ], + 'wrong_required_region' => [ + 'cart_id: "cart_id_value" + shipping_addresses: [{ + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + region: "wrong region" + city: "test city" + country_code: "US" + telephone: "88776655" + } + }]', + 'Region is not available for the selected country' ], ]; } @@ -558,7 +606,7 @@ public function testSetMultipleNewShippingAddresses() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -571,7 +619,7 @@ public function testSetMultipleNewShippingAddresses() company: "test company 2" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -614,7 +662,7 @@ public function testSetNewShippingAddressOnCartWithRedundantStreetLine() company: "test company" street: ["test street 1", "test street 2", "test street 3"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -797,10 +845,61 @@ public function testWithInvalidShippingAddressesInput() } } QUERY; - $this->expectExceptionMessage('The address failed to save. Verify the address and try again.'); + $this->expectExceptionMessage('Country is not available'); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetShippingAddressesWithNotRequiredRegion() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<graphQlMutation($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + $cartResponse = $response['setShippingAddressesOnCart']['cart']; + self::assertEquals('UA', $cartResponse['shipping_addresses'][0]['country']['code']); + self::assertEquals('Lviv', $cartResponse['shipping_addresses'][0]['region']['label']); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php @@ -823,7 +922,7 @@ public function testSetNewShippingAddressWithSaveInAddressBook() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -894,7 +993,7 @@ public function testSetNewShippingAddressWithNotSaveInAddressBook() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AllowGuestCheckoutOptionTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AllowGuestCheckoutOptionTest.php index 90ebec763b227..60c3cc2e8b24e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AllowGuestCheckoutOptionTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AllowGuestCheckoutOptionTest.php @@ -104,7 +104,7 @@ public function testSetBillingAddressToGuestCustomerCart() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" @@ -216,7 +216,7 @@ public function testSetNewShippingAddressOnCartWithGuestCheckoutDisabled() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AZ" postcode: "887766" country_code: "US" telephone: "88776655" diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index 92822c6ce2056..5f9f44084c8a9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -48,7 +48,7 @@ public function testSetNewBillingAddress() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -126,7 +126,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -201,7 +201,7 @@ public function testSetBillingAddressToCustomerCart() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -277,7 +277,7 @@ public function testSetBillingAddressOnNonExistentCart() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -404,7 +404,7 @@ public function testSetNewBillingAddressWithSameAsShippingAndMultishipping() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -449,7 +449,7 @@ public function testSetNewBillingAddressRedundantStreetLine() company: "test company" street: ["test street 1", "test street 2", "test street 3"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -491,7 +491,7 @@ public function testSetBillingAddressWithLowerCaseCountry() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "us" telephone: "88776655" diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index 2e98773ad9187..0b2e67c5650c0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -49,7 +49,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -113,7 +113,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -264,7 +264,7 @@ public function testSetNewShippingAddressOnCartWithRedundantStreetLine() company: "test company" street: ["test street 1", "test street 2", "test street 3"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -332,7 +332,7 @@ public function testSetMultipleNewShippingAddresses() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -345,7 +345,7 @@ public function testSetMultipleNewShippingAddresses() company: "test company 2" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" @@ -384,7 +384,7 @@ public function testSetShippingAddressOnNonExistentCart() company: "test company" street: ["test street 1", "test street 2"] city: "test city" - region: "test region" + region: "AL" postcode: "887766" country_code: "US" telephone: "88776655" diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/LinksTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/LinksTest.php index cc8d87ece656a..665d45921d435 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/LinksTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/LinksTest.php @@ -79,6 +79,7 @@ private function getPostData(): array 'name' => 'Simple Product', 'sku' => 'simple', 'url_key' => 'simple-product', + 'type_id' => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE ], 'links' => [ 'upsell' => [ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php index 00bfe70eef385..7ca04863f58a1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php @@ -432,6 +432,7 @@ public function testSaveDesign(): void 'store' => '0', 'set' => '4', 'back' => 'edit', + 'type_id' => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, 'product' => [], 'is_downloadable' => '0', 'affect_configurable_product_attributes' => '1', @@ -493,6 +494,7 @@ public function testSaveDesignWithDefaults(): void 'set' => '4', 'back' => 'edit', 'product' => [], + 'type_id' => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, 'is_downloadable' => '0', 'affect_configurable_product_attributes' => '1', 'new_variation_attribute_set_id' => '4', diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 6bdb74ef7b89a..775611c63a9f7 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -21,6 +21,7 @@ class ConfigOptionsListConstants const CONFIG_PATH_CRYPT_KEY = 'crypt/key'; const CONFIG_PATH_SESSION_SAVE = 'session/save'; const CONFIG_PATH_RESOURCE_DEFAULT_SETUP = 'resource/default_setup/connection'; + const CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS = 'db/connection/default/driver_options'; const CONFIG_PATH_DB_CONNECTION_DEFAULT = 'db/connection/default'; const CONFIG_PATH_DB_CONNECTIONS = 'db/connection'; const CONFIG_PATH_DB_PREFIX = 'db/table_prefix'; @@ -64,6 +65,10 @@ class ConfigOptionsListConstants const INPUT_KEY_DB_MODEL = 'db-model'; const INPUT_KEY_DB_INIT_STATEMENTS = 'db-init-statements'; const INPUT_KEY_DB_ENGINE = 'db-engine'; + const INPUT_KEY_DB_SSL_KEY = 'db-ssl-key'; + const INPUT_KEY_DB_SSL_CERT = 'db-ssl-cert'; + const INPUT_KEY_DB_SSL_CA = 'db-ssl-ca'; + const INPUT_KEY_DB_SSL_VERIFY = 'db-ssl-verify'; const INPUT_KEY_RESOURCE = 'resource'; const INPUT_KEY_SKIP_DB_VALIDATION = 'skip-db-validation'; const INPUT_KEY_CACHE_HOSTS = 'http-cache-hosts'; @@ -75,7 +80,11 @@ class ConfigOptionsListConstants const KEY_CACHE_FRONTEND = 'cache/frontend'; const CONFIG_PATH_BACKEND_OPTIONS = 'backend_options'; - /** @deprecated */ + /** + * @deprecated + * + * Definition format constant. + */ const INPUT_KEY_DEFINITION_FORMAT = 'definition-format'; /**#@+ @@ -104,6 +113,21 @@ class ConfigOptionsListConstants const KEY_MODEL = 'model'; const KEY_INIT_STATEMENTS = 'initStatements'; const KEY_ACTIVE = 'active'; + const KEY_DRIVER_OPTIONS = 'driver_options'; + /**#@-*/ + + /**#@+ + * Array keys for database driver options configurations + */ + const KEY_MYSQL_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY; + const KEY_MYSQL_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT; + const KEY_MYSQL_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA; + + /** + * Constant \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT cannot be used as it was introduced in PHP 7.1.4 + * and Magento 2 is currently supporting PHP 7.1.3. + */ + const KEY_MYSQL_SSL_VERIFY = 1014; /**#@-*/ /** @@ -128,6 +152,8 @@ class ConfigOptionsListConstants /** * Size of random string generated for store's encryption key + * phpcs:disable */ const STORE_KEY_RANDOM_STRING_SIZE = SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES; + //phpcs:enable } diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 723814432b7e1..7db2b26e3c621 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41730,7 +41730,7 @@ vars.putObject("randomIntGenerator", random); false - {"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} + {"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"AZ\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} = @@ -41920,7 +41920,7 @@ vars.putObject("randomIntGenerator", random); false - {"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} + {"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"AZ\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} = @@ -45369,7 +45369,7 @@ vars.put("product_sku", product.get("sku")); false - {"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} + {"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"AZ\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} = @@ -45408,7 +45408,7 @@ vars.put("product_sku", product.get("sku")); false - {"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} + {"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"AZ\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null} = diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index 4511abccaf09b..4b88a8732d2c7 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -5,6 +5,7 @@ */ namespace Magento\Setup\Controller; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Setup\Validator\DbValidator; use Zend\Json\Json; use Zend\Mvc\Controller\AbstractActionController; @@ -40,7 +41,25 @@ public function indexAction() try { $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY); $password = isset($params['password']) ? $params['password'] : ''; - $this->dbValidator->checkDatabaseConnection($params['name'], $params['host'], $params['user'], $password); + $driverOptions = []; + if ($this->isDriverOptionsGiven($params)) { + if (empty($params['driverOptionsSslVerify'])) { + $params['driverOptionsSslVerify'] = 0; + } + $driverOptions = [ + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => $params['driverOptionsSslKey'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => $params['driverOptionsSslCert'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => $params['driverOptionsSslCa'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => (int) $params['driverOptionsSslVerify'], + ]; + } + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( + $params['name'], + $params['host'], + $params['user'], + $password, + $driverOptions + ); $tablePrefix = isset($params['tablePrefix']) ? $params['tablePrefix'] : ''; $this->dbValidator->checkDatabaseTablePrefix($tablePrefix); return new JsonModel(['success' => true]); @@ -48,4 +67,19 @@ public function indexAction() return new JsonModel(['success' => false, 'error' => $e->getMessage()]); } } + + /** + * Is Driver Options Given + * + * @param array $params + * @return bool + */ + private function isDriverOptionsGiven($params) + { + return !( + empty($params['driverOptionsSslKey']) || + empty($params['driverOptionsSslCert']) || + empty($params['driverOptionsSslCa']) + ); + } } diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php index 80a20ff2e80f3..09d15489812e2 100644 --- a/setup/src/Magento/Setup/Model/ConfigGenerator.php +++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php @@ -14,11 +14,12 @@ use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\App\State; use Magento\Framework\Math\Random; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; /** * Creates deployment config data based on user input array * - * This class introduced to break down {@see Magento\Setup\Model\ConfigOptionsList::createConfig} + * This class introduced to break down {@see \Magento\Setup\Model\ConfigOptionsList::createConfig} */ class ConfigGenerator { @@ -62,6 +63,11 @@ class ConfigGenerator */ private $cryptKeyGenerator; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Constructor * @@ -69,17 +75,20 @@ class ConfigGenerator * @param DeploymentConfig $deploymentConfig * @param ConfigDataFactory|null $configDataFactory * @param CryptKeyGeneratorInterface|null $cryptKeyGenerator + * @param DriverOptions|null $driverOptions */ public function __construct( Random $random, DeploymentConfig $deploymentConfig, ConfigDataFactory $configDataFactory = null, - CryptKeyGeneratorInterface $cryptKeyGenerator = null + CryptKeyGeneratorInterface $cryptKeyGenerator = null, + DriverOptions $driverOptions = null ) { $this->random = $random; $this->deploymentConfig = $deploymentConfig; $this->configDataFactory = $configDataFactory ?? ObjectManager::getInstance()->get(ConfigDataFactory::class); $this->cryptKeyGenerator = $cryptKeyGenerator ?? ObjectManager::getInstance()->get(CryptKeyGenerator::class); + $this->driverOptions = $driverOptions ?? ObjectManager::getInstance()->get(DriverOptions::class); } /** @@ -181,6 +190,9 @@ public function createDbConfig(array $data) $configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_ACTIVE, '1'); } + $driverOptions = $this->driverOptions->getDriverOptions($data); + $configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_DRIVER_OPTIONS, $driverOptions); + return $configData; } diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php index c080b3c7fc6a1..7bc0853769217 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Setup\Model; @@ -12,6 +13,7 @@ use Magento\Framework\Setup\ConfigOptionsListInterface; use Magento\Framework\Setup\Option\FlagConfigOption; use Magento\Framework\Setup\Option\TextConfigOption; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; use Magento\Setup\Validator\DbValidator; /** @@ -53,17 +55,24 @@ class ConfigOptionsList implements ConfigOptionsListInterface \Magento\Setup\Model\ConfigOptionsList\Lock::class, ]; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Constructor * * @param ConfigGenerator $configGenerator * @param DbValidator $dbValidator * @param KeyValidator|null $encryptionKeyValidator + * @param DriverOptions|null $driverOptions */ public function __construct( ConfigGenerator $configGenerator, DbValidator $dbValidator, - KeyValidator $encryptionKeyValidator = null + KeyValidator $encryptionKeyValidator = null, + DriverOptions $driverOptions = null ) { $this->configGenerator = $configGenerator; $this->dbValidator = $dbValidator; @@ -72,6 +81,7 @@ public function __construct( $this->configOptionsCollection[] = $objectManager->get($className); } $this->encryptionKeyValidator = $encryptionKeyValidator ?: $objectManager->get(KeyValidator::class); + $this->driverOptions = $driverOptions ?? $objectManager->get(DriverOptions::class); } /** @@ -162,6 +172,36 @@ public function getOptions() ConfigOptionsListConstants::CONFIG_PATH_CACHE_HOSTS, 'http Cache hosts' ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY, + 'Full path of client key file in order to establish db connection through SSL', + '' + ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT, + 'Full path of client certificate file in order to establish db connection through SSL', + '' + ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CA, + 'Full path of server certificate file in order to establish db connection through SSL', + '' + ), + new FlagConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY, + 'Verify server certification' + ), ]; foreach ($this->configOptionsCollection as $configOptionsList) { @@ -349,12 +389,14 @@ private function validateDbSettings(array $options, DeploymentConfig $deployment ) { try { $options = $this->getDbSettings($options, $deploymentConfig); + $driverOptions = $this->driverOptions->getDriverOptions($options); - $this->dbValidator->checkDatabaseConnection( + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( $options[ConfigOptionsListConstants::INPUT_KEY_DB_NAME], $options[ConfigOptionsListConstants::INPUT_KEY_DB_HOST], $options[ConfigOptionsListConstants::INPUT_KEY_DB_USER], - $options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD] + $options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD], + $driverOptions ); } catch (\Exception $exception) { $errors[] = $exception->getMessage(); diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php new file mode 100644 index 0000000000000..1d9fdd6098cbb --- /dev/null +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -0,0 +1,51 @@ + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT, + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA, + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY + ]; + $driverOptions = []; + foreach ($driverOptionKeys as $configKey => $driverOptionKey) { + if ($this->optionExists($options, $driverOptionKey)) { + $driverOptions[$configKey] = $options[$driverOptionKey]; + } + } + return $driverOptions; + } + + /** + * Verify if option exists. + * + * @param array $options + * @param string $driverOptionKey + * @return bool + */ + private function optionExists($options, $driverOptionKey): bool + { + return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]); + } +} diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 7bbd838f557f4..23f8a13c8bfe8 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1375,7 +1375,32 @@ private function deleteDeploymentConfig() */ private function assertDbAccessible() { - $this->dbValidator->checkDatabaseConnection( + $driverOptionKeys = [ + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY + ]; + $driverOptions = []; + foreach ($driverOptionKeys as $driverOptionKey => $driverOptionConfig) { + $config = $this->deploymentConfig->get($driverOptionConfig); + if ($config !== null) { + $driverOptions[$driverOptionKey] = $config; + } + } + + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . ConfigOptionsListConstants::KEY_NAME @@ -1391,7 +1416,8 @@ private function assertDbAccessible() $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . ConfigOptionsListConstants::KEY_PASSWORD - ) + ), + $driverOptions ); $prefix = $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . diff --git a/setup/src/Magento/Setup/Model/RequestDataConverter.php b/setup/src/Magento/Setup/Model/RequestDataConverter.php index 0ed5dc669c95f..4964dbe596d85 100644 --- a/setup/src/Magento/Setup/Model/RequestDataConverter.php +++ b/setup/src/Magento/Setup/Model/RequestDataConverter.php @@ -51,6 +51,14 @@ private function convertDeploymentConfigForm(array $source) isset($source['db']['tablePrefix']) ? $source['db']['tablePrefix'] : ''; $result[BackendConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME] = isset($source['config']['address']['admin']) ? $source['config']['address']['admin'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_KEY] = isset($source['db']['driverOptionsSslKey']) + ? $source['db']['driverOptionsSslKey'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CERT] = isset($source['db']['driverOptionsSslCert']) + ? $source['db']['driverOptionsSslCert'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CA] = isset($source['db']['driverOptionsSslCa']) + ? $source['db']['driverOptionsSslCa'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_VERIFY] = isset($source['db']['driverOptionsSslVerify']) + ? $source['db']['driverOptionsSslVerify'] : ''; $result[SetupConfigOptionsList::INPUT_KEY_ENCRYPTION_KEY] = isset($source['config']['encrypt']['key']) ? $source['config']['encrypt']['key'] : null; $result[SetupConfigOptionsList::INPUT_KEY_SESSION_SAVE] = isset($source['config']['sessionSave']['type']) diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php index a388c72fc834b..63a92bd4a1982 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php @@ -11,6 +11,7 @@ use Magento\Framework\Config\Data\ConfigData; use Magento\Framework\Config\Data\ConfigDataFactory; use Magento\Setup\Model\ConfigGenerator; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; /** * Test for Magento\Setup\Model\ConfigGenerator class. @@ -32,6 +33,11 @@ class ConfigGeneratorTest extends \PHPUnit\Framework\TestCase */ private $configDataMock; + /** + * @var DriverOptions + */ + private $driverOptionsMock; + public function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -53,11 +59,17 @@ public function setUp() $configDataFactoryMock->method('create') ->willReturn($this->configDataMock); + $this->driverOptionsMock = $this->getMockBuilder(DriverOptions::class) + ->disableOriginalConstructor() + ->setMethods(['getDriverOptions']) + ->getMock(); + $this->model = $objectManager->getObject( ConfigGenerator::class, [ 'deploymentConfig' => $this->deploymentConfigMock, 'configDataFactory' => $configDataFactoryMock, + 'driverOptions' => $this->driverOptionsMock, ] ); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php index a3ade400fd363..4445fc076d49d 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php @@ -37,12 +37,29 @@ class ConfigOptionsListTest extends \PHPUnit\Framework\TestCase */ private $dbValidator; + /** + * @var \Magento\Framework\Encryption\KeyValidator|\PHPUnit_Framework_MockObject_MockObject + */ + private $encryptionKeyValidator; + + /** + * @var ConfigOptionsList\DriverOptions + */ + private $driverOptionsMock; + protected function setUp() { $this->generator = $this->createMock(\Magento\Setup\Model\ConfigGenerator::class); $this->deploymentConfig = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->dbValidator = $this->createMock(\Magento\Setup\Validator\DbValidator::class); - $this->object = new ConfigOptionsList($this->generator, $this->dbValidator); + $this->encryptionKeyValidator = $this->createMock(\Magento\Framework\Encryption\KeyValidator::class); + $this->driverOptionsMock = $this->createMock(ConfigOptionsList\DriverOptions::class); + $this->object = new ConfigOptionsList( + $this->generator, + $this->dbValidator, + $this->encryptionKeyValidator, + $this->driverOptionsMock + ); } public function testGetOptions() @@ -162,9 +179,12 @@ private function prepareValidationMocks() ->disableOriginalConstructor() ->getMock(); $this->dbValidator->expects($this->once())->method('checkDatabaseTablePrefix')->willReturn($configDataMock); + $this->dbValidator->expects($this->once()) + ->method('checkDatabaseConnectionWithDriverOptions') + ->willReturn($configDataMock); $this->dbValidator ->expects($this->once()) - ->method('checkDatabaseConnection') + ->method('checkDatabaseConnectionWithDriverOptions') ->willReturn($configDataMock); } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index d4cdee4b84bab..ea4261b271582 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -15,6 +15,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Setup\Model\CryptKeyGenerator; use PHPUnit\Framework\TestCase; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; /** * Test for Magento\Setup\Model\ConfigGenerator class. @@ -47,11 +48,17 @@ protected function setUp() $configDataFactoryMock = (new ObjectManager($this)) ->getObject(ConfigDataFactory::class, ['objectManager' => $objectManagerMock]); + $driverOptions = $this->getMockBuilder(DriverOptions::class) + ->disableOriginalConstructor() + ->setMethods(['getDriverOptions']) + ->getMock(); + $this->configGeneratorObject = new ConfigGenerator( $randomMock, $deployConfig, $configDataFactoryMock, - $cryptKeyGenerator + $cryptKeyGenerator, + $driverOptions ); } diff --git a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php index d8380bca54f7b..660c5ed893d59 100644 --- a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php +++ b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php @@ -5,6 +5,7 @@ */ namespace Magento\Setup\Validator; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Config\ConfigOptionsListConstants as ConfigOption; use Magento\Setup\Model\AdminAccount; use Magento\Setup\Model\ConfigOptionsList\DriverOptions; @@ -29,21 +30,29 @@ class AdminCredentialsValidator */ private $setupFactory; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Initialize dependencies. * * @param \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory * @param \Magento\Setup\Module\ConnectionFactory $connectionFactory * @param \Magento\Setup\Module\SetupFactory $setupFactory + * @param DriverOptions|null $driverOptions */ public function __construct( \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory, \Magento\Setup\Module\ConnectionFactory $connectionFactory, - \Magento\Setup\Module\SetupFactory $setupFactory + \Magento\Setup\Module\SetupFactory $setupFactory, + DriverOptions $driverOptions = null ) { $this->connectionFactory = $connectionFactory; $this->adminAccountFactory = $adminAccountFactory; $this->setupFactory = $setupFactory; + $this->driverOptions = $driverOptions ?? ObjectManager::getInstance()->get(DriverOptions::class); } /** @@ -55,6 +64,7 @@ public function __construct( */ public function validate(array $data) { + $driverOptions = $this->driverOptions->getDriverOptions($data); $dbConnection = $this->connectionFactory->create( [ ConfigOption::KEY_NAME => $data[ConfigOption::INPUT_KEY_DB_NAME], @@ -62,6 +72,7 @@ public function validate(array $data) ConfigOption::KEY_USER => $data[ConfigOption::INPUT_KEY_DB_USER], ConfigOption::KEY_PASSWORD => $data[ConfigOption::INPUT_KEY_DB_PASSWORD], ConfigOption::KEY_PREFIX => $data[ConfigOption::INPUT_KEY_DB_PREFIX], + ConfigOption::KEY_DRIVER_OPTIONS => $driverOptions ] ); diff --git a/setup/src/Magento/Setup/Validator/DbValidator.php b/setup/src/Magento/Setup/Validator/DbValidator.php index 075e48140e150..01ed537f887cd 100644 --- a/setup/src/Magento/Setup/Validator/DbValidator.php +++ b/setup/src/Magento/Setup/Validator/DbValidator.php @@ -78,6 +78,27 @@ public function checkDatabaseTablePrefix($prefix) */ public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '') { + return $this->checkDatabaseConnectionWithDriverOptions($dbName, $dbHost, $dbUser, $dbPass, []); + } + + /** + * Checks Database Connection with Driver Options + * + * @param string $dbName + * @param string $dbHost + * @param string $dbUser + * @param string $dbPass + * @param array $driverOptions + * @return bool + * @throws \Magento\Setup\Exception + */ + public function checkDatabaseConnectionWithDriverOptions( + $dbName, + $dbHost, + $dbUser, + $dbPass = '', + $driverOptions = [] + ) { // establish connection to information_schema view to retrieve information about user and table privileges $connection = $this->connectionFactory->create( [ @@ -86,6 +107,7 @@ public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '') ConfigOptionsListConstants::KEY_USER => $dbUser, ConfigOptionsListConstants::KEY_PASSWORD => $dbPass, ConfigOptionsListConstants::KEY_ACTIVE => true, + ConfigOptionsListConstants::KEY_DRIVER_OPTIONS => $driverOptions, ] ); diff --git a/setup/view/magento/setup/add-database.phtml b/setup/view/magento/setup/add-database.phtml index f36024c112823..5ba15cf0c1ec8 100644 --- a/setup/view/magento/setup/add-database.phtml +++ b/setup/view/magento/setup/add-database.phtml @@ -90,11 +90,96 @@ Create a database for me + */ +?> +
+
+ +
+
+ +
+
- +
+
+ +
+
+ +
+
-*/ -?> +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+