diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 48deddb2fe5ac..89564f97ccf16 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -5,8 +5,11 @@ */ namespace Magento\Sales\Model; +use Magento\Config\Model\Config\Source\Nooptreq; use Magento\Directory\Model\Currency; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; @@ -14,6 +17,7 @@ use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderItemInterface; use Magento\Sales\Api\Data\OrderStatusHistoryInterface; +use Magento\Sales\Api\OrderItemRepositoryInterface; use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\ProductOption; use Magento\Sales\Model\ResourceModel\Order\Address\Collection; @@ -24,8 +28,7 @@ use Magento\Sales\Model\ResourceModel\Order\Shipment\Collection as ShipmentCollection; use Magento\Sales\Model\ResourceModel\Order\Shipment\Track\Collection as TrackCollection; use Magento\Sales\Model\ResourceModel\Order\Status\History\Collection as HistoryCollection; -use Magento\Sales\Api\OrderItemRepositoryInterface; -use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Store\Model\ScopeInterface; /** * Order model @@ -299,6 +302,11 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ private $searchCriteriaBuilder; + /** + * @var ScopeConfigInterface; + */ + private $scopeConfig; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -331,6 +339,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param ProductOption|null $productOption * @param OrderItemRepositoryInterface $itemRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param ScopeConfigInterface $scopeConfig * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -364,7 +373,8 @@ public function __construct( ResolverInterface $localeResolver = null, ProductOption $productOption = null, OrderItemRepositoryInterface $itemRepository = null, - SearchCriteriaBuilder $searchCriteriaBuilder = null + SearchCriteriaBuilder $searchCriteriaBuilder = null, + ScopeConfigInterface $scopeConfig = null ) { $this->_storeManager = $storeManager; $this->_orderConfig = $orderConfig; @@ -392,6 +402,7 @@ public function __construct( ->get(OrderItemRepositoryInterface::class); $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: ObjectManager::getInstance() ->get(SearchCriteriaBuilder::class); + $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); parent::__construct( $context, @@ -1111,7 +1122,7 @@ public function addStatusHistoryComment($comment, $status = false) { return $this->addCommentToStatusHistory($comment, $status, false); } - + /** * Add a comment to order status history. * @@ -1503,7 +1514,7 @@ public function getItemById($itemId) * Get item by quote item id * * @param mixed $quoteItemId - * @return \Magento\Framework\DataObject|null + * @return \Magento\Framework\DataObject|null */ public function getItemByQuoteItemId($quoteItemId) { @@ -1967,11 +1978,23 @@ public function getRelatedObjects() */ public function getCustomerName() { - if ($this->getCustomerFirstname()) { - $customerName = $this->getCustomerFirstname() . ' ' . $this->getCustomerLastname(); - } else { - $customerName = (string)__('Guest'); + if (null === $this->getCustomerFirstname()) { + return (string)__('Guest'); } + + $customerName = ''; + if ($this->isVisibleCustomerPrefix() && strlen($this->getCustomerPrefix())) { + $customerName .= $this->getCustomerPrefix() . ' '; + } + $customerName .= $this->getCustomerFirstname(); + if ($this->isVisibleCustomerMiddlename() && strlen($this->getCustomerMiddlename())) { + $customerName .= ' ' . $this->getCustomerMiddlename(); + } + $customerName .= ' ' . $this->getCustomerLastname(); + if ($this->isVisibleCustomerSuffix() && strlen($this->getCustomerSuffix())) { + $customerName .= ' ' . $this->getCustomerSuffix(); + } + return $customerName; } @@ -4534,5 +4557,48 @@ public function setShippingMethod($shippingMethod) return $this->setData('shipping_method', $shippingMethod); } + /** + * Is visible customer middlename + * + * @return bool + */ + private function isVisibleCustomerMiddlename(): bool + { + return $this->scopeConfig->isSetFlag( + 'customer/address/middlename_show', + ScopeInterface::SCOPE_STORE + ); + } + + /** + * Is visible customer prefix + * + * @return bool + */ + private function isVisibleCustomerPrefix(): bool + { + $prefixShowValue = $this->scopeConfig->getValue( + 'customer/address/prefix_show', + ScopeInterface::SCOPE_STORE + ); + + return $prefixShowValue !== Nooptreq::VALUE_NO; + } + + /** + * Is visible customer suffix + * + * @return bool + */ + private function isVisibleCustomerSuffix(): bool + { + $prefixShowValue = $this->scopeConfig->getValue( + 'customer/address/suffix_show', + ScopeInterface::SCOPE_STORE + ); + + return $prefixShowValue !== Nooptreq::VALUE_NO; + } + //@codeCoverageIgnoreEnd } diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php index 705d2face2308..39c54be0d9c08 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -17,6 +18,8 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SearchCriteria; use Magento\Sales\Api\Data\OrderItemSearchResultInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use PHPUnit\Framework\MockObject\MockObject; /** * Test class for \Magento\Sales\Model\Order @@ -24,6 +27,7 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyPublicMethods) * @SuppressWarnings(PHPMD.ExcessivePublicCount) + * @SuppressWarnings(PHPMD.TooManyFields) */ class OrderTest extends \PHPUnit\Framework\TestCase { @@ -102,6 +106,11 @@ class OrderTest extends \PHPUnit\Framework\TestCase */ private $searchCriteriaBuilder; + /** + * @var MockObject|ScopeConfigInterface $scopeConfigMock + */ + private $scopeConfigMock; + protected function setUp() { $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -125,14 +134,17 @@ protected function setUp() \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class, ['create'] ); - $this->item = $this->createPartialMock(\Magento\Sales\Model\ResourceModel\Order\Item::class, [ + $this->item = $this->createPartialMock( + \Magento\Sales\Model\ResourceModel\Order\Item::class, + [ 'isDeleted', 'getQtyToInvoice', 'getParentItemId', 'getQuoteItemId', 'getLockedDoInvoice', 'getProductId', - ]); + ] + ); $this->salesOrderCollectionMock = $this->getMockBuilder( \Magento\Sales\Model\ResourceModel\Order\Collection::class )->disableOriginalConstructor() @@ -168,6 +180,7 @@ protected function setUp() ->setMethods(['addFilter', 'create']) ->disableOriginalConstructor()->getMockForAbstractClass(); + $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); $this->order = $helper->getObject( \Magento\Sales\Model\Order::class, [ @@ -182,7 +195,8 @@ protected function setUp() 'localeResolver' => $this->localeResolver, 'timezone' => $this->timezone, 'itemRepository' => $this->itemRepository, - 'searchCriteriaBuilder' => $this->searchCriteriaBuilder + 'searchCriteriaBuilder' => $this->searchCriteriaBuilder, + 'scopeConfig' => $this->scopeConfigMock ] ); } @@ -354,6 +368,51 @@ public function testCanInvoice() $this->assertTrue($this->order->canInvoice()); } + /** + * Ensure customer name returned correctly. + * + * @dataProvider customerNameProvider + * @param array $expectedData + */ + public function testGetCustomerName(array $expectedData) + { + $this->order->setCustomerFirstname($expectedData['first_name']); + $this->order->setCustomerSuffix($expectedData['customer_suffix']); + $this->order->setCustomerPrefix($expectedData['customer_prefix']); + $this->scopeConfigMock->expects($this->exactly($expectedData['invocation'])) + ->method('isSetFlag') + ->willReturn(true); + $this->assertEquals($expectedData['expected_name'], $this->order->getCustomerName()); + } + + /** + * Customer name data provider + */ + public function customerNameProvider() + { + return + [ + [ + [ + 'first_name' => null, + 'invocation' => 0, + 'expected_name' => 'Guest', + 'customer_suffix' => 'smith', + 'customer_prefix' => 'mr.' + ] + ], + [ + [ + 'first_name' => 'Smith', + 'invocation' => 1, + 'expected_name' => 'mr. Smith Carl', + 'customer_suffix' => 'Carl', + 'customer_prefix' => 'mr.' + ] + ] + ]; + } + /** * @param string $status * @@ -819,9 +878,10 @@ public function testCanVoidPayment($actionFlags, $orderState) if ($orderState == \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW) { $canVoidOrder = false; } - if ($orderState == \Magento\Sales\Model\Order::STATE_HOLDED && (!isset( - $actionFlags[\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD] - ) || $actionFlags[\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD] !== false) + if ($orderState == \Magento\Sales\Model\Order::STATE_HOLDED && + (!isset($actionFlags[\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD]) || + $actionFlags[\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD] !== false + ) ) { $canVoidOrder = false; }