diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index e9ca9c5ca646cb0f2ad106e0b1e084eff479671d..fb988ddde594a7d26cc9f0bfeb7f649397bb60f2 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -38,7 +38,7 @@ class ProductView ); $params = []; - $params['minAllowed'] = max((float)$stockItem->getQtyMinAllowed(), 1); + $params['minAllowed'] = (float)$stockItem->getMinSaleQty(); if ($stockItem->getQtyMaxAllowed()) { $params['maxAllowed'] = $stockItem->getQtyMaxAllowed(); } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php index c0ba42d1981ca2a12f3ea6aa063854ce465461bb..267ff26bb0ccbf7d4e8b84d8a4b09c256c5123d1 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php @@ -28,7 +28,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase $this->stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Model\Stock\Item::class) ->disableOriginalConstructor() - ->setMethods(['getQtyMinAllowed', 'getQtyMaxAllowed', 'getQtyIncrements']) + ->setMethods(['getMinSaleQty', 'getQtyMaxAllowed', 'getQtyIncrements']) ->getMock(); $this->stockRegistry = $this->getMockBuilder(\Magento\CatalogInventory\Api\StockRegistryInterface::class) @@ -47,7 +47,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase $result = [ 'validate-item-quantity' => [ - 'minAllowed' => 2, + 'minAllowed' => 0.5, 'maxAllowed' => 5, 'qtyIncrements' => 3 ] @@ -73,7 +73,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase ->method('getStockItem') ->with('productId', 'websiteId') ->willReturn($this->stockItem); - $this->stockItem->expects($this->once())->method('getQtyMinAllowed')->willReturn(2); + $this->stockItem->expects($this->once())->method('getMinSaleQty')->willReturn(0.5); $this->stockItem->expects($this->any())->method('getQtyMaxAllowed')->willReturn(5); $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3); diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml index 31a5dcea3a18f8b41eff7215fbfcdd499d5d4dac..4b486cd346bde1514dccdd27f0e9ac89ed9f8de4 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml +++ b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml @@ -179,7 +179,6 @@ <item name="dataScope" xsi:type="string">min_sale_qty</item> <item name="validation" xsi:type="array"> <item name="validate-number" xsi:type="boolean">true</item> - <item name="validate-digits" xsi:type="boolean">true</item> </item> <item name="sortOrder" xsi:type="string">0</item> <item name="value" xsi:type="object">Magento\CatalogInventory\Model\Source\StockConfiguration</item> diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index 0e8df9e08f11e82ddf68896b48254fb673eacb1d..5d7cd9e51a862897e445dba02b2ad1d8957cf001 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -358,11 +358,10 @@ class Cart extends DataObject implements CartInterface if ($productId) { $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId()); $minimumQty = $stockItem->getMinSaleQty(); - //If product was not found in cart and there is set minimal qty for it + //If product quantity is not specified in request and there is set minimal qty for it if ($minimumQty && $minimumQty > 0 && !$request->getQty() - && !$this->getQuote()->hasProductId($productId) ) { $request->setQty($minimumQty); } diff --git a/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php new file mode 100644 index 0000000000000000000000000000000000000000..7c758dba4acbde030cc825059ae332f892160ef2 --- /dev/null +++ b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php @@ -0,0 +1,113 @@ +<?php +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Paypal\Model\Config\Structure; + +/** + * PayPal change structure of payment methods configuration in admin panel. + */ +class PaymentSectionModifier +{ + /** + * Identifiers of special payment method configuration groups + * + * @var array + */ + private static $specialGroups = [ + 'account', + 'recommended_solutions', + 'other_paypal_payment_solutions', + 'other_payment_methods', + ]; + + /** + * Returns changed section structure. + * + * Payment configuration has predefined special blocks: + * - Account information (id = account), + * - Recommended Solutions (id = recommended_solutions), + * - Other PayPal paymnt solution (id = other_paypal_payment_solutions), + * - Other payment methods (id = other_payment_methods). + * All payment methods configuration should be moved to one of this group. + * To move payment method to specific configuration group specify "displayIn" + * attribute in system.xml file equals to any id of predefined special group. + * If "displayIn" attribute is not specified then payment method moved to "Other payment methods" group + * + * @param array $initialStructure + * @return array + */ + public function modify(array $initialStructure) + { + $changedStructure = array_fill_keys(self::$specialGroups, []); + + foreach ($initialStructure as $childSection => $childData) { + if (in_array($childSection, self::$specialGroups)) { + if (isset($changedStructure[$childSection]['children'])) { + $children = $changedStructure[$childSection]['children']; + if (isset($childData['children'])) { + $children += $childData['children']; + } + $childData['children'] = $children; + unset($children); + } + $changedStructure[$childSection] = $childData; + } else { + $moveInstructions = $this->getMoveInstructions($childSection, $childData); + if (!empty($moveInstructions)) { + foreach ($moveInstructions as $moveInstruction) { + unset($childData['children'][$moveInstruction['section']]); + unset($moveInstruction['data']['displayIn']); + $changedStructure + [$moveInstruction['parent']] + ['children'] + [$moveInstruction['section']] = $moveInstruction['data']; + } + } + if (!isset($moveInstructions[$childSection])) { + $changedStructure['other_payment_methods']['children'][$childSection] = $childData; + } + } + } + + return $changedStructure; + } + + /** + * Recursively collect groups that should be moved to special section + * + * @param string $section + * @param array $data + * @return array + */ + private function getMoveInstructions($section, $data) + { + $moved = []; + + if (array_key_exists('children', $data)) { + foreach ($data['children'] as $childSection => $childData) { + $movedChildren = $this->getMoveInstructions($childSection, $childData); + if (isset($movedChildren[$childSection])) { + unset($data['children'][$childSection]); + } + $moved = array_merge($moved, $movedChildren); + } + } + + if (isset($data['displayIn']) && in_array($data['displayIn'], self::$specialGroups)) { + $moved = array_merge( + [ + $section => [ + 'parent' => $data['displayIn'], + 'section' => $section, + 'data' => $data + ] + ], + $moved + ); + } + + return $moved; + } +} diff --git a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php index b026aa09692930fea7a58c1afc2946b280bad9fa..0d07abfb8047fc1c94bd9aba04cb15a0c6fdabfa 100644 --- a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php +++ b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php @@ -10,6 +10,8 @@ use Magento\Config\Model\Config\Structure; use Magento\Config\Model\Config\Structure\Element\Section; use Magento\Config\Model\Config\Structure\ElementInterface; use Magento\Paypal\Helper\Backend as BackendHelper; +use Magento\Framework\App\ObjectManager; +use Magento\Paypal\Model\Config\Structure\PaymentSectionModifier; /** * Plugin for \Magento\Config\Model\Config\Structure @@ -31,6 +33,11 @@ class StructurePlugin */ private $scopeDefiner; + /** + * @var PaymentSectionModifier + */ + private $paymentSectionModifier; + /** * @var string[] */ @@ -50,12 +57,18 @@ class StructurePlugin /** * @param ScopeDefiner $scopeDefiner - * @param BackendHelper $helper + * @param BackendHelper $backendHelper + * @param PaymentSectionModifier|null $paymentSectionModifier */ - public function __construct(ScopeDefiner $scopeDefiner, BackendHelper $helper) - { + public function __construct( + ScopeDefiner $scopeDefiner, + BackendHelper $backendHelper, + PaymentSectionModifier $paymentSectionModifier = null + ) { $this->scopeDefiner = $scopeDefiner; - $this->backendHelper = $helper; + $this->backendHelper = $backendHelper; + $this->paymentSectionModifier = $paymentSectionModifier + ?: ObjectManager::getInstance()->get(PaymentSectionModifier::class); } /** @@ -118,62 +131,17 @@ class StructurePlugin } /** - * Change payment config structure - * - * Groups which have `displayIn` element, transfer to appropriate group. - * Groups without `displayIn` transfer to other payment methods group. + * Changes payment config structure. * * @param Section $result * @return void */ private function restructurePayments(Section $result) { - $sectionMap = [ - 'account' => [], - 'recommended_solutions' => [], - 'other_paypal_payment_solutions' => [], - 'other_payment_methods' => [] - ]; - - $configuration = $result->getData(); - - foreach ($configuration['children'] as $section => $data) { - if (array_key_exists($section, $sectionMap)) { - $sectionMap[$section] = $data; - } elseif ($displayIn = $this->getDisplayInSection($section, $data)) { - $sectionMap[$displayIn['parent']]['children'][$displayIn['section']] = $displayIn['data']; - } else { - $sectionMap['other_payment_methods']['children'][$section] = $data; - } - } - - $configuration['children'] = $sectionMap; - $result->setData($configuration, $this->scopeDefiner->getScope()); - } - - /** - * Recursive search of `displayIn` element in node children - * - * @param string $section - * @param array $data - * @return array|null - */ - private function getDisplayInSection($section, $data) - { - if (is_array($data) && array_key_exists('displayIn', $data)) { - return [ - 'parent' => $data['displayIn'], - 'section' => $section, - 'data' => $data - ]; - } - - if (array_key_exists('children', $data)) { - foreach ($data['children'] as $childSection => $childData) { - return $this->getDisplayInSection($childSection, $childData); - } - } - - return null; + $sectionData = $result->getData(); + $sectionInitialStructure = isset($sectionData['children']) ? $sectionData['children'] : []; + $sectionChangedStructure = $this->paymentSectionModifier->modify($sectionInitialStructure); + $sectionData['children'] = $sectionChangedStructure; + $result->setData($sectionData, $this->scopeDefiner->getScope()); } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fdea2375d8497b76e573d5b8fe610e8adc14efcd --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php @@ -0,0 +1,182 @@ +<?php +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Unit\Model\Config\Structure; + +use Magento\Paypal\Model\Config\Structure\PaymentSectionModifier; + +class PaymentSectionModifierTest extends \PHPUnit_Framework_TestCase +{ + private static $specialGroups = [ + 'account', + 'recommended_solutions', + 'other_paypal_payment_solutions', + 'other_payment_methods', + ]; + + /** + * @param string $case + * @param array $structure + * @dataProvider caseProvider + */ + public function testSpecialGroupsPresent($case, $structure) + { + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + $presentSpecialGroups = array_intersect( + self::$specialGroups, + array_keys($modifiedStructure) + ); + + $this->assertEquals( + self::$specialGroups, + $presentSpecialGroups, + sprintf('All special groups must be present in %s case', $case) + ); + } + + /** + * @param string $case + * @param array $structure + * @dataProvider caseProvider + */ + public function testOnlySpecialGroupsPresent($case, $structure) + { + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + $presentNotSpecialGroups = array_diff( + array_keys($modifiedStructure), + self::$specialGroups + ); + + $this->assertEquals( + [], + $presentNotSpecialGroups, + sprintf('Only special groups should be present at top level in "%s" case', $case) + ); + } + + /** + * @param string $case + * @param array $structure + * @dataProvider caseProvider + */ + public function testGroupsNotRemovedAfterModification($case, $structure) + { + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + + $removedGroups = array_diff( + $this->fetchAllAvailableGroups($structure), + $this->fetchAllAvailableGroups($modifiedStructure) + ); + + $this->assertEquals( + [], + $removedGroups, + sprintf('Groups should not be removed after modification in "%s" case', $case) + ); + } + + public function testMovedToTargetSpecialGroup() + { + $structure = [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'recommended_solutions', + ], + 'some_group' => [ + 'id' => 'some_group', + 'children' => [ + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions' + ], + 'some_payment_method3' => [ + 'id' => 'some_payment_method3', + 'displayIn' => 'other_payment_methods' + ], + 'some_payment_method4' => [ + 'id' => 'some_payment_method4', + 'displayIn' => 'recommended_solutions' + ], + 'some_payment_method5' => [ + 'id' => 'some_payment_method5', + ], + ] + ], + ]; + + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + + $this->assertEquals( + [ + 'account' => [], + 'recommended_solutions' => [ + 'children' => [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + ], + 'some_payment_method4' => [ + 'id' => 'some_payment_method4', + ], + ], + ], + 'other_paypal_payment_solutions' => [], + 'other_payment_methods' => [ + 'children' => [ + 'some_payment_method3' => [ + 'id' => 'some_payment_method3', + ], + 'some_group' => [ + 'id' => 'some_group', + 'children' => [ + 'some_payment_method5' => [ + 'id' => 'some_payment_method5', + ], + ], + ], + ], + ], + ], + $modifiedStructure, + 'Some group is not moved correctly' + ); + } + + /** + * This helper method walks recursively through configuration structure and + * collect available configuration groups + * + * @param array $structure + * @return array Sorted list of group identifiers + */ + private function fetchAllAvailableGroups($structure) + { + $availableGroups = []; + foreach ($structure as $group => $data) { + $availableGroups[] = $group; + if (isset($data['children'])) { + $availableGroups = array_merge( + $availableGroups, + $this->fetchAllAvailableGroups($data['children']) + ); + } + } + $availableGroups = array_values(array_unique($availableGroups)); + sort($availableGroups); + return $availableGroups; + } + + public function caseProvider() + { + return include __DIR__ . '/_files/payment_section_structure_variations.php'; + } +} diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php new file mode 100644 index 0000000000000000000000000000000000000000..3dc323a1b2207c0253b6c885ae4e406f57bfc87f --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php @@ -0,0 +1,129 @@ +<?php +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + [ + 'empty structure', + [] + ], + [ + 'structure with special groups at the begin of the list', + [ + 'account' => [ + 'id' => 'account', + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + ], + 'some_payment_method' => [ + 'id' => 'some_payment_method', + ], + ] + ], + [ + 'structure with special groups at the end of the list', + [ + 'some_payment_method' => [ + 'id' => 'some_payment_method', + ], + 'account' => [ + 'id' => 'account', + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + ], + ] + ], + [ + 'structure with special groups in the middle of the list', + [ + 'some_payment_methodq' => [ + 'id' => 'some_payment_methodq', + ], + 'account' => [ + 'id' => 'account', + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + ], + ] + ], + [ + 'structure with all assigned groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'other_paypal_payment_solutions', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions', + ], + ] + ], + [ + 'structure with not assigned groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'other_paypal_payment_solutions', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + ], + ] + ], + [ + 'special groups has predefined children', + [ + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + 'children' => [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + ] + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions', + ], + ] + ], + [ + 'structure with displayIn that do not reference to special groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'some_payment_method1', + ], + ] + ], +]; diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php index 26dd4af0220aaeebfb10b397a9fa7c494fa36936..2e4d146ac6159b5bf995dca335ea3abe4a06549e 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php @@ -61,7 +61,10 @@ class StructurePluginTest extends \PHPUnit_Framework_TestCase $this->objectManagerHelper = new ObjectManagerHelper($this); $this->plugin = $this->objectManagerHelper->getObject( ConfigStructurePlugin::class, - ['scopeDefiner' => $this->configScopeDefinerMock, 'helper' => $this->backendHelperMock] + [ + 'scopeDefiner' => $this->configScopeDefinerMock, + 'backendHelper' => $this->backendHelperMock + ] ); } diff --git a/app/code/Magento/Sales/Setup/InstallSchema.php b/app/code/Magento/Sales/Setup/InstallSchema.php index 64240feef0f5f4036bed21ce22e14d6f6db57d10..6b0b27739ca15d966ab4cd8259af6b213a939cca 100644 --- a/app/code/Magento/Sales/Setup/InstallSchema.php +++ b/app/code/Magento/Sales/Setup/InstallSchema.php @@ -2091,7 +2091,7 @@ class InstallSchema implements InstallSchemaInterface )->addColumn( 'cc_number_enc', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 32, + 128, [], 'Cc Number Enc' )->addColumn( diff --git a/app/code/Magento/Sales/Setup/UpgradeSchema.php b/app/code/Magento/Sales/Setup/UpgradeSchema.php index 60f93fc765079760b2dd4ca434990337aaee748d..700da396b930d8312dfaaa6015268fa9531ae82b 100644 --- a/app/code/Magento/Sales/Setup/UpgradeSchema.php +++ b/app/code/Magento/Sales/Setup/UpgradeSchema.php @@ -84,6 +84,17 @@ class UpgradeSchema implements UpgradeSchemaInterface ); } } + if (version_compare($context->getVersion(), '2.0.5', '<')) { + $connection = $installer->getConnection(self::$connectionName); + $connection->modifyColumn( + $installer->getTable('sales_order_payment', self::$connectionName), + 'cc_number_enc', + [ + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 'length' => 128 + ] + ); + } } /** diff --git a/app/code/Magento/Shipping/Model/Shipping.php b/app/code/Magento/Shipping/Model/Shipping.php index 3df54577107a9b4dc512f33df197f83abccdc495..d67ab2ddf8d49d0dd07d933ae213378819c5d4f4 100644 --- a/app/code/Magento/Shipping/Model/Shipping.php +++ b/app/code/Magento/Shipping/Model/Shipping.php @@ -5,8 +5,10 @@ */ namespace Magento\Shipping\Model; -use Magento\Sales\Model\Order\Shipment; +use Magento\Framework\App\ObjectManager; use Magento\Quote\Model\Quote\Address\RateCollectorInterface; +use Magento\Quote\Model\Quote\Address\RateRequestFactory; +use Magento\Sales\Model\Order\Shipment; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -81,6 +83,11 @@ class Shipping implements RateCollectorInterface */ protected $stockRegistry; + /** + * @var RateRequestFactory + */ + private $rateRequestFactory; + /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Shipping\Model\Config $shippingConfig @@ -91,6 +98,9 @@ class Shipping implements RateCollectorInterface * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Framework\Math\Division $mathDivision * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + * @param RateRequestFactory $rateRequestFactory + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, @@ -101,7 +111,8 @@ class Shipping implements RateCollectorInterface \Magento\Shipping\Model\Shipment\RequestFactory $shipmentRequestFactory, \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Framework\Math\Division $mathDivision, - \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, + RateRequestFactory $rateRequestFactory = null ) { $this->_scopeConfig = $scopeConfig; $this->_shippingConfig = $shippingConfig; @@ -112,6 +123,7 @@ class Shipping implements RateCollectorInterface $this->_regionFactory = $regionFactory; $this->mathDivision = $mathDivision; $this->stockRegistry = $stockRegistry; + $this->rateRequestFactory = $rateRequestFactory ?: ObjectManager::getInstance()->get(RateRequestFactory::class); } /** @@ -463,7 +475,7 @@ class Shipping implements RateCollectorInterface public function collectRatesByAddress(\Magento\Framework\DataObject $address, $limitCarrier = null) { /** @var $request \Magento\Quote\Model\Quote\Address\RateRequest */ - $request = $this->_shipmentRequestFactory->create(); + $request = $this->rateRequestFactory->create(); $request->setAllItems($address->getAllItems()); $request->setDestCountryId($address->getCountryId()); $request->setDestRegionId($address->getRegionId()); @@ -473,10 +485,13 @@ class Shipping implements RateCollectorInterface $request->setPackageWeight($address->getWeight()); $request->setFreeMethodWeight($address->getFreeMethodWeight()); $request->setPackageQty($address->getItemQty()); - $request->setStoreId($this->_storeManager->getStore()->getId()); - $request->setWebsiteId($this->_storeManager->getStore()->getWebsiteId()); - $request->setBaseCurrency($this->_storeManager->getStore()->getBaseCurrency()); - $request->setPackageCurrency($this->_storeManager->getStore()->getCurrentCurrency()); + + /** @var \Magento\Store\Api\Data\StoreInterface $store */ + $store = $this->_storeManager->getStore(); + $request->setStoreId($store->getId()); + $request->setWebsiteId($store->getWebsiteId()); + $request->setBaseCurrency($store->getBaseCurrency()); + $request->setPackageCurrency($store->getCurrentCurrency()); $request->setLimitCarrier($limitCarrier); $request->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax()); diff --git a/app/code/Magento/Vault/Model/PaymentTokenRepository.php b/app/code/Magento/Vault/Model/PaymentTokenRepository.php index f32e7dbcb45dfe9c6b392504d5c11ffde8f0a460..f904fed1b8ad90168eca6992ca1e03e10b330b67 100644 --- a/app/code/Magento/Vault/Model/PaymentTokenRepository.php +++ b/app/code/Magento/Vault/Model/PaymentTokenRepository.php @@ -129,6 +129,7 @@ class PaymentTokenRepository implements PaymentTokenRepositoryInterface } $tokenModel->setIsActive(false); + $tokenModel->setIsVisible(false); $tokenModel->save(); return true; diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php index 054c0ce20cd813c22b73377884e2b51d2ae83e94..f6e325a0c47900ee280b2272b0c2c84edd96ebf9 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php @@ -17,7 +17,7 @@ class AssertCancelSuccessMessageInShoppingCart extends AbstractConstraint /** * Cancel success message text. */ - const SUCCESS_MESSAGE = 'Payment was canceled.'; + const SUCCESS_MESSAGE = 'Your purchase process has been cancelled.'; /** * Assert that success message about canceled order is present and correct. diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php index 52376ad81245ced6b87694ebbf8d4dd3c70e3a6e..76de7a2ab57d80f751f6c301f12a48dd5393a645 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php @@ -79,6 +79,7 @@ class ChangeTest extends \PHPUnit_Framework_TestCase ) ); $this->assertNotContains($testValue, $values1); + $this->assertRegExp('/([0-9]+:)([0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+)/', current($values1)); // Verify that the credit card number has been encrypted $values2 = $connection->fetchPairs( @@ -88,6 +89,7 @@ class ChangeTest extends \PHPUnit_Framework_TestCase ) ); $this->assertNotContains('1111111111', $values2); + $this->assertRegExp('/([0-9]+:)([0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+)/', current($values1)); /** clean up */ $select = $connection->select()->from($configModel->getMainTable())->where('path=?', $testPath); diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9aadc478f00c4b03f534ef12e71ae1538e81c9c8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Shipping\Model; + +use Magento\Framework\DataObject; +use Magento\Framework\ObjectManagerInterface; +use Magento\Quote\Model\Quote\Address\RateResult\Method; +use Magento\Shipping\Model\Rate\Result; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Contains list of tests for Shipping model + */ +class ShippingTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Shipping + */ + private $model; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(Shipping::class); + } + + /** + * Checks shipping rates processing by address. + * @covers \Magento\Shipping\Model\Shipping::collectRatesByAddress + * @return Result + */ + public function testCollectRatesByAddress() + { + $address = $this->objectManager->create(DataObject::class, [ + 'data' => [ + 'region_id' => 'CA', + 'postcode' => '11111', + 'lastname' => 'John', + 'firstname' => 'Doe', + 'street' => 'Some street', + 'city' => 'Los Angeles', + 'email' => 'john.doe@example.com', + 'telephone' => '11111111', + 'country_id' => 'US', + 'item_qty' => 1 + ] + ]); + /** @var Shipping $result */ + $result = $this->model->collectRatesByAddress($address, 'flatrate'); + static::assertInstanceOf(Shipping::class, $result); + + return $result->getResult(); + } + + /** + * Checks shipping rate details for processed address. + * @covers \Magento\Shipping\Model\Shipping::collectRatesByAddress + * @param Result $result + * @depends testCollectRatesByAddress + * @magentoConfigFixture carriers/flatrate/active 1 + * @magentoConfigFixture carriers/flatrate/price 5.00 + */ + public function testCollectRates(Result $result) + { + $rates = $result->getAllRates(); + static::assertNotEmpty($rates); + + /** @var Method $rate */ + $rate = array_pop($rates); + + static::assertInstanceOf(Method::class, $rate); + static::assertEquals('flatrate', $rate->getData('carrier')); + static::assertEquals(5, $rate->getData('price')); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php index c22ac69db338392544ad2cada1b908c0bc42aa77..255b660de37edde2ac98cb9ddd1d0f939b8d08f3 100644 --- a/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php @@ -8,39 +8,48 @@ namespace Magento\Vault\Model; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SortOrderBuilder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; /** - * Class PaymentTokenRepositoryTest - * @package Magento\Vault\Model + * PaymentTokenRepositoryTest contains tests for Vault token repository + * * @magentoDbIsolation enabled */ class PaymentTokenRepositoryTest extends \PHPUnit_Framework_TestCase { - /** @var PaymentTokenRepository */ + /** + * @var PaymentTokenRepository + */ private $repository; - /** @var SortOrderBuilder */ + /** + * @var SortOrderBuilder + */ private $sortOrderBuilder; - /** @var FilterBuilder */ + /** + * @var FilterBuilder + */ private $filterBuilder; - /** @var SearchCriteriaBuilder */ + /** + * @var SearchCriteriaBuilder + */ private $searchCriteriaBuilder; + /** + * @var ObjectManager + */ + private $objectManager; + public function setUp() { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->repository = $objectManager->create(PaymentTokenRepository::class); - $this->searchCriteriaBuilder = $objectManager->create( - \Magento\Framework\Api\SearchCriteriaBuilder::class - ); - $this->filterBuilder = $objectManager->get( - \Magento\Framework\Api\FilterBuilder::class - ); - $this->sortOrderBuilder = $objectManager->get( - \Magento\Framework\Api\SortOrderBuilder::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->repository = $this->objectManager->create(PaymentTokenRepository::class); + $this->searchCriteriaBuilder = $this->objectManager->create(SearchCriteriaBuilder::class); + $this->filterBuilder = $this->objectManager->get(FilterBuilder::class); + $this->sortOrderBuilder = $this->objectManager->get(SortOrderBuilder::class); } /** @@ -77,4 +86,26 @@ class PaymentTokenRepositoryTest extends \PHPUnit_Framework_TestCase $this->assertEquals('second', array_shift($items)->getPaymentMethodCode()); $this->assertEquals('first', array_shift($items)->getPaymentMethodCode()); } + + /** + * @covers \Magento\Vault\Model\PaymentTokenRepository::delete + * @magentoDataFixture Magento/Vault/_files/token.php + */ + public function testDelete() + { + /** @var PaymentTokenManagement $tokenManagement */ + $tokenManagement = $this->objectManager->get(PaymentTokenManagement::class); + + $token = $tokenManagement->getByPublicHash('public_hash', 0); + + /** @var PaymentTokenRepository $tokenRepository */ + $tokenRepository = $this->objectManager->get(PaymentTokenRepository::class); + $tokenRepository->delete($token); + + $deletedToken = $tokenRepository->getById($token->getEntityId()); + + static::assertEquals('public_hash', $deletedToken->getPublicHash()); + static::assertFalse($deletedToken->getIsActive()); + static::assertFalse($deletedToken->getIsVisible()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Vault/_files/token.php b/dev/tests/integration/testsuite/Magento/Vault/_files/token.php new file mode 100644 index 0000000000000000000000000000000000000000..29e8415c4207213f81e4a70914b53844bd724490 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Vault/_files/token.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Vault\Model\PaymentToken; +use Magento\Vault\Model\PaymentTokenRepository; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var PaymentToken $token */ +$token = $objectManager->create(PaymentToken::class); + +$token->setGatewayToken('gateway_token') + ->setPublicHash('public_hash') + ->setPaymentMethodCode('vault_payment') + ->setType('card') + ->setExpiresAt(strtotime('+1 year')) + ->setIsVisible(true) + ->setIsActive(true); + +/** @var PaymentTokenRepository $tokenRepository */ +$tokenRepository = $objectManager->create(PaymentTokenRepository::class); +$tokenRepository->save($token);