From e438c7020bce66262c4d6a54d52ab1e823a17c2b Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 27 Aug 2015 12:48:10 +0300 Subject: [PATCH 01/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Ui/InlineEdit.php | 213 +++++ .../Customer/Ui/Component/ColumnFactory.php | 3 + .../Component/Listing/AttributeRepository.php | 8 +- .../Customer/Ui/Component/Listing/Columns.php | 19 + app/code/Magento/Customer/etc/indexer.xml | 2 + .../ui_component/customer_listing.xml | 758 ++++++++++++++++++ 6 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php create mode 100644 app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php new file mode 100644 index 0000000000000..0472b10188355 --- /dev/null +++ b/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php @@ -0,0 +1,213 @@ +customerRepository = $customerRepository; + $this->addressRepository = $addressRepository; + $this->jsonFactory = $jsonFactory; + $this->addressFactory = $addressFactory; + } + + /** + * @return \Magento\Framework\Controller\Result\Json + */ + public function execute() + { + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->jsonFactory->create(); + $error = false; + $messages = []; + + if ($this->getRequest()->getParam('isAjax')) { + $postData = $this->getRequest()->getParam('items', []); + foreach (array_keys($postData) as $customerId) { + $this->setCustomer($this->customerRepository->getById($customerId)); + $this->updateCustomer($this->getData($postData[$customerId], true)); + if ($this->getCustomer()->getDefaultBilling()) { + $this->updateAddress($this->getData($postData[$customerId])); + } else { + $this->addNewAddress($this->getData($postData[$customerId])); + } + } + } + + return $resultJson->setData([ + 'messages' => $messages, + 'error' => $error + ]); + } + + /** + * Receive entity(customer|customer_address) data from request + * + * @param array $data + * @param null $isCustomerData + * @return array + */ + protected function getData(array $data, $isCustomerData = null) + { + $result = []; + $addressKeys = preg_grep( + '/^(' . AttributeRepository::BILLING_ADDRESS_PREFIX . '\w+)/', + array_keys($data), + $isCustomerData + ); + $result = array_intersect_key($data, array_flip($addressKeys)); + if ($isCustomerData === null) { + foreach ($result as $key => $value) { + if (strpos($key, AttributeRepository::BILLING_ADDRESS_PREFIX) !== false) { + unset($result[$key]); + $result[str_replace(AttributeRepository::BILLING_ADDRESS_PREFIX, '', $key)] = $value; + } + } + } + return $result; + } + + /** + * Update customer data + * + * @param array $data + */ + protected function updateCustomer(array $data) + { + $customer = $this->getCustomer(); + $this->setData($customer, $data); + $this->customerRepository->save($customer); + } + + /** + * Update customer address data + * + * @param array $data + */ + protected function updateAddress(array $data) + { + $addresses = $this->getCustomer()->getAddresses(); + /** @var \Magento\Customer\Api\Data\AddressInterface $address */ + foreach ($addresses as $address) { + if ($address->isDefaultBilling()) { + $this->setData($address, $this->parseStreetField($data)); + $this->addressRepository->save($address); + break; + } + } + } + + /** + * Update entity(customer|customer_address) data + * + * @param $entity + * @param $data + */ + protected function setData($entity, $data) + { + foreach ($data as $attributeName => $value) { + $setterName = 'set' . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($attributeName); + // Check if setter exists + if (method_exists($entity, $setterName)) { + call_user_func([$entity, $setterName], $value); + } + } + } + + /** + * Add new address to customer + * + * @param array $data + */ + protected function addNewAddress(array $data) + { + $customer = $this->getCustomer(); + /** @var \Magento\Customer\Api\Data\AddressInterface $address */ + $address = $this->addressFactory->create(); + $this->setData($address, $this->processAddressData($data)); + $address->setIsDefaultBilling(true); + $address->setCustomerId($customer->getId()); + $this->addressRepository->save($address); + $customer->setDefaultBilling($address->getId()); + } + + /** + * Parse street field + * + * @param array $data + * @return array + */ + protected function processAddressData(array $data) + { + if (isset($data['street'])) { + $data['street'] = explode("\n", $data['street']); + } + foreach (['firstname', 'lastname'] as $requiredField) { + if (empty($data[$requiredField])) { + $data[$requiredField] = $this->getCustomer()->{'get' . ucfirst($requiredField)}(); + } + } + return $data; + } + + /** + * Set customer + * + * @param CustomerInterface $customer + */ + protected function setCustomer(CustomerInterface $customer) + { + $this->customer = $customer; + } + + /** + * Receive customer + * + * @return CustomerInterface + */ + protected function getCustomer() + { + return $this->customer; + } +} diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 59a6fca610d28..610022b1e9562 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -58,6 +58,9 @@ public function create(array $attributeData, $columnName, $context, array $confi 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], ], $config); + if (count($attributeData[AttributeMetadata::OPTIONS]) && !isset($config[AttributeMetadata::OPTIONS])) { + $config[AttributeMetadata::OPTIONS] = $attributeData[AttributeMetadata::OPTIONS]; + } if ($attributeData[AttributeMetadata::OPTIONS]) { $config['options'] = $attributeData[AttributeMetadata::OPTIONS]; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index 294fa32b3e872..5afa0a306d516 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -111,11 +111,17 @@ protected function getListForEntity(array $metadata, $entityTypeCode, MetadataMa return $attributes; } + /** + * Convert options to array + * + * @param array $options + * @return array + */ protected function getOptionArray(array $options) { /** @var \Magento\Customer\Api\Data\OptionInterface $option */ foreach ($options as &$option) { - $option = ['label' => $option->getLabel(), 'value' => $option->getValue()]; + $option = ['label' => (string)$option->getLabel(), 'value' => $option->getValue()]; } return $options; } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 2f74af7f6bd16..b3dcfa2c6b121 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -8,6 +8,7 @@ use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Customer\Ui\Component\ColumnFactory; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; +use\Magento\Framework\View\Element\UiComponentInterface; class Columns extends \Magento\Ui\Component\Listing\Columns { @@ -111,6 +112,7 @@ public function addColumn(array $attributeData, $columnName) public function updateColumn(array $attributeData, $newAttributeCode) { $component = $this->components[$attributeData[AttributeMetadata::ATTRIBUTE_CODE]]; + $this->addOptions($component, $attributeData); if ($attributeData[AttributeMetadata::BACKEND_TYPE] != 'static') { if ($attributeData[AttributeMetadata::IS_USED_IN_GRID]) { @@ -134,4 +136,21 @@ public function updateColumn(array $attributeData, $newAttributeCode) ); } } + + /** + * Add options to component + * + * @param UiComponentInterface $component + * @param $attributeData + */ + public function addOptions(UiComponentInterface $component, $attributeData) + { + $config = $component->getData('config'); + if (count($attributeData[AttributeMetadata::OPTIONS]) && !isset($config[AttributeMetadata::OPTIONS])) { + $component->setData( + 'config', + array_merge($config, [AttributeMetadata::OPTIONS => $attributeData[AttributeMetadata::OPTIONS]]) + ); + } + } } diff --git a/app/code/Magento/Customer/etc/indexer.xml b/app/code/Magento/Customer/etc/indexer.xml index 093bb0b559fe3..4266aa569fd3a 100644 --- a/app/code/Magento/Customer/etc/indexer.xml +++ b/app/code/Magento/Customer/etc/indexer.xml @@ -35,6 +35,8 @@ provider="Magento\Customer\Model\Indexer\Address\AttributeProvider"> + + diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml new file mode 100644 index 0000000000000..208262b6a4b5d --- /dev/null +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -0,0 +1,758 @@ + + ++ + + customer_listing.customer_listing_data_source + customer_listing.customer_listing_data_source + + customer_columns + + + add + Add New Customer + primary + */*/new + + + + + + Magento\Customer\Ui\Component\DataProvider + customer_listing_data_source + entity_id + id + + + + + + + + + Magento_Ui/js/grid/provider + + + + + + + ui/grid/toolbar + + + + + + Magento_Ui/js/grid/controls/bookmarks/bookmarks + dataGridActions + + + + customer_listing + + + + + + + + + customer_listing.customer_listing.customer_columns + + Magento_Ui/js/grid/controls/columns + dataGridActions + + + + + + + customer_listing.customer_listing.customer_columns.ids + + + + + + + Magento_Ui/js/grid/search/search + dataGridFilters + customer_listing.customer_listing_data_source + customer_listing.customer_listing.listing_top.listing_filters_chips + + customer_listing.customer_listing.listing_top.bookmarks + current.search + + + + + + + + dataGridFilters + filters + + customer_listing.customer_listing.listing_top.bookmarks + current.filters + + + customer_listing.customer_listing.listing_top.listing_filters + + customer_listing.customer_listing.listing_top.bookmarks:current.columns.${ $.index }.visible + + + + + + + + entity_id + ID + + customer_listing.customer_listing.listing_top.listing_filters + + + + + + + from + from + From + + + + + + + to + to + To + + + + + + + + name + Name + + + + + + + email + Email + + + + + + Magento\Customer\Model\Config\Source\Group\Multiselect + + + + group_id + Group + Select... + + + + + + + billing_telephone + Phone + + + + + + + billing_postcode + ZIP + + + + + + Magento\Directory\Model\Resource\Country\Collection + + + + billing_country_id + Country + Select... + + + + + + + billing_region + State/Province + + + + + + + created_at + Customer Since + + customer_listing.customer_listing.listing_top.listing_filters + + + + + + + from + From + From + MM/dd/YYYY + + + + + + + to + To + To + MM/dd/YYYY + + + + + + + Magento\Config\Model\Config\Source\Website + + + + website_id + Website + Select... + + + + + + + + customer_listing.customer_listing.customer_columns.ids + bottom + + + delete + Delete + customer/index/massDelete + + Delete items + Are you sure you wan't to delete selected items? + + + + subscribe + Subscribe to Newsletter + customer/index/massSubscribe + + + unsubscribe + Unsubscribe from Newsletter + customer/index/massUnsubscribe + + + edit + Edit + + customer_listing.customer_listing.customer_columns_editor + editSelected + + + + entity_id + + + + + + + + customer_listing.customer_listing.listing_top.bookmarks + current.paging + + customer_listing.customer_listing.customer_columns.ids + bottom + + + 20 + 20 + + + 30 + 30 + + + 50 + 50 + + + 100 + 100 + + + 200 + 200 + + + + + + + + + + + customer_listing.customer_listing.listing_top.bookmarks + current + + + customer_listing.customer_listing.customer_columns.ids + true + entity_id + + customer/ui/inlineEdit + /path/to + false + + + + + customer_listing.customer_listing.customer_columns_editor + startEdit + + ${ $.$data.rowIndex } + true + + + true + + customer_listing.customer_listing.listing_top.bookmarks + columns.${ $.index } + current.${ $.storageConfig.root } + + + + + + + + Magento_Ui/js/grid/columns/multiselect + + + entity_id + false + 10 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + asc + true + left + ID + 20 + + + + + + + Magento_Ui/js/grid/columns/column + + + true + text + left + Name + 30 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + text + left + Email + 40 + + + + + + + Magento_Ui/js/grid/columns/select + + + select + true + select + left + Group + 50 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + text + left + Phone + 60 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + text + left + ZIP + 70 + + + + + + + Magento_Ui/js/grid/columns/select + + + select + select + left + Country + 80 + + + + + + + Magento_Ui/js/grid/columns/column + + + true + text + left + State/Province + 90 + + + + + + + Magento_Ui/js/grid/columns/date + + + true + date + left + Customer Since + 100 + + + + + + + Magento_Ui/js/grid/columns/select + + + select + select + left + Web Site + 110 + + + + + + + Magento_Ui/js/grid/columns/date + + + true + false + date + left + Last Logged In + 120 + + + + + + + Magento_Ui/js/grid/columns/column + + + true + false + text + left + Confirmed email + 130 + + + + + + + Magento_Ui/js/grid/columns/column + + + true + false + text + left + Account Created in + 140 + + + + + + + Magento_Ui/js/grid/columns/column + + + false + text + left + Billing Address + 150 + + + + + + + Magento_Ui/js/grid/columns/column + + + false + text + left + Shipping Address + 160 + + + + + + + Magento_Ui/js/grid/columns/date + + + date + true + false + date + left + Date Of Birth + 170 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + Tax VAT Number + 180 + + + + + + + Magento_Ui/js/grid/columns/select + + + select + false + select + left + Gender + 190 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + false + text + left + Street Address + 200 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + City + 210 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + Fax + 220 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + VAT Number + 230 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + Company + 240 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + Billing Firstname + 250 + + + + + + + Magento_Ui/js/grid/columns/column + + + text + true + false + text + left + Billing Lastname + 260 + + + + + + + false + actions + entity_id + left + Action + actions + false + false + + + + + From 09770e8d657acf12c48508defadbf852189e2431 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 27 Aug 2015 12:54:29 +0300 Subject: [PATCH 02/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php index 0472b10188355..b931c031e2e4f 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php @@ -90,7 +90,6 @@ public function execute() */ protected function getData(array $data, $isCustomerData = null) { - $result = []; $addressKeys = preg_grep( '/^(' . AttributeRepository::BILLING_ADDRESS_PREFIX . '\w+)/', array_keys($data), @@ -131,7 +130,7 @@ protected function updateAddress(array $data) /** @var \Magento\Customer\Api\Data\AddressInterface $address */ foreach ($addresses as $address) { if ($address->isDefaultBilling()) { - $this->setData($address, $this->parseStreetField($data)); + $this->setData($address, $this->processAddressData($data)); $this->addressRepository->save($address); break; } From 0c9332d48f946e7870874e33457e21e61eb7dc3c Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 1 Sep 2015 16:16:08 +0300 Subject: [PATCH 03/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Index/InlineEdit.php | 233 ++++++++++++++++++ .../Controller/Adminhtml/Ui/InlineEdit.php | 212 ---------------- .../ui_component/customer_listing.xml | 2 +- 3 files changed, 234 insertions(+), 213 deletions(-) create mode 100644 app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php delete mode 100644 app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php new file mode 100644 index 0000000000000..1201012cc8623 --- /dev/null +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -0,0 +1,233 @@ +resultJsonFactory->create(); + + $postItems = $this->getRequest()->getParam('items', []); + if (!($this->getRequest()->getParam('isAjax') && count($postItems))) { + $this->getMessageManager()->addError(__('Please correct the data sent.')); + } + + foreach (array_keys($postItems) as $customerId) { + $this->setCustomer($this->_customerRepository->getById($customerId)); + if ($this->getCustomer()->getDefaultBilling()) { + $this->updateDefaultBilling($this->getData($postItems[$customerId])); + } else { + $this->addNewBilling($this->getData($postItems[$customerId])); + } + $this->updateCustomer($this->getData($postItems[$customerId], true)); + $this->saveCustomer($this->getCustomer()); + } + + return $resultJson->setData([ + 'messages' => $this->getErrorMessages(), + 'error' => $this->isErrorExists() + ]); + } + + /** + * Receive entity(customer|customer_address) data from request + * + * @param array $data + * @param null $isCustomerData + * @return array + */ + protected function getData(array $data, $isCustomerData = null) + { + $addressKeys = preg_grep( + '/^(' . AttributeRepository::BILLING_ADDRESS_PREFIX . '\w+)/', + array_keys($data), + $isCustomerData + ); + $result = array_intersect_key($data, array_flip($addressKeys)); + if ($isCustomerData === null) { + foreach ($result as $key => $value) { + if (strpos($key, AttributeRepository::BILLING_ADDRESS_PREFIX) !== false) { + unset($result[$key]); + $result[str_replace(AttributeRepository::BILLING_ADDRESS_PREFIX, '', $key)] = $value; + } + } + } + return $result; + } + + /** + * Update customer data + * + * @param array $data + * @return bool|CustomerInterface + */ + protected function updateCustomer(array $data) + { + $customer = $this->getCustomer(); + $customerData = array_merge( + $this->customerMapper->toFlatArray($customer), + $data + ); + $this->dataObjectHelper->populateWithArray( + $customer, + $customerData, + '\Magento\Customer\Api\Data\CustomerInterface' + ); + } + + /** + * Update customer address data + * + * @param array $data + */ + protected function updateDefaultBilling(array $data) + { + $addresses = $this->getCustomer()->getAddresses(); + /** @var \Magento\Customer\Api\Data\AddressInterface $address */ + foreach ($addresses as $address) { + if ($address->isDefaultBilling()) { + $addressData = array_merge( + $this->addressMapper->toFlatArray($address), + $this->processAddressData($data) + ); + $this->dataObjectHelper->populateWithArray( + $address, + $addressData, + '\Magento\Customer\Api\Data\AddressInterface' + ); + break; + } + } + } + + /** + * Add new address to customer + * + * @param array $data + */ + protected function addNewBilling(array $data) + { + $customer = $this->getCustomer(); + /** @var \Magento\Customer\Api\Data\AddressInterface $address */ + $address = $this->addressDataFactory->create(); + $this->dataObjectHelper->populateWithArray( + $address, + $this->processAddressData($data), + '\Magento\Customer\Api\Data\AddressInterface' + ); + $address->setCustomerId($customer->getId()); + $address->setIsDefaultBilling(true); + $this->addressRepository->save($address); + $customer->setAddresses(array_merge($customer->getAddresses(), [$address])); + } + + /** + * Save customer with error catching + * + * @param CustomerInterface $customer + * @return bool + */ + protected function saveCustomer(CustomerInterface $customer) + { + try { + $this->_customerRepository->save($customer); + } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { + $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); + } catch (\Magento\Framework\Validator\Exception $e) { + $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); + } catch (\Magento\Framework\Exception\InputException $e) { + $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); + } catch (\Exception $e) { + $this->messageManager->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); + } + return true; + } + + /** + * Parse street field + * + * @param array $data + * @return array + */ + protected function processAddressData(array $data) + { + if (isset($data['street'])) { + $data['street'] = explode("\n", $data['street']); + } + foreach (['firstname', 'lastname'] as $requiredField) { + if (empty($data[$requiredField])) { + $data[$requiredField] = $this->getCustomer()->{'get' . ucfirst($requiredField)}(); + } + } + return $data; + } + + /** + * Get array with errors + * + * @return array + */ + protected function getErrorMessages() + { + $messages = []; + foreach ($this->getMessageManager()->getMessages()->getItems() as $error) { + $messages[] = $error->getText(); + } + return $messages; + } + + /** + * Check if errors exists + * + * @return bool + */ + protected function isErrorExists() + { + return (bool)$this->getMessageManager()->getMessages(true)->getCount(); + } + + /** + * Set customer + * + * @param CustomerInterface $customer + */ + protected function setCustomer(CustomerInterface $customer) + { + $this->customer = $customer; + } + + /** + * Receive customer + * + * @return CustomerInterface + */ + protected function getCustomer() + { + return $this->customer; + } + + /** + * Add page title to error message + * + * @param string $errorText + * @return string + */ + protected function getErrorWithCustomerId($errorText) + { + return '[Customer ID: ' . $this->getCustomer()->getId() . '] ' . __($errorText); + } +} diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php deleted file mode 100644 index b931c031e2e4f..0000000000000 --- a/app/code/Magento/Customer/Controller/Adminhtml/Ui/InlineEdit.php +++ /dev/null @@ -1,212 +0,0 @@ -customerRepository = $customerRepository; - $this->addressRepository = $addressRepository; - $this->jsonFactory = $jsonFactory; - $this->addressFactory = $addressFactory; - } - - /** - * @return \Magento\Framework\Controller\Result\Json - */ - public function execute() - { - /** @var \Magento\Framework\Controller\Result\Json $resultJson */ - $resultJson = $this->jsonFactory->create(); - $error = false; - $messages = []; - - if ($this->getRequest()->getParam('isAjax')) { - $postData = $this->getRequest()->getParam('items', []); - foreach (array_keys($postData) as $customerId) { - $this->setCustomer($this->customerRepository->getById($customerId)); - $this->updateCustomer($this->getData($postData[$customerId], true)); - if ($this->getCustomer()->getDefaultBilling()) { - $this->updateAddress($this->getData($postData[$customerId])); - } else { - $this->addNewAddress($this->getData($postData[$customerId])); - } - } - } - - return $resultJson->setData([ - 'messages' => $messages, - 'error' => $error - ]); - } - - /** - * Receive entity(customer|customer_address) data from request - * - * @param array $data - * @param null $isCustomerData - * @return array - */ - protected function getData(array $data, $isCustomerData = null) - { - $addressKeys = preg_grep( - '/^(' . AttributeRepository::BILLING_ADDRESS_PREFIX . '\w+)/', - array_keys($data), - $isCustomerData - ); - $result = array_intersect_key($data, array_flip($addressKeys)); - if ($isCustomerData === null) { - foreach ($result as $key => $value) { - if (strpos($key, AttributeRepository::BILLING_ADDRESS_PREFIX) !== false) { - unset($result[$key]); - $result[str_replace(AttributeRepository::BILLING_ADDRESS_PREFIX, '', $key)] = $value; - } - } - } - return $result; - } - - /** - * Update customer data - * - * @param array $data - */ - protected function updateCustomer(array $data) - { - $customer = $this->getCustomer(); - $this->setData($customer, $data); - $this->customerRepository->save($customer); - } - - /** - * Update customer address data - * - * @param array $data - */ - protected function updateAddress(array $data) - { - $addresses = $this->getCustomer()->getAddresses(); - /** @var \Magento\Customer\Api\Data\AddressInterface $address */ - foreach ($addresses as $address) { - if ($address->isDefaultBilling()) { - $this->setData($address, $this->processAddressData($data)); - $this->addressRepository->save($address); - break; - } - } - } - - /** - * Update entity(customer|customer_address) data - * - * @param $entity - * @param $data - */ - protected function setData($entity, $data) - { - foreach ($data as $attributeName => $value) { - $setterName = 'set' . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($attributeName); - // Check if setter exists - if (method_exists($entity, $setterName)) { - call_user_func([$entity, $setterName], $value); - } - } - } - - /** - * Add new address to customer - * - * @param array $data - */ - protected function addNewAddress(array $data) - { - $customer = $this->getCustomer(); - /** @var \Magento\Customer\Api\Data\AddressInterface $address */ - $address = $this->addressFactory->create(); - $this->setData($address, $this->processAddressData($data)); - $address->setIsDefaultBilling(true); - $address->setCustomerId($customer->getId()); - $this->addressRepository->save($address); - $customer->setDefaultBilling($address->getId()); - } - - /** - * Parse street field - * - * @param array $data - * @return array - */ - protected function processAddressData(array $data) - { - if (isset($data['street'])) { - $data['street'] = explode("\n", $data['street']); - } - foreach (['firstname', 'lastname'] as $requiredField) { - if (empty($data[$requiredField])) { - $data[$requiredField] = $this->getCustomer()->{'get' . ucfirst($requiredField)}(); - } - } - return $data; - } - - /** - * Set customer - * - * @param CustomerInterface $customer - */ - protected function setCustomer(CustomerInterface $customer) - { - $this->customer = $customer; - } - - /** - * Receive customer - * - * @return CustomerInterface - */ - protected function getCustomer() - { - return $this->customer; - } -} diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 208262b6a4b5d..4f387c5959212 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -329,7 +329,7 @@ true entity_id - customer/ui/inlineEdit + customer/index/inlineEdit /path/to false From 5454f4cce973a8db2ffe7605a49386d724a3aff7 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 1 Sep 2015 17:21:11 +0300 Subject: [PATCH 04/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Index/InlineEdit.php | 17 +++++++++-------- .../Customer/Ui/Component/ColumnFactory.php | 4 +++- app/code/Magento/Customer/etc/indexer.xml | 1 - .../adminhtml/ui_component/customer_listing.xml | 1 - 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 1201012cc8623..99599ce3ba1fd 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -73,7 +73,7 @@ protected function getData(array $data, $isCustomerData = null) * Update customer data * * @param array $data - * @return bool|CustomerInterface + * @return void */ protected function updateCustomer(array $data) { @@ -93,6 +93,7 @@ protected function updateCustomer(array $data) * Update customer address data * * @param array $data + * @return void */ protected function updateDefaultBilling(array $data) { @@ -118,6 +119,7 @@ protected function updateDefaultBilling(array $data) * Add new address to customer * * @param array $data + * @return void */ protected function addNewBilling(array $data) { @@ -139,22 +141,18 @@ protected function addNewBilling(array $data) * Save customer with error catching * * @param CustomerInterface $customer - * @return bool + * @return void */ protected function saveCustomer(CustomerInterface $customer) { try { $this->_customerRepository->save($customer); - } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { - $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); - } catch (\Magento\Framework\Validator\Exception $e) { - $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); - } catch (\Magento\Framework\Exception\InputException $e) { + } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); } catch (\Exception $e) { $this->messageManager->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); + $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } - return true; } /** @@ -166,6 +164,7 @@ protected function saveCustomer(CustomerInterface $customer) protected function processAddressData(array $data) { if (isset($data['street'])) { + //TODO: will be refactored after problem with street field parsing will be resolved $data['street'] = explode("\n", $data['street']); } foreach (['firstname', 'lastname'] as $requiredField) { @@ -204,10 +203,12 @@ protected function isErrorExists() * Set customer * * @param CustomerInterface $customer + * @return $this */ protected function setCustomer(CustomerInterface $customer) { $this->customer = $customer; + return $this; } /** diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 610022b1e9562..77473b01691bf 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -19,6 +19,7 @@ class ColumnFactory */ protected $jsComponentMap = [ 'text' => 'Magento_Ui/js/grid/columns/column', + 'select' => 'Magento_Ui/js/grid/columns/select', 'date' => 'Magento_Ui/js/grid/columns/date', ]; @@ -29,7 +30,7 @@ class ColumnFactory 'default' => 'text', 'text' => 'text', 'boolean' => 'text', - 'select' => 'text', + 'select' => 'select', 'multiselect' => 'text', 'date' => 'date', ]; @@ -55,6 +56,7 @@ public function create(array $attributeData, $columnName, $context, array $confi $config = array_merge([ 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), + 'editor' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], ], $config); diff --git a/app/code/Magento/Customer/etc/indexer.xml b/app/code/Magento/Customer/etc/indexer.xml index 4266aa569fd3a..d7aa80a12f7b5 100644 --- a/app/code/Magento/Customer/etc/indexer.xml +++ b/app/code/Magento/Customer/etc/indexer.xml @@ -41,7 +41,6 @@ - diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 4f387c5959212..8970a0bf1f0db 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -459,7 +459,6 @@ Magento_Ui/js/grid/columns/select - select select left Country From 1a19d67c3c140a9d908a9a259ff36b7795c0786f Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 1 Sep 2015 18:52:50 +0300 Subject: [PATCH 05/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Controller/Adminhtml/Index/InlineEdit.php | 4 ---- .../Customer/view/adminhtml/ui_component/customer_listing.xml | 1 - 2 files changed, 5 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 99599ce3ba1fd..81d6b4a59f77d 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -163,10 +163,6 @@ protected function saveCustomer(CustomerInterface $customer) */ protected function processAddressData(array $data) { - if (isset($data['street'])) { - //TODO: will be refactored after problem with street field parsing will be resolved - $data['street'] = explode("\n", $data['street']); - } foreach (['firstname', 'lastname'] as $requiredField) { if (empty($data[$requiredField])) { $data[$requiredField] = $this->getCustomer()->{'get' . ucfirst($requiredField)}(); diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 8970a0bf1f0db..f7d725091f722 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -634,7 +634,6 @@ Magento_Ui/js/grid/columns/column - text false text left From 1b0f94de455abd9364e5f2ee0a0049e8f0c7c131 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 1 Sep 2015 18:57:31 +0300 Subject: [PATCH 06/47] MAGETWO-38562: PHP - Customer - Inline editing --- app/code/Magento/Customer/Controller/Adminhtml/Index.php | 8 +++++++- .../Customer/Controller/Adminhtml/Index/InlineEdit.php | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index.php b/app/code/Magento/Customer/Controller/Adminhtml/Index.php index dd1eff1f0efbb..dd0ed50d3d592 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index.php @@ -143,6 +143,9 @@ abstract class Index extends \Magento\Backend\App\Action */ protected $resultJsonFactory; + /** @var \Psr\Log\LoggerInterface */ + protected $logger; + /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry @@ -169,6 +172,7 @@ abstract class Index extends \Magento\Backend\App\Action * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory + * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -197,7 +201,8 @@ public function __construct( \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory, \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, - \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory + \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, + \Psr\Log\LoggerInterface $logger ) { $this->_coreRegistry = $coreRegistry; $this->_fileFactory = $fileFactory; @@ -223,6 +228,7 @@ public function __construct( $this->resultPageFactory = $resultPageFactory; $this->resultForwardFactory = $resultForwardFactory; $this->resultJsonFactory = $resultJsonFactory; + $this->logger = $logger; parent::__construct($context); } diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 81d6b4a59f77d..28cbc31e3f0d6 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -151,7 +151,7 @@ protected function saveCustomer(CustomerInterface $customer) $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); } catch (\Exception $e) { $this->messageManager->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); - $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); + $this->logger->critical($e); } } From a0bbf8abbb9af8655be1d0fbf0ca3f7a13024d61 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 11:29:20 +0300 Subject: [PATCH 07/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Controller/Adminhtml/Index/Viewfile.php | 6 ++++-- app/code/Magento/Customer/Ui/Component/Listing/Columns.php | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php index 52a8ea95f9412..a50ff36ed6c79 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php @@ -88,7 +88,8 @@ public function __construct( \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\Controller\Result\RawFactory $resultRawFactory, - \Magento\Framework\Url\DecoderInterface $urlDecoder + \Magento\Framework\Url\DecoderInterface $urlDecoder, + \Psr\Log\LoggerInterface $logger ) { parent::__construct( $context, @@ -115,7 +116,8 @@ public function __construct( $resultLayoutFactory, $resultPageFactory, $resultForwardFactory, - $resultJsonFactory + $resultJsonFactory, + $logger ); $this->resultRawFactory = $resultRawFactory; $this->urlDecoder = $urlDecoder; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index b3dcfa2c6b121..5b1cb117386f7 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -141,9 +141,10 @@ public function updateColumn(array $attributeData, $newAttributeCode) * Add options to component * * @param UiComponentInterface $component - * @param $attributeData + * @param array $attributeData + * @return void */ - public function addOptions(UiComponentInterface $component, $attributeData) + public function addOptions(UiComponentInterface $component, array $attributeData) { $config = $component->getData('config'); if (count($attributeData[AttributeMetadata::OPTIONS]) && !isset($config[AttributeMetadata::OPTIONS])) { From d900969927691627a6e70b48773fa23105db47db Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 12:01:47 +0300 Subject: [PATCH 08/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Customer/Setup/UpgradeData.php | 16 ++++++++++++-- .../Customer/Ui/Component/Listing/Columns.php | 4 ++-- .../ui_component/customer_listing.xml | 22 ++++++++++++++++--- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Customer/Setup/UpgradeData.php b/app/code/Magento/Customer/Setup/UpgradeData.php index a93a89503a042..5fe1ae9a45fbe 100644 --- a/app/code/Magento/Customer/Setup/UpgradeData.php +++ b/app/code/Magento/Customer/Setup/UpgradeData.php @@ -150,9 +150,9 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_searchable_in_grid' => true, ], 'region_id' => [ - 'is_used_in_grid' => true, + 'is_used_in_grid' => false, 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => true, + 'is_filterable_in_grid' => false, 'is_searchable_in_grid' => false, ], 'postcode' => [ @@ -173,6 +173,18 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => false, 'is_searchable_in_grid' => true, ], + 'firstname' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'lastname' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], ], ]; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 5b1cb117386f7..8409f77a5a535 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -121,7 +121,7 @@ public function updateColumn(array $attributeData, $newAttributeCode) [ 'name' => $newAttributeCode, 'dataType' => $attributeData[AttributeMetadata::BACKEND_TYPE], - 'visible' => $attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID] + 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID] ] ); $component->setData('config', $config); @@ -131,7 +131,7 @@ public function updateColumn(array $attributeData, $newAttributeCode) 'config', array_merge( $component->getData('config'), - ['visible' => $attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID]] + ['visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID]] ) ); } diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index f7d725091f722..af6828c75c4ad 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -399,7 +399,13 @@ Magento_Ui/js/grid/columns/column - text + + text + + true + true + + true text left @@ -414,7 +420,12 @@ Magento_Ui/js/grid/columns/select - select + + select + + true + + true select left @@ -500,7 +511,12 @@ Magento_Ui/js/grid/columns/select - select + + select + + true + + select left Web Site From fe0afe1104e4e107eafabf46a78eee2eb48b8c1c Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 12:03:43 +0300 Subject: [PATCH 09/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Customer/Controller/Adminhtml/Index/Viewfile.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php index a50ff36ed6c79..943eb3b8cd995 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php @@ -58,6 +58,7 @@ class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory * @param \Magento\Framework\Url\DecoderInterface $urlDecoder + * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -87,9 +88,9 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, + \Psr\Log\LoggerInterface $logger, \Magento\Framework\Controller\Result\RawFactory $resultRawFactory, - \Magento\Framework\Url\DecoderInterface $urlDecoder, - \Psr\Log\LoggerInterface $logger + \Magento\Framework\Url\DecoderInterface $urlDecoder ) { parent::__construct( $context, From 87e50280fb72448a377297feb55022e69b5da067 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 12:23:00 +0300 Subject: [PATCH 10/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Customer/InvalidateToken.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php index a4191a86d4522..732ae5f70798c 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php @@ -33,7 +33,6 @@ class InvalidateToken extends \Magento\Customer\Controller\Adminhtml\Index protected $tokenService; /** - * @param CustomerTokenServiceInterface $tokenService * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory @@ -59,6 +58,8 @@ class InvalidateToken extends \Magento\Customer\Controller\Adminhtml\Index * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory + * @param CustomerTokenServiceInterface $tokenService + * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -88,7 +89,8 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, - CustomerTokenServiceInterface $tokenService + CustomerTokenServiceInterface $tokenService, + \Psr\Log\LoggerInterface $logger ) { $this->tokenService = $tokenService; parent::__construct( @@ -116,7 +118,8 @@ public function __construct( $resultLayoutFactory, $resultPageFactory, $resultForwardFactory, - $resultJsonFactory + $resultJsonFactory, + $logger ); } From babeab55e5fb63794ad41dd6dd69c525e03053a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 12:52:11 +0300 Subject: [PATCH 11/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Customer/Setup/UpgradeData.php | 66 ++++++++++++------- app/code/Magento/Customer/etc/module.xml | 2 +- .../ui_component/customer_listing.xml | 12 ++++ 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Customer/Setup/UpgradeData.php b/app/code/Magento/Customer/Setup/UpgradeData.php index 632734648dfb3..44b1342830b58 100644 --- a/app/code/Magento/Customer/Setup/UpgradeData.php +++ b/app/code/Magento/Customer/Setup/UpgradeData.php @@ -149,9 +149,9 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_searchable_in_grid' => true, ], 'region_id' => [ - 'is_used_in_grid' => false, + 'is_used_in_grid' => true, 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, + 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => false, ], 'postcode' => [ @@ -172,6 +172,28 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => false, 'is_searchable_in_grid' => true, ], + ], + ]; + $this->upgradeAttributes($entityAttributes, $customerSetup); + } + + if (version_compare($context->getVersion(), '2.0.2') < 0) { + $entityTypeId = $customerSetup->getEntityTypeId(Customer::ENTITY); + $attributeId = $customerSetup->getAttributeId($entityTypeId, 'gender'); + + $option = ['attribute_id' => $attributeId, 'values' => [3 => 'Not Specified']]; + $customerSetup->addAttributeOption($option); + } + + if (version_compare($context->getVersion(), '2.0.3', '<')) { + $entityAttributes = [ + 'customer_address' => [ + 'region_id' => [ + 'is_used_in_grid' => false, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => false, + ], 'firstname' => [ 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -186,29 +208,29 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface ], ], ]; + $this->upgradeAttributes($entityAttributes, $customerSetup); + } + $setup->endSetup(); + } - foreach ($entityAttributes as $entityType => $attributes) { - foreach ($attributes as $attributeCode => $attributeData) { - $attribute = $customerSetup->getEavConfig()->getAttribute($entityType, $attributeCode); - foreach ($attributeData as $key => $value) { - $attribute->setData($key, $value); - } - $attribute->save(); + /** + * @param array $entityAttributes + * @param CustomerSetup $customerSetup + * @return void + */ + protected function upgradeAttributes(array $entityAttributes, CustomerSetup $customerSetup) + { + foreach ($entityAttributes as $entityType => $attributes) { + foreach ($attributes as $attributeCode => $attributeData) { + $attribute = $customerSetup->getEavConfig()->getAttribute($entityType, $attributeCode); + foreach ($attributeData as $key => $value) { + $attribute->setData($key, $value); } + $attribute->save(); } - $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); - $indexer->reindexAll(); - $this->eavConfig->clear(); } - - if (version_compare($context->getVersion(), '2.0.2') < 0) { - $entityTypeId = $customerSetup->getEntityTypeId(Customer::ENTITY); - $attributeId = $customerSetup->getAttributeId($entityTypeId, 'gender'); - - $option = ['attribute_id' => $attributeId, 'values' => [3 => 'Not Specified']]; - $customerSetup->addAttributeOption($option); - } - - $setup->endSetup(); + $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); + $indexer->reindexAll(); + $this->eavConfig->clear(); } } diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml index c6d9cd6440a39..251ffe9e53fb0 100644 --- a/app/code/Magento/Customer/etc/module.xml +++ b/app/code/Magento/Customer/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index f47561d7b4ee2..582d01e5e391a 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -328,6 +328,18 @@ + + + + edit + Edit + + customer_listing.customer_listing.customer_columns_editor + editSelected + + + + From 2d7a8b6ee2b7774d203cb42e2b6a001da2711498 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 12:57:36 +0300 Subject: [PATCH 12/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Customer/InvalidateToken.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php index 732ae5f70798c..c21d8366fdfbd 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php @@ -89,8 +89,8 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, - CustomerTokenServiceInterface $tokenService, - \Psr\Log\LoggerInterface $logger + \Psr\Log\LoggerInterface $logger, + CustomerTokenServiceInterface $tokenService ) { $this->tokenService = $tokenService; parent::__construct( From 947bc0e3d345c2a161ed4d31b25276cc8c6d3a25 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 13:26:35 +0300 Subject: [PATCH 13/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php index 4b0d7626492ef..ff5f5ad7e8ffe 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php @@ -75,6 +75,7 @@ public function testCreate() 'config' => [ 'label' => __('Label'), 'dataType' => 'text', + 'editor' => 'text', 'align' => 'left', 'visible' => true, 'options' => [ From 7bf6bf6911f1f0393417f3b35b18d2d5d98f9cf1 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 15:41:10 +0300 Subject: [PATCH 14/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Unit/Ui/Component/Listing/ColumnsTest.php | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php index 92ec5d4082f3e..e8faf0b8f6210 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php @@ -138,7 +138,20 @@ public function testPrepareWithUpdateColumn() ->method('getData') ->with('config') ->willReturn([]); - $this->column->expects($this->once()) + $this->column->expects($this->at(3)) + ->method('setData') + ->with( + 'config', + [ + 'options' => [ + [ + 'label' => 'Label', + 'value' => 'Value' + ] + ] + ] + ); + $this->column->expects($this->at(5)) ->method('setData') ->with( 'config', @@ -146,8 +159,7 @@ public function testPrepareWithUpdateColumn() 'name' => $attributeCode, 'dataType' => $backendType, 'visible' => true - ] - ); + ]); $this->component->addColumn($attributeData, $attributeCode); $this->component->prepare(); @@ -186,7 +198,20 @@ public function testPrepareWithUpdateStaticColumn() ->method('getData') ->with('config') ->willReturn([]); - $this->column->expects($this->once()) + $this->column->expects($this->at(3)) + ->method('setData') + ->with( + 'config', + [ + 'options' => [ + [ + 'label' => 'Label', + 'value' => 'Value' + ] + ] + ] + ); + $this->column->expects($this->at(5)) ->method('setData') ->with( 'config', From 580c08837ae90eacfb4d816df2c3f5f6438a21fe Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 15:47:41 +0300 Subject: [PATCH 15/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php index e8faf0b8f6210..357c209026351 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php @@ -159,7 +159,8 @@ public function testPrepareWithUpdateColumn() 'name' => $attributeCode, 'dataType' => $backendType, 'visible' => true - ]); + ] + ); $this->component->addColumn($attributeData, $attributeCode); $this->component->prepare(); From d1559da87de75349f0961df06bb64119e117bf8d Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Wed, 2 Sep 2015 17:40:13 +0300 Subject: [PATCH 16/47] MAGETWO-41478: Cannot access public wish list after it is renamed --- .../Wishlist/view/frontend/layout/wishlist_shared_index.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_shared_index.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_shared_index.xml index 9b0a5804ab781..3ee4e012f66be 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_shared_index.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_shared_index.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> - + From 686266c3eb7c82b269232d981109519c3bf59a84 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 2 Sep 2015 18:40:23 +0300 Subject: [PATCH 17/47] MAGETWO-38562: PHP - Customer - Inline editing --- app/code/Magento/Ui/Component/Filters/Type/Input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/Component/Filters/Type/Input.php b/app/code/Magento/Ui/Component/Filters/Type/Input.php index 7b7bb9b192827..50474472ae05b 100644 --- a/app/code/Magento/Ui/Component/Filters/Type/Input.php +++ b/app/code/Magento/Ui/Component/Filters/Type/Input.php @@ -69,7 +69,7 @@ protected function applyFilter() if (!empty($value)) { $filter = $this->filterBuilder->setConditionType('like') ->setField($this->getName()) - ->setValue(sprintf('%s%%', $value)) + ->setValue(sprintf('%%%s%%', $value)) ->create(); $this->getContext()->getDataProvider()->addFilter($filter); From 44c9de07b44098ae314b0e2c03360114c7a38274 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 3 Sep 2015 13:20:49 +0300 Subject: [PATCH 18/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Controller/Adminhtml/Index/InlineEdit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 28cbc31e3f0d6..98390196b6974 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -148,9 +148,9 @@ protected function saveCustomer(CustomerInterface $customer) try { $this->_customerRepository->save($customer); } catch (\Magento\Framework\Exception\LocalizedException $e) { - $this->messageManager->addError($this->getErrorWithCustomerId($e->getMessage())); + $this->getMessageManager()->addError($this->getErrorWithCustomerId($e->getMessage())); } catch (\Exception $e) { - $this->messageManager->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); + $this->getMessageManager()->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); $this->logger->critical($e); } } From 5cbaaa33e2ce2b1e3898b169a9ead010927da982 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 3 Sep 2015 14:56:31 +0300 Subject: [PATCH 19/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Index/InlineEdit.php | 8 +- .../Adminhtml/Index/InlineEditTest.php | 385 ++++++++++++++++++ 2 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 98390196b6974..5173b338497e3 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -11,7 +11,7 @@ class InlineEdit extends \Magento\Customer\Controller\Adminhtml\Index { /** @var CustomerInterface */ - protected $customer; + private $customer; /** * @return \Magento\Framework\Controller\Result\Json @@ -23,7 +23,10 @@ public function execute() $postItems = $this->getRequest()->getParam('items', []); if (!($this->getRequest()->getParam('isAjax') && count($postItems))) { - $this->getMessageManager()->addError(__('Please correct the data sent.')); + return $resultJson->setData([ + 'messages' => [__('Please correct the data sent.')], + 'error' => true, + ]); } foreach (array_keys($postItems) as $customerId) { @@ -149,6 +152,7 @@ protected function saveCustomer(CustomerInterface $customer) $this->_customerRepository->save($customer); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->getMessageManager()->addError($this->getErrorWithCustomerId($e->getMessage())); + $this->logger->critical($e); } catch (\Exception $e) { $this->getMessageManager()->addError($this->getErrorWithCustomerId('We can\'t save the customer.')); $this->logger->critical($e); diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php new file mode 100644 index 0000000000000..5e3ff17544ac6 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php @@ -0,0 +1,385 @@ +request = $this->getMockForAbstractClass('Magento\Framework\App\RequestInterface', [], '', false); + $this->messageManager = $this->getMockForAbstractClass( + 'Magento\Framework\Message\ManagerInterface', + [], + '', + false + ); + $this->customerData = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + '', + false + ); + $this->address = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\AddressInterface', + [], + 'address', + false + ); + $this->addressMapper = $this->getMock('Magento\Customer\Model\Address\Mapper', [], [], '', false); + $this->customerMapper = $this->getMock('Magento\Customer\Model\Customer\Mapper', [], [], '', false); + $this->resultJsonFactory = $this->getMock( + 'Magento\Framework\Controller\Result\JsonFactory', + ['create'], + [], + '', + false + ); + $this->resultJson = $this->getMock('Magento\Framework\Controller\Result\Json', [], [], '', false); + $this->customerRepository = $this->getMockForAbstractClass( + 'Magento\Customer\Api\CustomerRepositoryInterface', + [], + '', + false + ); + $this->dataObjectHelper = $this->getMock('Magento\Framework\Api\DataObjectHelper', [], [], '', false); + $this->addressDataFactory = $this->getMock( + 'Magento\Customer\Api\Data\AddressInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->addressRepository = $this->getMockForAbstractClass( + 'Magento\Customer\Api\AddressRepositoryInterface', + [], + '', + false + ); + $this->messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false); + $this->message = $this->getMockForAbstractClass( + 'Magento\Framework\Message\MessageInterface', + [], + '', + false + ); + $this->logger = $this->getMockForAbstractClass('Psr\Log\LoggerInterface', [], '', false); + + $this->context = $objectManager->getObject( + 'Magento\Backend\App\Action\Context', + [ + 'request' => $this->request, + 'messageManager' => $this->messageManager, + ] + ); + $this->controller = $objectManager->getObject( + 'Magento\Customer\Controller\Adminhtml\Index\InlineEdit', + [ + 'context' => $this->context, + 'resultJsonFactory' => $this->resultJsonFactory, + 'customerRepository' => $this->customerRepository, + 'addressMapper' => $this->addressMapper, + 'customerMapper' => $this->customerMapper, + 'dataObjectHelper' => $this->dataObjectHelper, + 'addressDataFactory' => $this->addressDataFactory, + 'addressRepository' => $this->addressRepository, + 'logger' => $this->logger, + ] + ); + + $this->items = [ + 14 => [ + 'email' => 'test@test.ua', + 'billing_postcode' => '07294', + ] + ]; + } + + protected function prepareMocksForTesting() + { + $this->resultJsonFactory->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + $this->request->expects($this->at(0)) + ->method('getParam') + ->with('items', []) + ->willReturn($this->items); + $this->request->expects($this->at(1)) + ->method('getParam') + ->with('isAjax') + ->willReturn(true); + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with(14) + ->willReturn($this->customerData); + $this->customerMapper->expects($this->once()) + ->method('toFlatArray') + ->with($this->customerData) + ->willReturn(['name' => 'Firstname Lastname']); + $this->dataObjectHelper->expects($this->at(1)) + ->method('populateWithArray') + ->with( + $this->customerData, + [ + 'name' => 'Firstname Lastname', + 'email' => 'test@test.ua', + ], + '\Magento\Customer\Api\Data\CustomerInterface' + ); + } + + protected function prepareMocksForUpdateDefaultBilling() + { + $this->prepareMocksForProcessAddressData(); + $addressData = [ + 'postcode' => '07294', + 'firstname' => 'Firstname', + 'lastname' => 'Lastname', + ]; + $this->customerData->expects($this->once()) + ->method('getAddresses') + ->willReturn([$this->address]); + $this->address->expects($this->once()) + ->method('isDefaultBilling') + ->willReturn(true); + $this->addressMapper->expects($this->once()) + ->method('toFlatArray') + ->with($this->address) + ->willReturn([]); + $this->dataObjectHelper->expects($this->at(0)) + ->method('populateWithArray') + ->with( + $this->address, + $addressData, + '\Magento\Customer\Api\Data\AddressInterface' + ); + } + + protected function prepareMocksForAddNewBilling() + { + $this->prepareMocksForProcessAddressData(); + $addressData = [ + 'postcode' => '07294', + 'firstname' => 'Firstname', + 'lastname' => 'Lastname', + ]; + + $this->addressDataFactory->expects($this->once()) + ->method('create') + ->willReturn($this->address); + $this->dataObjectHelper->expects($this->at(0)) + ->method('populateWithArray') + ->with( + $this->address, + $addressData, + '\Magento\Customer\Api\Data\AddressInterface' + ); + $this->customerData->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(12); + $this->address->expects($this->once()) + ->method('setCustomerId') + ->with(12); + $this->address->expects($this->once()) + ->method('setIsDefaultBilling') + ->with(true); + $this->addressRepository->expects($this->once()) + ->method('save') + ->with($this->address); + $this->customerData->expects($this->once()) + ->method('getAddresses') + ->willReturn([]); + $this->customerData->expects($this->once()) + ->method('setAddresses') + ->with([$this->address]); + } + + protected function prepareMocksForProcessAddressData() + { + $this->customerData->expects($this->once()) + ->method('getFirstname') + ->willReturn('Firstname'); + $this->customerData->expects($this->once()) + ->method('getLastname') + ->willReturn('Lastname'); + } + + protected function prepareMocksForErrorMessagesProcessing() + { + $this->messageManager->expects($this->atLeastOnce()) + ->method('getMessages') + ->willReturn($this->messageCollection); + $this->messageCollection->expects($this->once()) + ->method('getItems') + ->willReturn([$this->message]); + $this->messageCollection->expects($this->once()) + ->method('getCount') + ->willReturn(1); + $this->message->expects($this->once()) + ->method('getText') + ->willReturn('Error text'); + $this->resultJson->expects($this->once()) + ->method('setData') + ->with([ + 'messages' => ['Error text'], + 'error' => true, + ]) + ->willReturnSelf(); + } + + public function testExecuteWithUpdateBilling() + { + $this->prepareMocksForTesting(); + $this->customerData->expects($this->once()) + ->method('getDefaultBilling') + ->willReturn(23); + $this->prepareMocksForUpdateDefaultBilling(); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($this->customerData); + $this->prepareMocksForErrorMessagesProcessing(); + $this->assertSame($this->resultJson, $this->controller->execute()); + } + + public function testExecuteWithNewBilling() + { + $this->prepareMocksForTesting(); + $this->customerData->expects($this->once()) + ->method('getDefaultBilling') + ->willReturn(false); + $this->prepareMocksForAddNewBilling(); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($this->customerData); + $this->prepareMocksForErrorMessagesProcessing(); + $this->assertSame($this->resultJson, $this->controller->execute()); + } + + public function testExecuteWithoutItems() + { + $this->resultJsonFactory->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + $this->request->expects($this->at(0)) + ->method('getParam') + ->with('items', []) + ->willReturn([]); + $this->request->expects($this->at(1)) + ->method('getParam') + ->with('isAjax') + ->willReturn(false); + $this->resultJson + ->expects($this->once()) + ->method('setData') + ->with([ + 'messages' => [__('Please correct the data sent.')], + 'error' => true, + ]) + ->willReturnSelf(); + $this->assertSame($this->resultJson, $this->controller->execute()); + } + + public function testExecuteLocalizedException() + { + $exception = new \Magento\Framework\Exception\LocalizedException(__('Exception message')); + $this->prepareMocksForTesting(); + $this->customerData->expects($this->once()) + ->method('getDefaultBilling') + ->willReturn(false); + $this->prepareMocksForAddNewBilling(); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($this->customerData) + ->willThrowException($exception); + $this->messageManager->expects($this->once()) + ->method('addError') + ->with('[Customer ID: 12] Exception message'); + $this->logger->expects($this->once()) + ->method('critical') + ->with($exception); + + $this->prepareMocksForErrorMessagesProcessing(); + $this->assertSame($this->resultJson, $this->controller->execute()); + } + + public function testExecuteException() + { + $exception = new \Exception('Exception message'); + $this->prepareMocksForTesting(); + $this->customerData->expects($this->once()) + ->method('getDefaultBilling') + ->willReturn(false); + $this->prepareMocksForAddNewBilling(); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($this->customerData) + ->willThrowException($exception); + $this->messageManager->expects($this->once()) + ->method('addError') + ->with('[Customer ID: 12] We can\'t save the customer.'); + $this->logger->expects($this->once()) + ->method('critical') + ->with($exception); + + $this->prepareMocksForErrorMessagesProcessing(); + $this->assertSame($this->resultJson, $this->controller->execute()); + } +} From 78291a62ac8d52524f48bbddd0708db7644aaa82 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 3 Sep 2015 16:06:55 +0300 Subject: [PATCH 20/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Index/InlineEdit.php | 6 +---- .../Adminhtml/Index/InlineEditTest.php | 4 ---- .../ui_component/customer_listing.xml | 22 ------------------- 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 5173b338497e3..f67f08ae44254 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -104,13 +104,9 @@ protected function updateDefaultBilling(array $data) /** @var \Magento\Customer\Api\Data\AddressInterface $address */ foreach ($addresses as $address) { if ($address->isDefaultBilling()) { - $addressData = array_merge( - $this->addressMapper->toFlatArray($address), - $this->processAddressData($data) - ); $this->dataObjectHelper->populateWithArray( $address, - $addressData, + $this->processAddressData($data), '\Magento\Customer\Api\Data\AddressInterface' ); break; diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php index 5e3ff17544ac6..d943fef8a2bc9 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php @@ -200,10 +200,6 @@ protected function prepareMocksForUpdateDefaultBilling() $this->address->expects($this->once()) ->method('isDefaultBilling') ->willReturn(true); - $this->addressMapper->expects($this->once()) - ->method('toFlatArray') - ->with($this->address) - ->willReturn([]); $this->dataObjectHelper->expects($this->at(0)) ->method('populateWithArray') ->with( diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 582d01e5e391a..f3d609d68266f 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -248,29 +248,7 @@ customer_listing.customer_listing.customer_columns.ids - Magento_Ui/js/grid/tree-massactions bottom - - - delete - Delete - customer/index/massDelete - - Delete items - Are you sure you wan't to delete selected items? - - - - subscribe - Subscribe to Newsletter - customer/index/massSubscribe - - - unsubscribe - Unsubscribe from Newsletter - customer/index/massUnsubscribe - - entity_id From 56667b865285dec6e4f47ef007d5c07e23f33e25 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Thu, 3 Sep 2015 18:49:41 +0300 Subject: [PATCH 21/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Controller/Adminhtml/Index/InlineEdit.php | 24 ------- .../Adminhtml/Index/InlineEditTest.php | 64 ++----------------- .../ui_component/customer_listing.xml | 1 + 3 files changed, 7 insertions(+), 82 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index f67f08ae44254..d6a03a8ae6aa8 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -33,8 +33,6 @@ public function execute() $this->setCustomer($this->_customerRepository->getById($customerId)); if ($this->getCustomer()->getDefaultBilling()) { $this->updateDefaultBilling($this->getData($postItems[$customerId])); - } else { - $this->addNewBilling($this->getData($postItems[$customerId])); } $this->updateCustomer($this->getData($postItems[$customerId], true)); $this->saveCustomer($this->getCustomer()); @@ -114,28 +112,6 @@ protected function updateDefaultBilling(array $data) } } - /** - * Add new address to customer - * - * @param array $data - * @return void - */ - protected function addNewBilling(array $data) - { - $customer = $this->getCustomer(); - /** @var \Magento\Customer\Api\Data\AddressInterface $address */ - $address = $this->addressDataFactory->create(); - $this->dataObjectHelper->populateWithArray( - $address, - $this->processAddressData($data), - '\Magento\Customer\Api\Data\AddressInterface' - ); - $address->setCustomerId($customer->getId()); - $address->setIsDefaultBilling(true); - $this->addressRepository->save($address); - $customer->setAddresses(array_merge($customer->getAddresses(), [$address])); - } - /** * Save customer with error catching * diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php index d943fef8a2bc9..f820b44f118b3 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php @@ -153,7 +153,7 @@ public function setUp() ]; } - protected function prepareMocksForTesting() + protected function prepareMocksForTesting($populateSequence = 0) { $this->resultJsonFactory->expects($this->once()) ->method('create') @@ -174,7 +174,7 @@ protected function prepareMocksForTesting() ->method('toFlatArray') ->with($this->customerData) ->willReturn(['name' => 'Firstname Lastname']); - $this->dataObjectHelper->expects($this->at(1)) + $this->dataObjectHelper->expects($this->at($populateSequence)) ->method('populateWithArray') ->with( $this->customerData, @@ -184,6 +184,9 @@ protected function prepareMocksForTesting() ], '\Magento\Customer\Api\Data\CustomerInterface' ); + $this->customerData->expects($this->any()) + ->method('getId') + ->willReturn(12); } protected function prepareMocksForUpdateDefaultBilling() @@ -209,45 +212,6 @@ protected function prepareMocksForUpdateDefaultBilling() ); } - protected function prepareMocksForAddNewBilling() - { - $this->prepareMocksForProcessAddressData(); - $addressData = [ - 'postcode' => '07294', - 'firstname' => 'Firstname', - 'lastname' => 'Lastname', - ]; - - $this->addressDataFactory->expects($this->once()) - ->method('create') - ->willReturn($this->address); - $this->dataObjectHelper->expects($this->at(0)) - ->method('populateWithArray') - ->with( - $this->address, - $addressData, - '\Magento\Customer\Api\Data\AddressInterface' - ); - $this->customerData->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn(12); - $this->address->expects($this->once()) - ->method('setCustomerId') - ->with(12); - $this->address->expects($this->once()) - ->method('setIsDefaultBilling') - ->with(true); - $this->addressRepository->expects($this->once()) - ->method('save') - ->with($this->address); - $this->customerData->expects($this->once()) - ->method('getAddresses') - ->willReturn([]); - $this->customerData->expects($this->once()) - ->method('setAddresses') - ->with([$this->address]); - } - protected function prepareMocksForProcessAddressData() { $this->customerData->expects($this->once()) @@ -283,7 +247,7 @@ protected function prepareMocksForErrorMessagesProcessing() public function testExecuteWithUpdateBilling() { - $this->prepareMocksForTesting(); + $this->prepareMocksForTesting(1); $this->customerData->expects($this->once()) ->method('getDefaultBilling') ->willReturn(23); @@ -295,20 +259,6 @@ public function testExecuteWithUpdateBilling() $this->assertSame($this->resultJson, $this->controller->execute()); } - public function testExecuteWithNewBilling() - { - $this->prepareMocksForTesting(); - $this->customerData->expects($this->once()) - ->method('getDefaultBilling') - ->willReturn(false); - $this->prepareMocksForAddNewBilling(); - $this->customerRepository->expects($this->once()) - ->method('save') - ->with($this->customerData); - $this->prepareMocksForErrorMessagesProcessing(); - $this->assertSame($this->resultJson, $this->controller->execute()); - } - public function testExecuteWithoutItems() { $this->resultJsonFactory->expects($this->once()) @@ -340,7 +290,6 @@ public function testExecuteLocalizedException() $this->customerData->expects($this->once()) ->method('getDefaultBilling') ->willReturn(false); - $this->prepareMocksForAddNewBilling(); $this->customerRepository->expects($this->once()) ->method('save') ->with($this->customerData) @@ -363,7 +312,6 @@ public function testExecuteException() $this->customerData->expects($this->once()) ->method('getDefaultBilling') ->willReturn(false); - $this->prepareMocksForAddNewBilling(); $this->customerRepository->expects($this->once()) ->method('save') ->with($this->customerData) diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index f3d609d68266f..209764421ae9c 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -248,6 +248,7 @@ customer_listing.customer_listing.customer_columns.ids + Magento_Ui/js/grid/tree-massactions bottom entity_id From 7abfa2a72a407ee65f386e13af9aaf4076458c6a Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Fri, 4 Sep 2015 17:54:45 +0300 Subject: [PATCH 22/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Ui/Component/ColumnFactory.php | 36 ++++++---- .../Component/Listing/AttributeRepository.php | 3 + .../Customer/Ui/Component/Listing/Columns.php | 26 +++++-- .../ui_component/customer_listing.xml | 10 --- .../Grid/Column/InlineEditUpdater.php | 62 ++++++++++++++++ .../Component/Grid/Column/ValidationRules.php | 71 +++++++++++++++++++ 6 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php create mode 100644 app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 77473b01691bf..0061e5bccb82f 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -6,30 +6,29 @@ namespace Magento\Customer\Ui\Component; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; +use Magento\Ui\Component\Grid\Column\InlineEditUpdater; +use Magento\Customer\Api\CustomerMetadataInterface; class ColumnFactory { - /** - * @var \Magento\Framework\View\Element\UiComponentFactory - */ + /** @var \Magento\Framework\View\Element\UiComponentFactory */ protected $componentFactory; - /** - * @var array - */ + /** @var InlineEditUpdater */ + protected $inlineEditUpdater; + + /** @var array */ protected $jsComponentMap = [ 'text' => 'Magento_Ui/js/grid/columns/column', 'select' => 'Magento_Ui/js/grid/columns/select', 'date' => 'Magento_Ui/js/grid/columns/date', ]; - /** - * @var array - */ + /** @var array */ protected $dataTypeMap = [ 'default' => 'text', 'text' => 'text', - 'boolean' => 'text', + 'boolean' => 'select', 'select' => 'select', 'multiselect' => 'text', 'date' => 'date', @@ -37,11 +36,14 @@ class ColumnFactory /** * @param \Magento\Framework\View\Element\UiComponentFactory $componentFactory + * @param InlineEditUpdater $inlineEditor */ public function __construct( - \Magento\Framework\View\Element\UiComponentFactory $componentFactory + \Magento\Framework\View\Element\UiComponentFactory $componentFactory, + InlineEditUpdater $inlineEditor ) { $this->componentFactory = $componentFactory; + $this->inlineEditUpdater = $inlineEditor; } /** @@ -56,7 +58,6 @@ public function create(array $attributeData, $columnName, $context, array $confi $config = array_merge([ 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), - 'editor' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], ], $config); @@ -76,7 +77,16 @@ public function create(array $attributeData, $columnName, $context, array $confi ], 'context' => $context, ]; - return $this->componentFactory->create($columnName, 'column', $arguments); + $column = $this->componentFactory->create($columnName, 'column', $arguments); + if ($attributeData['entity_type_code'] == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + $this->inlineEditUpdater->applyEditing( + $column, + $attributeData[AttributeMetadata::FRONTEND_INPUT], + $attributeData[AttributeMetadata::VALIDATION_RULES], + $attributeData[AttributeMetadata::REQUIRED] + ); + } + return $column; } /** diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index 5afa0a306d516..5238b24ec8c0d 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -105,6 +105,9 @@ protected function getListForEntity(array $metadata, $entityTypeCode, MetadataMa AttributeMetadataInterface::IS_VISIBLE_IN_GRID => $attribute->getIsVisibleInGrid(), AttributeMetadataInterface::IS_FILTERABLE_IN_GRID => $management->canBeFilterableInGrid($attribute), AttributeMetadataInterface::IS_SEARCHABLE_IN_GRID => $management->canBeSearchableInGrid($attribute), + AttributeMetadataInterface::VALIDATION_RULES => $attribute->getValidationRules(), + AttributeMetadataInterface::REQUIRED => $attribute->isRequired(), + 'entity_type_code' => $entityTypeCode, ]; } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 8409f77a5a535..2c46f49323a59 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -8,24 +8,26 @@ use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Customer\Ui\Component\ColumnFactory; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; -use\Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\Component\Grid\Column\InlineEditUpdater; +use Magento\Customer\Api\CustomerMetadataInterface; class Columns extends \Magento\Ui\Component\Listing\Columns { - /** - * @var int - */ + /** @var int */ protected $columnSortOrder; - /** - * @var AttributeRepository - */ + /** @var AttributeRepository */ protected $attributeRepository; + /** @var InlineEditUpdater */ + protected $inlineEditUpdater; + /** * @param ContextInterface $context * @param ColumnFactory $columnFactory * @param AttributeRepository $attributeRepository + * @param InlineEditUpdater $inlineEditor * @param array $components * @param array $data */ @@ -33,12 +35,14 @@ public function __construct( ContextInterface $context, ColumnFactory $columnFactory, AttributeRepository $attributeRepository, + InlineEditUpdater $inlineEditor, array $components = [], array $data = [] ) { parent::__construct($context, $components, $data); $this->columnFactory = $columnFactory; $this->attributeRepository = $attributeRepository; + $this->inlineEditUpdater = $inlineEditor; } /** @@ -113,6 +117,14 @@ public function updateColumn(array $attributeData, $newAttributeCode) { $component = $this->components[$attributeData[AttributeMetadata::ATTRIBUTE_CODE]]; $this->addOptions($component, $attributeData); + if ($attributeData['entity_type_code'] == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + $this->inlineEditUpdater->applyEditing( + $component, + $attributeData[AttributeMetadata::FRONTEND_INPUT], + $attributeData[AttributeMetadata::VALIDATION_RULES], + $attributeData[AttributeMetadata::REQUIRED] + ); + } if ($attributeData[AttributeMetadata::BACKEND_TYPE] != 'static') { if ($attributeData[AttributeMetadata::IS_USED_IN_GRID]) { diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 209764421ae9c..bcec4946dff93 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -439,10 +439,6 @@ text - - true - true - true text @@ -460,9 +456,6 @@ select - - true - true select @@ -551,9 +544,6 @@ select - - true - select left diff --git a/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php b/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php new file mode 100644 index 0000000000000..99dd7f4f14515 --- /dev/null +++ b/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php @@ -0,0 +1,62 @@ +validationRules = $validationRules; + } + + /** + * Add editor config + * + * @param UiComponentInterface $column + * @param $frontendInput + * @param array $validationRules + * @param bool|false $isRequired + * @return UiComponentInterface + */ + public function applyEditing( + UiComponentInterface $column, + $frontendInput, + array $validationRules, + $isRequired = false + ) { + if (in_array($frontendInput, $this->editableFields)) { + $config = $column->getConfiguration(); + $config['editor'] = [ + 'editorType' => $config['dataType'] + ]; + $validationRules = $this->validationRules->getValidationRules($isRequired, $validationRules); + if (!empty($validationRules)) { + $config['editor']['validation'] = $validationRules; + } + $column->setData('config', $config); + } + return $column; + } +} diff --git a/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php b/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php new file mode 100644 index 0000000000000..c9a2679eebfec --- /dev/null +++ b/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php @@ -0,0 +1,71 @@ + 'validate-alpha', + 'numeric' => 'validate-number', + 'alphanumeric' => 'validate-alphanum', + 'url' => 'validate-url', + 'email' => 'validate-email', + ]; + + /** + * @param $isRequired + * @param $validationRules + * @return array + */ + public function getValidationRules($isRequired, $validationRules) + { + $rules = []; + if ($isRequired) { + $rules['required-entry'] = true; + } + if (empty($validationRules)) { + return $rules; + } + /** @var ValidationRuleInterface $rule */ + foreach ($validationRules as $rule) { + if (!$rule instanceof ValidationRuleInterface) { + continue; + } + $validationClass = $this->getValidationClass($rule); + if ($validationClass) { + $rules[$validationClass] = $this->getRuleValue($rule); + } + } + + return $rules; + } + + /** + * @param ValidationRuleInterface $rule + * @return string + */ + protected function getValidationClass(ValidationRuleInterface $rule) + { + $key = $rule->getName() == 'input_validation' ? $rule->getValue() : $rule->getName(); + return isset($this->inputValidationMap[$key]) + ? $this->inputValidationMap[$key] + : $key; + } + + /** + * @param ValidationRuleInterface $rule + * @return bool|string + */ + protected function getRuleValue(ValidationRuleInterface $rule) + { + return $rule->getName() != 'input_validation' ? $rule->getValue() : true; + } +} From 3a85549ac8c0d4c32cb5b8b0599c1e8384cea5b1 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Fri, 4 Sep 2015 18:17:20 +0300 Subject: [PATCH 23/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index d6a03a8ae6aa8..b926d8b45cfde 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -122,6 +122,9 @@ protected function saveCustomer(CustomerInterface $customer) { try { $this->_customerRepository->save($customer); + } catch (\Magento\Framework\Exception\InputException $e) { + $this->getMessageManager()->addError($this->getErrorWithCustomerId($e->getMessage())); + $this->logger->critical($e); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->getMessageManager()->addError($this->getErrorWithCustomerId($e->getMessage())); $this->logger->critical($e); From 63e5c557fb3b407e0ad9a1b575543abcbed982f0 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Fri, 4 Sep 2015 21:15:57 +0300 Subject: [PATCH 24/47] MAGETWO-40878: Password reset link does not expire when email address changed --- .../Api/AccountManagementInterface.php | 11 + .../Customer/Controller/Account/EditPost.php | 108 +- .../Customer/Model/AccountManagement.php | 20 + .../Unit/Controller/Account/EditPostTest.php | 951 ++++++++++++------ .../Test/Unit/Model/AccountManagementTest.php | 64 ++ 5 files changed, 833 insertions(+), 321 deletions(-) diff --git a/app/code/Magento/Customer/Api/AccountManagementInterface.php b/app/code/Magento/Customer/Api/AccountManagementInterface.php index afd19537fd4c3..6df298a22e9d3 100644 --- a/app/code/Magento/Customer/Api/AccountManagementInterface.php +++ b/app/code/Magento/Customer/Api/AccountManagementInterface.php @@ -133,6 +133,17 @@ public function changePassword($email, $currentPassword, $newPassword); */ public function changePasswordById($customerId, $currentPassword, $newPassword); + /** + * Change customer email. + * + * @api + * @param string $email + * @param string $newEmail + * @return bool true on success + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function changeEmail($email, $newEmail); + /** * Send an email to the customer with a password reset link. * diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index e56a0f5d5941e..3e5aa10842c1c 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -70,42 +70,28 @@ public function execute() /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultRedirectFactory->create(); if (!$this->formKeyValidator->validate($this->getRequest())) { - $resultRedirect->setPath('*/*/edit'); - return $resultRedirect; + return $resultRedirect->setPath('*/*/edit'); } if ($this->getRequest()->isPost()) { $customerId = $this->_getSession()->getCustomerId(); + $currentCustomer = $this->customerRepository->getById($customerId); + + // Prepare new customer data $customer = $this->customerExtractor->extract('customer_account_edit', $this->_request); $customer->setId($customerId); if ($customer->getAddresses() == null) { - $customer->setAddresses($this->customerRepository->getById($customerId)->getAddresses()); + $customer->setAddresses($currentCustomer->getAddresses()); } + // Change customer password if ($this->getRequest()->getParam('change_password')) { - $currPass = $this->getRequest()->getPost('current_password'); - $newPass = $this->getRequest()->getPost('password'); - $confPass = $this->getRequest()->getPost('password_confirmation'); - - if (strlen($newPass)) { - if ($newPass == $confPass) { - try { - $customerEmail = $this->customerRepository->getById($customerId)->getEmail(); - $this->customerAccountManagement->changePassword($customerEmail, $currPass, $newPass); - } catch (AuthenticationException $e) { - $this->messageManager->addError($e->getMessage()); - } catch (\Exception $e) { - $this->messageManager->addException( - $e, - __('Something went wrong while changing the password.') - ); - } - } else { - $this->messageManager->addError(__('Confirm your new password.')); - } - } else { - $this->messageManager->addError(__('Please enter new password.')); - } + $this->changeCustomerPassword($currentCustomer->getEmail()); + } + + // Change customer email + if ($currentCustomer->getEmail() !== $customer->getEmail()) { + $this->changeCustomerEmail($currentCustomer->getEmail(), $customer->getEmail()); } try { @@ -115,24 +101,74 @@ public function execute() } catch (InputException $e) { $this->messageManager->addException($e, __('Invalid input')); } catch (\Exception $e) { - $this->messageManager->addException( - $e, - __('We can\'t save the customer.') . $e->getMessage() . '
' . $e->getTraceAsString() . '
' - ); + $message = __('We can\'t save the customer.') + . $e->getMessage() + . '
' . $e->getTraceAsString() . '
'; + $this->messageManager->addException($e, $message); } if ($this->messageManager->getMessages()->getCount() > 0) { $this->_getSession()->setCustomerFormData($this->getRequest()->getPostValue()); - $resultRedirect->setPath('*/*/edit'); - return $resultRedirect; + return $resultRedirect->setPath('*/*/edit'); } $this->messageManager->addSuccess(__('You saved the account information.')); - $resultRedirect->setPath('customer/account'); - return $resultRedirect; + return $resultRedirect->setPath('customer/account'); + } + + return $resultRedirect->setPath('*/*/edit'); + } + + /** + * Change customer password + * + * @param string $email + * @return $this + */ + protected function changeCustomerPassword($email) + { + $currPass = $this->getRequest()->getPost('current_password'); + $newPass = $this->getRequest()->getPost('password'); + $confPass = $this->getRequest()->getPost('password_confirmation'); + + if (!strlen($newPass)) { + $this->messageManager->addError(__('Please enter new password.')); + return $this; + } + + if ($newPass !== $confPass) { + $this->messageManager->addError(__('Confirm your new password.')); + return $this; + } + + try { + $this->customerAccountManagement->changePassword($email, $currPass, $newPass); + } catch (AuthenticationException $e) { + $this->messageManager->addError($e->getMessage()); + } catch (\Exception $e) { + $this->messageManager->addException($e, __('Something went wrong while changing the password.')); + } + + return $this; + } + + /** + * Change customer email address + * + * @param string $email + * @param string $newEmail + * @return $this + */ + protected function changeCustomerEmail($email, $newEmail) + { + try { + $this->customerAccountManagement->changeEmail($email, $newEmail); + } catch (AuthenticationException $e) { + $this->messageManager->addError($e->getMessage()); + } catch (\Exception $e) { + $this->messageManager->addException($e, __('Something went wrong while changing the email.')); } - $resultRedirect->setPath('*/*/edit'); - return $resultRedirect; + return $this; } } diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 3f3a18d2b3cad..9d7b0d00ac7d2 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -609,6 +609,26 @@ public function changePasswordById($customerId, $currentPassword, $newPassword) return $this->changePasswordForCustomer($customer, $currentPassword, $newPassword); } + /** + * {@inheritdoc} + */ + public function changeEmail($email, $newEmail) + { + try { + $customer = $this->customerRepository->get($email); + } catch (NoSuchEntityException $e) { + throw new InvalidEmailOrPasswordException(__('Invalid login.')); + } + + $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId()); + $customerSecure->setRpToken(null); + $customerSecure->setRpTokenCreatedAt(null); + + $this->customerRepository->save($customer); + + return true; + } + /** * Change customer password. * diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php index 60cf3b1348f7d..e3909c15b0c52 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -3,408 +3,789 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Customer\Test\Unit\Controller\Account; +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Controller\Account\EditPost; +use Magento\Customer\Model\CustomerExtractor; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Request\Http; +use Magento\Framework\Controller\Result\Redirect; +use Magento\Framework\Controller\Result\RedirectFactory; +use Magento\Framework\Data\Form\FormKey\Validator; +use Magento\Framework\Message\Collection as MessageCollection; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\View\Result\PageFactory; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class EditPostTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var EditPost */ - protected $context; + protected $model; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var Context | \PHPUnit_Framework_MockObject_MockObject */ - protected $customerSession; + protected $context; /** - * @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject + * @var Session | \PHPUnit_Framework_MockObject_MockObject */ - protected $resultRedirectFactory; + protected $session; /** - * @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject + * @var PageFactory | \PHPUnit_Framework_MockObject_MockObject */ - protected $resultPageFactory; + protected $pageFactory; /** - * @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject + * @var AccountManagementInterface | \PHPUnit_Framework_MockObject_MockObject */ protected $customerAccountManagement; /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CustomerRepositoryInterface | \PHPUnit_Framework_MockObject_MockObject */ protected $customerRepository; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + * @var Validator | \PHPUnit_Framework_MockObject_MockObject */ - protected $formKeyValidator; + protected $validator; /** - * @var \Magento\Customer\Model\CustomerExtractor|\PHPUnit_Framework_MockObject_MockObject + * @var CustomerExtractor | \PHPUnit_Framework_MockObject_MockObject */ protected $customerExtractor; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var RedirectFactory | \PHPUnit_Framework_MockObject_MockObject */ - protected $redirectResultMock; + protected $resultRedirectFactory; /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + * @var Redirect | \PHPUnit_Framework_MockObject_MockObject */ - protected $response; + protected $resultRedirect; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var Http | \PHPUnit_Framework_MockObject_MockObject */ protected $request; /** - * @var \Magento\TestFramework\Helper\ObjectManager|\PHPUnit_Framework_MockObject_MockObject + * @var ManagerInterface | \PHPUnit_Framework_MockObject_MockObject */ - protected $objectManager; - - /** - * @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $customer; + protected $messageManager; /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var MessageCollection | \PHPUnit_Framework_MockObject_MockObject */ - protected $messageManager; + protected $messageCollection; - public function setUp() + protected function setUp() { - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $this->response = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false); - $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - - $this->messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false); - - $this->resultRedirectFactory = $this->getMock( - 'Magento\Framework\Controller\Result\RedirectFactory', - ['create'], - [], - '', - false - ); - - $this->context = $this->objectManager->getObject( - 'Magento\Framework\App\Action\Context', - [ - 'request' => $this->request, - 'response' => $this->response, - 'messageManager' => $this->messageManager, - 'resultRedirectFactory' => $this->resultRedirectFactory - ] - ); - - $this->redirectResultMock = $this->getMock('Magento\Framework\Controller\Result\Redirect', [], [], '', false); - $this->customerSession = $this->getMock('Magento\Customer\Model\Session', [], [], '', false); - $this->resultPageFactory = $this->getMock('Magento\Framework\View\Result\PageFactory', [], [], '', false); - $this->customerAccountManagement = $this->getMockForAbstractClass( - 'Magento\Customer\Api\AccountManagementInterface', - [], - '', - false - ); - $this->customerRepository = $this->getMockForAbstractClass( - 'Magento\Customer\Api\CustomerRepositoryInterface', - [], - '', - false - ); - $this->formKeyValidator = $this->getMock('Magento\Framework\Data\Form\FormKey\Validator', [], [], '', false); - $this->customerExtractor = $this->getMock('Magento\Customer\Model\CustomerExtractor', [], [], '', false); - $this->customer = $this->getMockForAbstractClass( - 'Magento\Customer\Api\Data\CustomerInterface', - [], - 'dataCustomer', - false + $this->prepareContext(); + + $this->session = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->setMethods([ + 'getCustomerId', + 'setCustomerFormData', + ]) + ->getMock(); + + $this->pageFactory = $this->getMockBuilder('Magento\Framework\View\Result\PageFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerAccountManagement = $this->getMockBuilder('Magento\Customer\Api\AccountManagementInterface') + ->getMockForAbstractClass(); + + $this->customerRepository = $this->getMockBuilder('Magento\Customer\Api\CustomerRepositoryInterface') + ->getMockForAbstractClass(); + + $this->validator = $this->getMockBuilder('Magento\Framework\Data\Form\FormKey\Validator') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerExtractor = $this->getMockBuilder('Magento\Customer\Model\CustomerExtractor') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new EditPost( + $this->context, + $this->session, + $this->pageFactory, + $this->customerAccountManagement, + $this->customerRepository, + $this->validator, + $this->customerExtractor ); } - /** - * @return \Magento\Customer\Controller\Account\EditPost - */ - public function getController() + public function testInvalidFormKey() { - return $this->objectManager->getObject( - 'Magento\Customer\Controller\Account\EditPost', - [ - 'context' => $this->context, - 'customerSession' => $this->customerSession, - 'resultRedirectFactory' => $this->resultRedirectFactory, - 'resultPageFactory' => $this->resultPageFactory, - 'customerAccountManagement' => $this->customerAccountManagement, - 'customerRepository' => $this->customerRepository, - 'formKeyValidator' => $this->formKeyValidator, - 'customerExtractor' => $this->customerExtractor - ] - ); + $this->validator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(false); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturnSelf(); + + $this->assertSame($this->resultRedirect, $this->model->execute()); } - public function testEditPostActionWithInvalidFormKey() + public function testNoPostValues() { - $this->resultRedirectFactory - ->expects($this->once()) - ->method('create') - ->willReturn($this->redirectResultMock); - $this->formKeyValidator - ->expects($this->once()) + $this->validator->expects($this->once()) ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->request->expects($this->once()) + ->method('isPost') ->willReturn(false); - $this->redirectResultMock - ->expects($this->once()) + + $this->resultRedirect->expects($this->once()) ->method('setPath') ->with('*/*/edit') - ->willReturn('http://test.com/customer/account/edit'); + ->willReturnSelf(); - $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + $this->assertSame($this->resultRedirect, $this->model->execute()); } - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function testEditPostActionWithAuthenticationExceptionWhenTryingChangePassword() + public function testGeneralSave() { - $customerId = 24; - $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false); - $loadedCustomer = $this->getMockForAbstractClass( - 'Magento\Customer\Api\Data\CustomerInterface', - [], - 'loadedCustomer', - false - ); + $customerId = 1; + $customerEmail = 'user1@example.com'; - $loadedCustomer - ->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address, $address]); + $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') + ->getMockForAbstractClass(); - $this->resultRedirectFactory - ->expects($this->once()) - ->method('create') - ->willReturn($this->redirectResultMock); - $this->formKeyValidator - ->expects($this->once()) + $this->validator->expects($this->once()) ->method('validate') + ->with($this->request) ->willReturn(true); - $this->request - ->expects($this->once()) + + $this->request->expects($this->once()) ->method('isPost') ->willReturn(true); + $this->request->expects($this->once()) + ->method('getParam') + ->with('change_password') + ->willReturn(false); - $this->customerSession - ->expects($this->once()) + $this->session->expects($this->once()) ->method('getCustomerId') ->willReturn($customerId); - $this->customerExtractor - ->expects($this->once()) + + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($currentCustomerMock); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($newCustomerMock) + ->willReturnSelf(); + + $this->customerExtractor->expects($this->once()) ->method('extract') - ->willReturn($this->customer); - $this->customer - ->expects($this->once()) + ->with('customer_account_edit', $this->request) + ->willReturn($newCustomerMock); + + $currentCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $currentCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $newCustomerMock->expects($this->once()) ->method('setId') - ->with($customerId); - $this->customer - ->expects($this->once()) + ->with($customerId) + ->willReturnSelf(); + $newCustomerMock->expects($this->once()) ->method('getAddresses') ->willReturn(null); - $this->customerRepository - ->expects($this->exactly(2)) - ->method('getById') - ->with($customerId) - ->willReturn($loadedCustomer); - $this->customer - ->expects($this->once()) + $newCustomerMock->expects($this->once()) ->method('setAddresses') - ->with([$address, $address]); - $this->request - ->expects($this->once()) + ->with([$address]) + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $this->messageManager->expects($this->once()) + ->method('getMessages') + ->willReturn($this->messageCollection); + $this->messageManager->expects($this->once()) + ->method('addSuccess') + ->with(__('You saved the account information.')) + ->willReturnSelf(); + + $this->messageCollection->expects($this->once()) + ->method('getCount') + ->willReturn(0); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('customer/account') + ->willReturnSelf(); + + $this->assertSame($this->resultRedirect, $this->model->execute()); + } + + /** + * @param string $currentPassword + * @param string $newPassword + * @param string $confirmationPassword + * @param [] $errors + * + * @dataProvider changePasswordDataProvider + */ + public function testChangePassword( + $currentPassword, + $newPassword, + $confirmationPassword, + $errors + ) { + $customerId = 1; + $customerEmail = 'user1@example.com'; + + $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + + $this->validator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->request->expects($this->once()) + ->method('isPost') + ->willReturn(true); + $this->request->expects($this->once()) ->method('getParam') ->with('change_password') ->willReturn(true); - - $this->request - ->expects($this->at(2)) - ->method('getPost') - ->with('current_password', null) - ->willReturn(123); - $this->request - ->expects($this->at(3)) - ->method('getPost') - ->with('password', null) - ->willReturn(321); - $this->request - ->expects($this->at(4)) + $this->request->expects($this->any()) + ->method('getPostValue') + ->willReturn(true); + $this->request->expects($this->exactly(3)) ->method('getPost') - ->with('password_confirmation', null) - ->willReturn(321); - - $this->customerAccountManagement - ->expects($this->once()) - ->method('changePassword') - ->willThrowException(new \Magento\Framework\Exception\AuthenticationException(__('Error'))); - $this->messageManager - ->expects($this->once()) - ->method('addError') - ->with('Error'); - - $exception = new \Magento\Framework\Exception\InputException(__('Error')); - $this->customerRepository - ->expects($this->once()) + ->willReturnMap([ + ['current_password', null, $currentPassword], + ['password', null, $newPassword], + ['password_confirmation', null, $confirmationPassword], + ]); + + $this->session->expects($this->once()) + ->method('getCustomerId') + ->willReturn($customerId); + + // Prepare errors processing + if (!empty($errors)) { + if (!empty($errors['exception'])) { + $exception = new $errors['exception'](__($errors['message'])); + + $this->customerAccountManagement->expects($this->once()) + ->method('changePassword') + ->with($customerEmail, $currentPassword, $newPassword) + ->willThrowException($exception); + + $this->messageManager->expects($this->any()) + ->method('addException') + ->with($exception, __('Something went wrong while changing the password.')) + ->willReturnSelf(); + } + + $this->session->expects($this->once()) + ->method('setCustomerFormData') + ->with(true) + ->willReturnSelf(); + + $this->messageManager->expects($this->any()) + ->method('addError') + ->with($errors['message']) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturnSelf(); + } else { + $this->customerAccountManagement->expects($this->once()) + ->method('changePassword') + ->with($customerEmail, $currentPassword, $newPassword) + ->willReturnSelf(); + + $this->messageManager->expects($this->once()) + ->method('addSuccess') + ->with(__('You saved the account information.')) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('customer/account') + ->willReturnSelf(); + } + + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($currentCustomerMock); + $this->customerRepository->expects($this->once()) ->method('save') - ->willThrowException($exception); - $this->messageManager - ->expects($this->once()) - ->method('addException') - ->with($exception, 'Invalid input'); - $this->request - ->expects($this->once()) - ->method('getPostValue') - ->willReturn([]); + ->with($newCustomerMock) + ->willReturnSelf(); - $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false); - $messageCollection - ->expects($this->once()) - ->method('getCount') - ->willReturn(3); - $this->messageManager - ->expects($this->once()) + $this->customerExtractor->expects($this->once()) + ->method('extract') + ->with('customer_account_edit', $this->request) + ->willReturn($newCustomerMock); + + $currentCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $currentCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($customerEmail); + + $newCustomerMock->expects($this->once()) + ->method('setId') + ->with($customerId) + ->willReturnSelf(); + $newCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('setAddresses') + ->with([$address]) + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $this->messageManager->expects($this->once()) ->method('getMessages') - ->willReturn($messageCollection); - $this->customerSession - ->expects($this->once()) - ->method('__call') - ->with('setCustomerFormData', [[]]); - - $this->redirectResultMock - ->expects($this->once()) - ->method('setPath') - ->with('*/*/edit') - ->willReturn('http://test.com/customer/account/edit'); + ->willReturn($this->messageCollection); - $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + $this->messageCollection->expects($this->once()) + ->method('getCount') + ->willReturn($errors); + + + $this->assertSame($this->resultRedirect, $this->model->execute()); } /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @return array */ - public function testEditPostActionWithoutErrors() + public function changePasswordDataProvider() { - $customerId = 24; - $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false); - $loadedCustomer = $this->getMockForAbstractClass( - 'Magento\Customer\Api\Data\CustomerInterface', - [], - 'loadedCustomer', - false - ); - - $loadedCustomer - ->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address, $address]); + return [ + [ + 'current_password' => '', + 'new_password' => '', + 'confirmation_password' => '', + 'errors' => [ + 'counter' => 1, + 'message' => __('Please enter new password.'), + ], + ], + [ + 'current_password' => '', + 'new_password' => 'user2@example.com', + 'confirmation_password' => 'user3@example.com', + 'errors' => [ + 'counter' => 1, + 'message' => __('Confirm your new password.'), + ], + ], + [ + 'current_password' => 'user1@example.com', + 'new_password' => 'user2@example.com', + 'confirmation_password' => 'user2@example.com', + 'errors' => [ + 'counter' => 0, + 'message' => '', + ], + ], + [ + 'current_password' => 'user1@example.com', + 'new_password' => 'user2@example.com', + 'confirmation_password' => 'user2@example.com', + 'errors' => [ + 'counter' => 1, + 'message' => 'AuthenticationException', + 'exception' => '\Magento\Framework\Exception\AuthenticationException', + ], + ], + [ + 'current_password' => 'user1@example.com', + 'new_password' => 'user2@example.com', + 'confirmation_password' => 'user2@example.com', + 'errors' => [ + 'counter' => 1, + 'message' => 'Exception', + 'exception' => '\Exception', + ], + ], + ]; + } - $this->resultRedirectFactory - ->expects($this->once()) - ->method('create') - ->willReturn($this->redirectResultMock); - $this->formKeyValidator - ->expects($this->once()) + /** + * @param string $currentEmail + * @param string $newEmail + * @param [] $errors + * + * @dataProvider changeEmailDataProvider + */ + public function testChangeEmail( + $currentEmail, + $newEmail, + $errors + ) { + $customerId = 1; + + $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + + $this->validator->expects($this->once()) ->method('validate') + ->with($this->request) ->willReturn(true); - $this->request - ->expects($this->once()) + + $this->request->expects($this->once()) ->method('isPost') ->willReturn(true); + $this->request->expects($this->once()) + ->method('getParam') + ->with('change_password') + ->willReturn(false); + $this->request->expects($this->any()) + ->method('getPostValue') + ->willReturn(true); - $this->customerSession - ->expects($this->once()) + $this->session->expects($this->once()) ->method('getCustomerId') ->willReturn($customerId); - $this->customerExtractor - ->expects($this->once()) + + // Prepare errors processing + if (!empty($errors)) { + if (!empty($errors['exception'])) { + $exception = new $errors['exception'](__($errors['message'])); + + $this->customerAccountManagement->expects($this->once()) + ->method('changeEmail') + ->with($currentEmail, $newEmail) + ->willThrowException($exception); + + $this->messageManager->expects($this->any()) + ->method('addException') + ->with($exception, __('Something went wrong while changing the email.')) + ->willReturnSelf(); + } + + $this->session->expects($this->once()) + ->method('setCustomerFormData') + ->with(true) + ->willReturnSelf(); + + $this->messageManager->expects($this->any()) + ->method('addError') + ->with($errors['message']) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturnSelf(); + } else { + $this->customerAccountManagement->expects($this->once()) + ->method('changeEmail') + ->with($currentEmail, $newEmail) + ->willReturnSelf(); + + $this->messageManager->expects($this->once()) + ->method('addSuccess') + ->with(__('You saved the account information.')) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('customer/account') + ->willReturnSelf(); + } + + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($currentCustomerMock); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($newCustomerMock) + ->willReturnSelf(); + + $this->customerExtractor->expects($this->once()) ->method('extract') - ->willReturn($this->customer); - $this->customer - ->expects($this->once()) + ->with('customer_account_edit', $this->request) + ->willReturn($newCustomerMock); + + $currentCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $currentCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($currentEmail); + + $newCustomerMock->expects($this->once()) ->method('setId') - ->with($customerId); - $this->customer - ->expects($this->once()) + ->with($customerId) + ->willReturnSelf(); + $newCustomerMock->expects($this->once()) ->method('getAddresses') ->willReturn(null); - $this->customerRepository - ->expects($this->exactly(2)) - ->method('getById') - ->with($customerId) - ->willReturn($loadedCustomer); - $this->customer - ->expects($this->once()) + $newCustomerMock->expects($this->once()) ->method('setAddresses') - ->with([$address, $address]); - $this->request - ->expects($this->once()) + ->with([$address]) + ->willReturn(null); + $newCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($newEmail); + + $this->messageManager->expects($this->once()) + ->method('getMessages') + ->willReturn($this->messageCollection); + + $this->messageCollection->expects($this->once()) + ->method('getCount') + ->willReturn($errors); + + + $this->assertSame($this->resultRedirect, $this->model->execute()); + } + + /** + * @return array + */ + public function changeEmailDataProvider() + { + return [ + [ + 'current_email' => 'user1@example.com', + 'new_email' => 'user2@example.com', + 'errors' => [ + 'counter' => 0, + 'message' => '', + ], + ], + [ + 'current_email' => 'user1@example.com', + 'new_email' => 'user2@example.com', + 'errors' => [ + 'counter' => 1, + 'message' => 'AuthenticationException', + 'exception' => '\Magento\Framework\Exception\AuthenticationException', + ], + ], + [ + 'current_email' => 'user1@example.com', + 'new_email' => 'user2@example.com', + 'errors' => [ + 'counter' => 1, + 'message' => 'Exception', + 'exception' => '\Exception', + ], + ], + ]; + } + + /** + * @param int $counter + * @param string $message + * @param string $exception + * + * @dataProvider exceptionDataProvider + */ + public function testGeneralException( + $counter, + $message, + $exception + ) { + $customerId = 1; + $customerEmail = 'user1@example.com'; + + $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + + $exception = new $exception(__($message)); + + $this->validator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->request->expects($this->once()) + ->method('isPost') + ->willReturn(true); + $this->request->expects($this->once()) ->method('getParam') ->with('change_password') + ->willReturn(false); + $this->request->expects($this->any()) + ->method('getPostValue') ->willReturn(true); - $this->request - ->expects($this->at(2)) - ->method('getPost') - ->with('current_password', null) - ->willReturn(123); - $this->request - ->expects($this->at(3)) - ->method('getPost') - ->with('password', null) - ->willReturn(321); - $this->request - ->expects($this->at(4)) - ->method('getPost') - ->with('password_confirmation', null) - ->willReturn(321); + $this->session->expects($this->once()) + ->method('getCustomerId') + ->willReturn($customerId); + $this->session->expects($this->once()) + ->method('setCustomerFormData') + ->with(true) + ->willReturnSelf(); + + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($currentCustomerMock); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($newCustomerMock) + ->willThrowException($exception); - $this->customerAccountManagement - ->expects($this->once()) - ->method('changePassword'); + $this->customerExtractor->expects($this->once()) + ->method('extract') + ->with('customer_account_edit', $this->request) + ->willReturn($newCustomerMock); - $this->customerRepository - ->expects($this->once()) - ->method('save'); + $currentCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $currentCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); - $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false); - $messageCollection - ->expects($this->once()) - ->method('getCount') - ->willReturn(0); - $this->messageManager - ->expects($this->once()) + $newCustomerMock->expects($this->once()) + ->method('setId') + ->with($customerId) + ->willReturnSelf(); + $newCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('setAddresses') + ->with([$address]) + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $this->messageManager->expects($this->once()) ->method('getMessages') - ->willReturn($messageCollection); + ->willReturn($this->messageCollection); - $this->messageManager - ->expects($this->once()) - ->method('addSuccess') - ->with('You saved the account information.'); + $this->messageCollection->expects($this->once()) + ->method('getCount') + ->willReturn($counter); - $this->redirectResultMock - ->expects($this->once()) + $this->resultRedirect->expects($this->once()) ->method('setPath') - ->with('customer/account') - ->willReturn('http://test.com/customer/account/edit'); + ->with('*/*/edit') + ->willReturnSelf(); - $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + $this->assertSame($this->resultRedirect, $this->model->execute()); + } + + /** + * @return array + */ + public function exceptionDataProvider() + { + return [ + [ + 'counter' => 1, + 'message' => 'AuthenticationException', + 'exception' => '\Magento\Framework\Exception\AuthenticationException', + ], + [ + 'counter' => 1, + 'message' => 'InputException', + 'exception' => '\Magento\Framework\Exception\InputException', + ], + [ + 'counter' => 1, + 'message' => 'Exception', + 'exception' => '\Exception', + ], + ]; + } + + protected function prepareContext() + { + $this->context = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultRedirectFactory = $this->getMockBuilder('Magento\Framework\Controller\Result\RedirectFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http') + ->disableOriginalConstructor() + ->getMock(); + + $this->messageManager = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface') + ->getMockForAbstractClass(); + + $this->messageCollection = $this->getMockBuilder('Magento\Framework\Message\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $this->context->expects($this->any()) + ->method('getResultRedirectFactory') + ->willReturn($this->resultRedirectFactory); + + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->request); + + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManager); + + $this->resultRedirectFactory->expects($this->any()) + ->method('create') + ->willReturn($this->resultRedirect); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index b33d35c8f4c14..7009a4609f862 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -7,6 +7,7 @@ use Magento\Customer\Model\AccountManagement; use Magento\Framework\App\Area; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Store\Model\ScopeInterface; @@ -1170,4 +1171,67 @@ private function reInitModel() ] ); } + + public function testChangeEmail() + { + $currentEmail = 'user1@example.com'; + $newEmail = 'user1@example.com'; + $customerId = 1; + + $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + $customerSecureMock = $this->getMockBuilder('Magento\Customer\Model\Data\CustomerSecure') + ->disableOriginalConstructor() + ->setMethods([ + 'setRpToken', + 'setRpTokenCreatedAt', + ]) + ->getMock(); + + $customerMock->expects($this->once()) + ->method('getId') + ->willReturn($customerId); + + $customerSecureMock->expects($this->once()) + ->method('setRpToken') + ->with(null) + ->willReturnSelf(); + $customerSecureMock->expects($this->once()) + ->method('setRpTokenCreatedAt') + ->with(null) + ->willReturnSelf(); + + $this->customerRepository->expects($this->once()) + ->method('get') + ->with($currentEmail) + ->willReturn($customerMock); + $this->customerRepository->expects($this->once()) + ->method('save') + ->with($customerMock) + ->willReturnSelf(); + + $this->customerRegistry->expects($this->once()) + ->method('retrieveSecureData') + ->with($customerId) + ->willReturn($customerSecureMock); + + $this->assertTrue($this->accountManagement->changeEmail($currentEmail, $newEmail)); + } + + /** + * @expectedException \Magento\Framework\Exception\InvalidEmailOrPasswordException + * @expectedExceptionMessage Invalid login + */ + public function testChangeException() + { + $currentEmail = 'user1@example.com'; + $newEmail = 'user1@example.com'; + + $this->customerRepository->expects($this->once()) + ->method('get') + ->with($currentEmail) + ->willThrowException(new NoSuchEntityException(__('NoSuchEntityException'))); + + $this->accountManagement->changeEmail($currentEmail, $newEmail); + } } From 3a3fd26b92e3f2854dd850e7feb65acc2f60f1b5 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Fri, 4 Sep 2015 21:55:39 +0300 Subject: [PATCH 25/47] MAGETWO-40878: Password reset link does not expire when email address changed --- .../Unit/Controller/Account/EditPostTest.php | 321 +++++++++--------- 1 file changed, 160 insertions(+), 161 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php index e3909c15b0c52..ae29ecddb0b6c 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -169,13 +169,19 @@ public function testGeneralSave() $customerId = 1; $customerEmail = 'user1@example.com'; - $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); - $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); + $currentCustomerMock = $this->getCurrentCustomerMock($address); + $currentCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + $this->validator->expects($this->once()) ->method('validate') ->with($this->request) @@ -207,28 +213,6 @@ public function testGeneralSave() ->with('customer_account_edit', $this->request) ->willReturn($newCustomerMock); - $currentCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $currentCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - - $newCustomerMock->expects($this->once()) - ->method('setId') - ->with($customerId) - ->willReturnSelf(); - $newCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('setAddresses') - ->with([$address]) - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $this->messageManager->expects($this->once()) ->method('getMessages') ->willReturn($this->messageCollection); @@ -266,13 +250,19 @@ public function testChangePassword( $customerId = 1; $customerEmail = 'user1@example.com'; - $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); - $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); + $currentCustomerMock = $this->getCurrentCustomerMock($address); + $currentCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($customerEmail); + + $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + $this->validator->expects($this->once()) ->method('validate') ->with($this->request) @@ -302,34 +292,7 @@ public function testChangePassword( // Prepare errors processing if (!empty($errors)) { - if (!empty($errors['exception'])) { - $exception = new $errors['exception'](__($errors['message'])); - - $this->customerAccountManagement->expects($this->once()) - ->method('changePassword') - ->with($customerEmail, $currentPassword, $newPassword) - ->willThrowException($exception); - - $this->messageManager->expects($this->any()) - ->method('addException') - ->with($exception, __('Something went wrong while changing the password.')) - ->willReturnSelf(); - } - - $this->session->expects($this->once()) - ->method('setCustomerFormData') - ->with(true) - ->willReturnSelf(); - - $this->messageManager->expects($this->any()) - ->method('addError') - ->with($errors['message']) - ->willReturnSelf(); - - $this->resultRedirect->expects($this->once()) - ->method('setPath') - ->with('*/*/edit') - ->willReturnSelf(); + $this->mockChangePasswordErrors($currentPassword, $newPassword, $errors, $customerEmail); } else { $this->customerAccountManagement->expects($this->once()) ->method('changePassword') @@ -361,28 +324,6 @@ public function testChangePassword( ->with('customer_account_edit', $this->request) ->willReturn($newCustomerMock); - $currentCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $currentCustomerMock->expects($this->exactly(2)) - ->method('getEmail') - ->willReturn($customerEmail); - - $newCustomerMock->expects($this->once()) - ->method('setId') - ->with($customerId) - ->willReturnSelf(); - $newCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('setAddresses') - ->with([$address]) - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $this->messageManager->expects($this->once()) ->method('getMessages') ->willReturn($this->messageCollection); @@ -465,13 +406,19 @@ public function testChangeEmail( ) { $customerId = 1; - $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); - $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); + $currentCustomerMock = $this->getCurrentCustomerMock($address); + $currentCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($currentEmail); + + $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $newCustomerMock->expects($this->exactly(2)) + ->method('getEmail') + ->willReturn($newEmail); + $this->validator->expects($this->once()) ->method('validate') ->with($this->request) @@ -494,34 +441,7 @@ public function testChangeEmail( // Prepare errors processing if (!empty($errors)) { - if (!empty($errors['exception'])) { - $exception = new $errors['exception'](__($errors['message'])); - - $this->customerAccountManagement->expects($this->once()) - ->method('changeEmail') - ->with($currentEmail, $newEmail) - ->willThrowException($exception); - - $this->messageManager->expects($this->any()) - ->method('addException') - ->with($exception, __('Something went wrong while changing the email.')) - ->willReturnSelf(); - } - - $this->session->expects($this->once()) - ->method('setCustomerFormData') - ->with(true) - ->willReturnSelf(); - - $this->messageManager->expects($this->any()) - ->method('addError') - ->with($errors['message']) - ->willReturnSelf(); - - $this->resultRedirect->expects($this->once()) - ->method('setPath') - ->with('*/*/edit') - ->willReturnSelf(); + $this->mockChangeEmailErrors($currentEmail, $newEmail, $errors); } else { $this->customerAccountManagement->expects($this->once()) ->method('changeEmail') @@ -553,28 +473,6 @@ public function testChangeEmail( ->with('customer_account_edit', $this->request) ->willReturn($newCustomerMock); - $currentCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $currentCustomerMock->expects($this->exactly(2)) - ->method('getEmail') - ->willReturn($currentEmail); - - $newCustomerMock->expects($this->once()) - ->method('setId') - ->with($customerId) - ->willReturnSelf(); - $newCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('setAddresses') - ->with([$address]) - ->willReturn(null); - $newCustomerMock->expects($this->exactly(2)) - ->method('getEmail') - ->willReturn($newEmail); - $this->messageManager->expects($this->once()) ->method('getMessages') ->willReturn($this->messageCollection); @@ -583,7 +481,6 @@ public function testChangeEmail( ->method('getCount') ->willReturn($errors); - $this->assertSame($this->resultRedirect, $this->model->execute()); } @@ -637,13 +534,19 @@ public function testGeneralException( $customerId = 1; $customerEmail = 'user1@example.com'; - $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); - $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); + $currentCustomerMock = $this->getCurrentCustomerMock($address); + $currentCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + + $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $newCustomerMock->expects($this->once()) + ->method('getEmail') + ->willReturn($customerEmail); + $exception = new $exception(__($message)); $this->validator->expects($this->once()) @@ -684,28 +587,6 @@ public function testGeneralException( ->with('customer_account_edit', $this->request) ->willReturn($newCustomerMock); - $currentCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $currentCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - - $newCustomerMock->expects($this->once()) - ->method('setId') - ->with($customerId) - ->willReturnSelf(); - $newCustomerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('setAddresses') - ->with([$address]) - ->willReturn(null); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $this->messageManager->expects($this->once()) ->method('getMessages') ->willReturn($this->messageCollection); @@ -788,4 +669,122 @@ protected function prepareContext() ->method('create') ->willReturn($this->resultRedirect); } + + /** + * @param int $customerId + * @param \PHPUnit_Framework_MockObject_MockObject $address + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getNewCustomerMock($customerId, $address) + { + $newCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + + $newCustomerMock->expects($this->once()) + ->method('setId') + ->with($customerId) + ->willReturnSelf(); + $newCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn(null); + $newCustomerMock->expects($this->once()) + ->method('setAddresses') + ->with([$address]) + ->willReturn(null); + + return $newCustomerMock; + } + + /** + * @param \PHPUnit_Framework_MockObject_MockObject $address + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getCurrentCustomerMock($address) + { + $currentCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + + $currentCustomerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + + return $currentCustomerMock; + } + + /** + * @param string $currentEmail + * @param string $newEmail + * @param [] $errors + * @return void + */ + protected function mockChangeEmailErrors($currentEmail, $newEmail, $errors) + { + if (!empty($errors['exception'])) { + $exception = new $errors['exception'](__($errors['message'])); + + $this->customerAccountManagement->expects($this->once()) + ->method('changeEmail') + ->with($currentEmail, $newEmail) + ->willThrowException($exception); + + $this->messageManager->expects($this->any()) + ->method('addException') + ->with($exception, __('Something went wrong while changing the email.')) + ->willReturnSelf(); + } + + $this->session->expects($this->once()) + ->method('setCustomerFormData') + ->with(true) + ->willReturnSelf(); + + $this->messageManager->expects($this->any()) + ->method('addError') + ->with($errors['message']) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturnSelf(); + } + + /** + * @param string $currentPassword + * @param string $newPassword + * @param [] $errors + * @param string $customerEmail + * @return void + */ + protected function mockChangePasswordErrors($currentPassword, $newPassword, $errors, $customerEmail) + { + if (!empty($errors['exception'])) { + $exception = new $errors['exception'](__($errors['message'])); + + $this->customerAccountManagement->expects($this->once()) + ->method('changePassword') + ->with($customerEmail, $currentPassword, $newPassword) + ->willThrowException($exception); + + $this->messageManager->expects($this->any()) + ->method('addException') + ->with($exception, __('Something went wrong while changing the password.')) + ->willReturnSelf(); + } + + $this->session->expects($this->once()) + ->method('setCustomerFormData') + ->with(true) + ->willReturnSelf(); + + $this->messageManager->expects($this->any()) + ->method('addError') + ->with($errors['message']) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturnSelf(); + } } From 6c89b362c2124dece530b4e496f0e63145af4e14 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 12:44:47 +0300 Subject: [PATCH 26/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Grid/Column/InlineEditUpdaterTest.php | 77 +++++++++++++++++++ .../Grid/Column/ValidationRulesTest.php | 67 ++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php create mode 100644 app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php diff --git a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php b/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php new file mode 100644 index 0000000000000..39903d3f0876a --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php @@ -0,0 +1,77 @@ +validationRules = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\ValidationRules') + ->disableOriginalConstructor() + ->getMock(); + + $this->validationRule = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->column = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->component = new InlineEditUpdater($this->validationRules); + } + + public function testApplyEditing() + { + $this->column->expects($this->once()) + ->method('getConfiguration') + ->willReturn([ + 'dataType' => 'text', + 'visible' => true, + ]); + $this->validationRules->expects($this->once()) + ->method('getValidationRules') + ->with(true, [$this->validationRule]) + ->willReturn([ + 'validate-email' => true, + 'required-entry' => true + ]); + $this->column->expects($this->once()) + ->method('setData') + ->with( + 'config', + [ + 'dataType' => 'text', + 'visible' => true, + 'editor' => [ + 'editorType' => 'text', + 'validation' => [ + 'validate-email' => true, + 'required-entry' => true, + ] + ] + ] + ); + + $this->component->applyEditing($this->column, 'text', [$this->validationRule], true); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php b/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php new file mode 100644 index 0000000000000..69f7041181cc9 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php @@ -0,0 +1,67 @@ +validationRules = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\ValidationRules') + ->disableOriginalConstructor() + ->getMock(); + + $this->validationRule = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->validationRules = new ValidationRules(); + } + + public function testGetValidationRules() + { + $expectsRules = [ + 'required-entry' => true, + 'validate-number' => true, + ]; + $this->validationRule->expects($this->atLeastOnce()) + ->method('getName') + ->willReturn('input_validation'); + $this->validationRule->expects($this->atLeastOnce()) + ->method('getValue') + ->willReturn('numeric'); + + $this->assertEquals( + $expectsRules, + $this->validationRules->getValidationRules( + true, + [ + $this->validationRule, + new \Magento\Framework\DataObject(), + ] + ) + ); + } + + public function testGetValidationRulesWithOnlyRequiredRule() + { + $expectsRules = [ + 'required-entry' => true, + ]; + $this->assertEquals( + $expectsRules, + $this->validationRules->getValidationRules(true, []) + ); + } +} From b7fcbecac5f248497574b6cdfa1c795722a08c64 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 13:37:39 +0300 Subject: [PATCH 27/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php index f820b44f118b3..e806e30201346 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index; +/** + * @SuppressWarnings(PHPMD.TooManyFields) + */ class InlineEditTest extends \PHPUnit_Framework_TestCase { /** @var \Magento\Customer\Controller\Adminhtml\Index\InlineEdit */ From 0cabd83bacebe093625f163629e6e3ac8db6a0f0 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 13:56:50 +0300 Subject: [PATCH 28/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Unit/Ui/Component/ColumnFactoryTest.php | 19 +++++++++++---- .../Listing/AttributeRepositoryTest.php | 9 +++++++ .../Unit/Ui/Component/Listing/ColumnsTest.php | 24 +++++++++++++++++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php index ff5f5ad7e8ffe..f9c591734b5ed 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php @@ -24,6 +24,9 @@ class ColumnFactoryTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $column; + /** @var \Magento\Ui\Component\Grid\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ + protected $inlineEditUpdater; + /** @var ColumnFactory */ protected $columnFactory; @@ -61,7 +64,11 @@ public function setUp() false ); - $this->columnFactory = new ColumnFactory($this->componentFactory); + $this->inlineEditUpdater = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\InlineEditUpdater') + ->disableOriginalConstructor() + ->getMock(); + + $this->columnFactory = new ColumnFactory($this->componentFactory, $this->inlineEditUpdater); } public function testCreate() @@ -75,7 +82,6 @@ public function testCreate() 'config' => [ 'label' => __('Label'), 'dataType' => 'text', - 'editor' => 'text', 'align' => 'left', 'visible' => true, 'options' => [ @@ -90,7 +96,7 @@ public function testCreate() ]; $attributeData = [ 'attribute_code' => 'billing_attribute_code', - 'frontend_input' => 'frontend-input', + 'frontend_input' => 'text', 'frontend_label' => 'Label', 'backend_type' => 'backend-type', 'options' => [ @@ -103,8 +109,13 @@ public function testCreate() 'is_visible_in_grid' => true, 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => true, + 'entity_type_code' => 'customer', + 'validation_rules' => [], + 'required' => false, ]; - + $this->inlineEditUpdater->expects($this->once()) + ->method('applyEditing') + ->with($this->column, 'text', []); $this->componentFactory->expects($this->once()) ->method('create') ->with($columnName, 'column', $config) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php index fcd5ff19400e9..8443aac4204c1 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php @@ -118,6 +118,12 @@ public function testGetList() $this->attribute->expects($this->once()) ->method('getIsVisibleInGrid') ->willReturn(true); + $this->attribute->expects($this->once()) + ->method('getValidationRules') + ->willReturn([]); + $this->attribute->expects($this->once()) + ->method('isRequired') + ->willReturn(false); $this->option->expects($this->once()) ->method('getLabel') ->willReturn('Label'); @@ -145,6 +151,9 @@ public function testGetList() 'is_visible_in_grid' => true, 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => true, + 'validation_rules' => [], + 'required'=> false, + 'entity_type_code' => 'customer_address', ] ], $this->component->getList() diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php index 357c209026351..adf9ac4136705 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php @@ -24,6 +24,9 @@ class ColumnsTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $column; + /** @var \Magento\Ui\Component\Grid\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ + protected $inlineEditUpdater; + /** @var Columns */ protected $component; @@ -63,10 +66,15 @@ public function setUp() false ); + $this->inlineEditUpdater = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\InlineEditUpdater') + ->disableOriginalConstructor() + ->getMock(); + $this->component = new Columns( $this->context, $this->columnFactory, - $this->attributeRepository + $this->attributeRepository, + $this->inlineEditUpdater ); } @@ -93,6 +101,9 @@ public function testPrepareWithAddColumn() 'is_visible_in_grid' => true, 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => true, + 'validation_rules' => [], + 'required'=> false, + 'entity_type_code' => 'customer_address', ] ] ); @@ -111,7 +122,7 @@ public function testPrepareWithUpdateColumn() $backendType = 'backend-type'; $attributeData = [ 'attribute_code' => 'billing_attribute_code', - 'frontend_input' => 'frontend-input', + 'frontend_input' => 'text', 'frontend_label' => 'frontend-label', 'backend_type' => 'backend-type', 'options' => [ @@ -124,7 +135,13 @@ public function testPrepareWithUpdateColumn() 'is_visible_in_grid' => true, 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => true, + 'validation_rules' => [], + 'required'=> false, + 'entity_type_code' => 'customer', ]; + $this->inlineEditUpdater->expects($this->once()) + ->method('applyEditing') + ->with($this->column, 'text', [], false); $this->attributeRepository->expects($this->atLeastOnce()) ->method('getList') @@ -185,6 +202,9 @@ public function testPrepareWithUpdateStaticColumn() 'is_visible_in_grid' => true, 'is_filterable_in_grid' => true, 'is_searchable_in_grid' => true, + 'validation_rules' => [], + 'required'=> false, + 'entity_type_code' => 'customer_address', ]; $this->attributeRepository->expects($this->atLeastOnce()) From 1e2f2cc781bc291da3228384075212b4a984f8c8 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 14:00:58 +0300 Subject: [PATCH 29/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Magento/Ui/Component/Grid/Column/InlineEditUpdater.php | 6 ++++-- .../Magento/Ui/Component/Grid/Column/ValidationRules.php | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php b/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php index 99dd7f4f14515..f9641155e4b50 100644 --- a/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php +++ b/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php @@ -27,7 +27,9 @@ class InlineEditUpdater /** * @param ValidationRules $validationRules */ - public function __construct(ValidationRules $validationRules) { + public function __construct( + ValidationRules $validationRules + ) { $this->validationRules = $validationRules; } @@ -35,7 +37,7 @@ public function __construct(ValidationRules $validationRules) { * Add editor config * * @param UiComponentInterface $column - * @param $frontendInput + * @param string $frontendInput * @param array $validationRules * @param bool|false $isRequired * @return UiComponentInterface diff --git a/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php b/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php index c9a2679eebfec..583b6a7b61189 100644 --- a/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php +++ b/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php @@ -21,8 +21,8 @@ class ValidationRules ]; /** - * @param $isRequired - * @param $validationRules + * @param boolean $isRequired + * @param array $validationRules * @return array */ public function getValidationRules($isRequired, $validationRules) From b9f89945f2dc16f922eee4de14448e359b585031 Mon Sep 17 00:00:00 2001 From: Maxim Medinskiy Date: Mon, 7 Sep 2015 15:42:07 +0300 Subject: [PATCH 30/47] MAGETWO-40745: Failing Integration tests in Code Coverage build - Magento\Customer\Controller\Adminhtml\IndexTest --- .../Adminhtml/Index/MassAssignGroupTest.php | 85 +++++++++ .../Adminhtml/Index/MassDeleteTest.php | 62 +++++++ .../Adminhtml/Index/MassSubscribeTest.php | 82 +++++++++ .../Controller/Adminhtml/IndexTest.php | 161 ------------------ 4 files changed, 229 insertions(+), 161 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php new file mode 100644 index 0000000000000..b4bebab4c1fdd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php @@ -0,0 +1,85 @@ +customerRepository = Bootstrap::getObjectManager()->get( + 'Magento\Customer\Api\CustomerRepositoryInterface' + ); + } + + protected function tearDown() + { + /** + * Unset customer data + */ + Bootstrap::getObjectManager()->get('Magento\Backend\Model\Session')->setCustomerData(null); + + /** + * Unset messages + */ + Bootstrap::getObjectManager()->get('Magento\Backend\Model\Session')->getMessages(true); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + */ + public function testMassAssignGroupAction() + { + $customer = $this->customerRepository->getById(1); + $this->assertEquals(1, $customer->getGroupId()); + + $this->getRequest() + ->setParam('group', 0) + ->setPostValue('namespace', 'customer_listing') + ->setPostValue('selected', [1]); + $this->dispatch('backend/customer/index/massAssignGroup'); + $this->assertSessionMessages( + $this->equalTo(['A total of 1 record(s) were updated.']), + \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS + ); + $this->assertRedirect($this->stringStartsWith($this->baseControllerUrl)); + + $customer = $this->customerRepository->getById(1); + $this->assertEquals(0, $customer->getGroupId()); + } + + /** + * Valid group Id but no customer Ids specified + * @magentoDbIsolation enabled + */ + public function testMassAssignGroupActionNoCustomerIds() + { + $this->getRequest()->setParam('group', 0)->setPostValue('namespace', 'customer_listing'); + $this->dispatch('backend/customer/index/massAssignGroup'); + $this->assertSessionMessages( + $this->equalTo(['Please select item(s).']), + \Magento\Framework\Message\MessageInterface::TYPE_ERROR + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php new file mode 100644 index 0000000000000..3b4aba93fa5da --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php @@ -0,0 +1,62 @@ +get('Magento\Backend\Model\Session')->setCustomerData(null); + + /** + * Unset messages + */ + Bootstrap::getObjectManager()->get('Magento\Backend\Model\Session')->getMessages(true); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + */ + public function testMassDeleteAction() + { + $this->getRequest()->setPostValue('selected', [1])->setPostValue('namespace', 'customer_listing'); + $this->dispatch('backend/customer/index/massDelete'); + $this->assertSessionMessages( + $this->equalTo(['A total of 1 record(s) were deleted.']), + \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS + ); + $this->assertRedirect($this->stringStartsWith($this->baseControllerUrl)); + } + + /** + * Valid group Id but no customer Ids specified + * @magentoDbIsolation enabled + */ + public function testMassDeleteActionNoCustomerIds() + { + $this->getRequest()->setPostValue('namespace', 'customer_listing'); + $this->dispatch('backend/customer/index/massDelete'); + $this->assertSessionMessages( + $this->equalTo(['Please select item(s).']), + \Magento\Framework\Message\MessageInterface::TYPE_ERROR + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php new file mode 100644 index 0000000000000..93331ad9e22c4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php @@ -0,0 +1,82 @@ +get('Magento\Backend\Model\Session')->setCustomerData(null); + + /** + * Unset messages + */ + Bootstrap::getObjectManager()->get('Magento\Backend\Model\Session')->getMessages(true); + } + + /** + * @magentoDataFixture Magento/Customer/_files/two_customers.php + */ + public function testMassSubscriberAction() + { + // Pre-condition + /** @var \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory */ + $subscriberFactory = Bootstrap::getObjectManager()->get('Magento\Newsletter\Model\SubscriberFactory'); + $this->assertNull($subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus()); + $this->assertNull($subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus()); + // Setup + $this->getRequest()->setPostValue('selected', [1, 2])->setPostValue('namespace', 'customer_listing'); + + // Test + $this->dispatch('backend/customer/index/massSubscribe'); + + // Assertions + $this->assertRedirect($this->stringStartsWith($this->baseControllerUrl)); + $this->assertSessionMessages( + $this->equalTo(['A total of 2 record(s) were updated.']), + \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS + ); + $this->assertEquals( + Subscriber::STATUS_SUBSCRIBED, + $subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus() + ); + $this->assertEquals( + Subscriber::STATUS_SUBSCRIBED, + $subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus() + ); + } + + /** + * @magentoDbIsolation enabled + */ + public function testMassSubscriberActionNoSelection() + { + $this->getRequest()->setPostValue('namespace', 'customer_listing'); + $this->dispatch('backend/customer/index/massSubscribe'); + + $this->assertRedirect($this->stringStartsWith($this->baseControllerUrl)); + $this->assertSessionMessages( + $this->equalTo(['Please select item(s).']), + \Magento\Framework\Message\MessageInterface::TYPE_ERROR + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php index 670a2eea07170..41cda6cd89487 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php @@ -543,167 +543,6 @@ public function testProductReviewsAction() $this->assertContains('
get('Magento\Newsletter\Model\SubscriberFactory'); - $this->assertNull($subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus()); - $this->assertNull($subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus()); - // Setup - $this->getRequest()->setPostValue('selected', [1, 2])->setPostValue('namespace', 'customer_listing'); - - // Test - $this->dispatch('backend/customer/index/massSubscribe'); - - // Assertions - $this->assertRedirect($this->stringContains('customer/index')); - $this->assertSessionMessages( - $this->equalTo(['A total of 2 record(s) were updated.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - $this->assertEquals( - Subscriber::STATUS_SUBSCRIBED, - $subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus() - ); - $this->assertEquals( - Subscriber::STATUS_SUBSCRIBED, - $subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus() - ); - } - - /** - * @magentoDbIsolation enabled - */ - public function testMassSubscriberActionNoSelection() - { - $this->getRequest()->setPostValue('namespace', 'customer_listing'); - $this->dispatch('backend/customer/index/massSubscribe'); - - $this->assertRedirect($this->stringContains('customer/index')); - $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), - \Magento\Framework\Message\MessageInterface::TYPE_ERROR - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testMassDeleteAction() - { - $this->getRequest()->setPostValue('selected', [1])->setPostValue('namespace', 'customer_listing'); - $this->dispatch('backend/customer/index/massDelete'); - $this->assertSessionMessages( - $this->equalTo(['A total of 1 record(s) were deleted.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - $this->assertRedirect($this->stringContains('customer/index')); - } - - /** - * Valid group Id but no customer Ids specified - * @magentoDbIsolation enabled - */ - public function testMassDeleteActionNoCustomerIds() - { - $this->getRequest()->setPostValue('namespace', 'customer_listing'); - $this->dispatch('backend/customer/index/massDelete'); - $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), - \Magento\Framework\Message\MessageInterface::TYPE_ERROR - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testMassAssignGroupAction() - { - $customer = $this->customerRepository->getById(1); - $this->assertEquals(1, $customer->getGroupId()); - - $this->getRequest() - ->setParam('group', 0) - ->setPostValue('namespace', 'customer_listing') - ->setPostValue('selected', [1]); - $this->dispatch('backend/customer/index/massAssignGroup'); - $this->assertSessionMessages( - $this->equalTo(['A total of 1 record(s) were updated.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - $this->assertRedirect($this->stringContains('customer/index')); - - $customer = $this->customerRepository->getById(1); - $this->assertEquals(0, $customer->getGroupId()); - } - - /** - * Valid group Id but no customer Ids specified - * @magentoDbIsolation enabled - */ - public function testMassAssignGroupActionNoCustomerIds() - { - $this->getRequest()->setParam('group', 0)->setPostValue('namespace', 'customer_listing'); - $this->dispatch('backend/customer/index/massAssignGroup'); - $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), - \Magento\Framework\Message\MessageInterface::TYPE_ERROR - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/two_customers.php - */ - public function testMassUnsubscriberAction() - { - // Setup - /** @var \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory */ - $subscriberFactory = Bootstrap::getObjectManager()->get('Magento\Newsletter\Model\SubscriberFactory'); - $subscriberFactory->create()->subscribeCustomerById(1); - $subscriberFactory->create()->subscribeCustomerById(2); - $this->getRequest()->setPostValue('selected', [1, 2])->setPostValue('namespace', 'customer_listing'); - - // Ensure secret key is disabled (subscription status notification emails turn it off) - $this->_objectManager->get('Magento\Backend\Model\UrlInterface')->turnOffSecretKey(); - - // Test - $this->dispatch('backend/customer/index/massUnsubscribe'); - - // Assertions - $this->assertRedirect($this->stringContains('customer/index')); - $this->assertSessionMessages( - $this->equalTo(['A total of 2 record(s) were updated.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - $this->assertEquals( - Subscriber::STATUS_UNSUBSCRIBED, - $subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus() - ); - $this->assertEquals( - Subscriber::STATUS_UNSUBSCRIBED, - $subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus() - ); - } - - /** - * @magentoDbIsolation enabled - */ - public function testMassUnsubscriberActionNoSelection() - { - $this->getRequest()->setPostValue('namespace', 'customer_listing'); - $this->dispatch('backend/customer/index/massUnsubscribe'); - - $this->assertRedirect($this->stringContains('customer/index')); - $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), - \Magento\Framework\Message\MessageInterface::TYPE_ERROR - ); - } - /** * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/Customer/_files/customer_address.php From 2ddce418fda8effd9ba2c454792b13bed97c05a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 15:42:49 +0300 Subject: [PATCH 31/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Component/Listing}/Column/InlineEditUpdaterTest.php | 8 ++++---- .../Ui/Component/Listing}/Column/ValidationRulesTest.php | 6 +++--- app/code/Magento/Customer/Ui/Component/ColumnFactory.php | 2 +- .../Ui/Component/Listing}/Column/InlineEditUpdater.php | 2 +- .../Ui/Component/Listing}/Column/ValidationRules.php | 2 +- .../Magento/Customer/Ui/Component/Listing/Columns.php | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) rename app/code/Magento/{Ui/Test/Unit/Component/Grid => Customer/Test/Unit/Ui/Component/Listing}/Column/InlineEditUpdaterTest.php (90%) rename app/code/Magento/{Ui/Test/Unit/Component/Grid => Customer/Test/Unit/Ui/Component/Listing}/Column/ValidationRulesTest.php (90%) rename app/code/Magento/{Ui/Component/Grid => Customer/Ui/Component/Listing}/Column/InlineEditUpdater.php (96%) rename app/code/Magento/{Ui/Component/Grid => Customer/Ui/Component/Listing}/Column/ValidationRules.php (97%) diff --git a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/InlineEditUpdaterTest.php similarity index 90% rename from app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php rename to app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/InlineEditUpdaterTest.php index 39903d3f0876a..21afae3e481c3 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/InlineEditUpdaterTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/InlineEditUpdaterTest.php @@ -3,10 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Test\Unit\Component\Grid\Column; +namespace Magento\Customer\Test\Unit\Ui\Component\Listing\Column; -use Magento\Ui\Component\Grid\Column\ValidationRules; -use Magento\Ui\Component\Grid\Column\InlineEditUpdater; +use Magento\Customer\Ui\Component\Listing\Column\ValidationRules; +use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; use Magento\Customer\Api\Data\ValidationRuleInterface; class InlineEditUpdaterTest extends \PHPUnit_Framework_TestCase @@ -25,7 +25,7 @@ class InlineEditUpdaterTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->validationRules = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\ValidationRules') + $this->validationRules = $this->getMockBuilder('Magento\Customer\Ui\Component\Listing\Column\ValidationRules') ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ValidationRulesTest.php similarity index 90% rename from app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php rename to app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ValidationRulesTest.php index 69f7041181cc9..e65e6b903e1c0 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Grid/Column/ValidationRulesTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ValidationRulesTest.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Test\Unit\Component\Grid\Column; +namespace Magento\Customer\Test\Unit\Ui\Component\Listing\Column; -use Magento\Ui\Component\Grid\Column\ValidationRules; +use Magento\Customer\Ui\Component\Listing\Column\ValidationRules; use Magento\Customer\Api\Data\ValidationRuleInterface; class ValidationRulesTest extends \PHPUnit_Framework_TestCase @@ -18,7 +18,7 @@ class ValidationRulesTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->validationRules = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\ValidationRules') + $this->validationRules = $this->getMockBuilder('Magento\Customer\Ui\Component\Listing\Column\ValidationRules') ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 0061e5bccb82f..c1b984ced81eb 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -6,7 +6,7 @@ namespace Magento\Customer\Ui\Component; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; -use Magento\Ui\Component\Grid\Column\InlineEditUpdater; +use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; use Magento\Customer\Api\CustomerMetadataInterface; class ColumnFactory diff --git a/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php similarity index 96% rename from app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php rename to app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php index f9641155e4b50..7794ecffd9338 100644 --- a/app/code/Magento/Ui/Component/Grid/Column/InlineEditUpdater.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Component\Grid\Column; +namespace Magento\Customer\Ui\Component\Listing\Column; use Magento\Framework\View\Element\UiComponentInterface; diff --git a/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php similarity index 97% rename from app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php rename to app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php index 583b6a7b61189..478391083d8f2 100644 --- a/app/code/Magento/Ui/Component/Grid/Column/ValidationRules.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Component\Grid\Column; +namespace Magento\Customer\Ui\Component\Listing\Column; use Magento\Customer\Api\Data\ValidationRuleInterface; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 2c46f49323a59..1a2065a9eb8a1 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -9,7 +9,7 @@ use Magento\Customer\Ui\Component\ColumnFactory; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\Component\Grid\Column\InlineEditUpdater; +use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; use Magento\Customer\Api\CustomerMetadataInterface; class Columns extends \Magento\Ui\Component\Listing\Columns From 8bbc495f4854c5d8d82983c566077aca1483f9e0 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 16:11:28 +0300 Subject: [PATCH 32/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Unit/Ui/Component/Listing/ColumnsTest.php | 14 +------------- .../Customer/Ui/Component/Listing/Columns.php | 16 ---------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php index adf9ac4136705..692e6f65e33d1 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php @@ -24,9 +24,6 @@ class ColumnsTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $column; - /** @var \Magento\Ui\Component\Grid\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ - protected $inlineEditUpdater; - /** @var Columns */ protected $component; @@ -66,15 +63,10 @@ public function setUp() false ); - $this->inlineEditUpdater = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\InlineEditUpdater') - ->disableOriginalConstructor() - ->getMock(); - $this->component = new Columns( $this->context, $this->columnFactory, - $this->attributeRepository, - $this->inlineEditUpdater + $this->attributeRepository ); } @@ -139,10 +131,6 @@ public function testPrepareWithUpdateColumn() 'required'=> false, 'entity_type_code' => 'customer', ]; - $this->inlineEditUpdater->expects($this->once()) - ->method('applyEditing') - ->with($this->column, 'text', [], false); - $this->attributeRepository->expects($this->atLeastOnce()) ->method('getList') ->willReturn([$attributeCode => $attributeData]); diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 1a2065a9eb8a1..c0eadc9ffe4aa 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -9,8 +9,6 @@ use Magento\Customer\Ui\Component\ColumnFactory; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; -use Magento\Customer\Api\CustomerMetadataInterface; class Columns extends \Magento\Ui\Component\Listing\Columns { @@ -20,14 +18,10 @@ class Columns extends \Magento\Ui\Component\Listing\Columns /** @var AttributeRepository */ protected $attributeRepository; - /** @var InlineEditUpdater */ - protected $inlineEditUpdater; - /** * @param ContextInterface $context * @param ColumnFactory $columnFactory * @param AttributeRepository $attributeRepository - * @param InlineEditUpdater $inlineEditor * @param array $components * @param array $data */ @@ -35,14 +29,12 @@ public function __construct( ContextInterface $context, ColumnFactory $columnFactory, AttributeRepository $attributeRepository, - InlineEditUpdater $inlineEditor, array $components = [], array $data = [] ) { parent::__construct($context, $components, $data); $this->columnFactory = $columnFactory; $this->attributeRepository = $attributeRepository; - $this->inlineEditUpdater = $inlineEditor; } /** @@ -117,14 +109,6 @@ public function updateColumn(array $attributeData, $newAttributeCode) { $component = $this->components[$attributeData[AttributeMetadata::ATTRIBUTE_CODE]]; $this->addOptions($component, $attributeData); - if ($attributeData['entity_type_code'] == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { - $this->inlineEditUpdater->applyEditing( - $component, - $attributeData[AttributeMetadata::FRONTEND_INPUT], - $attributeData[AttributeMetadata::VALIDATION_RULES], - $attributeData[AttributeMetadata::REQUIRED] - ); - } if ($attributeData[AttributeMetadata::BACKEND_TYPE] != 'static') { if ($attributeData[AttributeMetadata::IS_USED_IN_GRID]) { From 77c0a183a2a308c6960992a259ad69d261a6cd7c Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 16:34:18 +0300 Subject: [PATCH 33/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php index f9c591734b5ed..dafcfefdc384c 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php @@ -24,7 +24,7 @@ class ColumnFactoryTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $column; - /** @var \Magento\Ui\Component\Grid\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ protected $inlineEditUpdater; /** @var ColumnFactory */ @@ -64,7 +64,9 @@ public function setUp() false ); - $this->inlineEditUpdater = $this->getMockBuilder('Magento\Ui\Component\Grid\Column\InlineEditUpdater') + $this->inlineEditUpdater = $this->getMockBuilder( + 'Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater' + ) ->disableOriginalConstructor() ->getMock(); From 778f63a772a51f85e5eed0ed910a0bce859197d9 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 17:18:02 +0300 Subject: [PATCH 34/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Unit/Ui/Component/Listing/ColumnsTest.php | 27 +++++++++++++++---- .../Customer/Ui/Component/Listing/Columns.php | 18 +++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php index 692e6f65e33d1..fbdfdf3ff4798 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php @@ -24,6 +24,9 @@ class ColumnsTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $column; + /** @var \Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater|\PHPUnit_Framework_MockObject_MockObject */ + protected $inlineEditUpdater; + /** @var Columns */ protected $component; @@ -63,10 +66,16 @@ public function setUp() false ); + $this->inlineEditUpdater = $this->getMockBuilder( + 'Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater' + )->disableOriginalConstructor() + ->getMock(); + $this->component = new Columns( $this->context, $this->columnFactory, - $this->attributeRepository + $this->attributeRepository, + $this->inlineEditUpdater ); } @@ -131,6 +140,7 @@ public function testPrepareWithUpdateColumn() 'required'=> false, 'entity_type_code' => 'customer', ]; + $this->attributeRepository->expects($this->atLeastOnce()) ->method('getList') ->willReturn([$attributeCode => $attributeData]); @@ -177,7 +187,7 @@ public function testPrepareWithUpdateStaticColumn() $backendType = 'static'; $attributeData = [ 'attribute_code' => 'billing_attribute_code', - 'frontend_input' => 'frontend-input', + 'frontend_input' => 'text', 'frontend_label' => 'frontend-label', 'backend_type' => $backendType, 'options' => [ @@ -192,8 +202,11 @@ public function testPrepareWithUpdateStaticColumn() 'is_searchable_in_grid' => true, 'validation_rules' => [], 'required'=> false, - 'entity_type_code' => 'customer_address', + 'entity_type_code' => 'customer', ]; + $this->inlineEditUpdater->expects($this->once()) + ->method('applyEditing') + ->with($this->column, 'text', [], false); $this->attributeRepository->expects($this->atLeastOnce()) ->method('getList') @@ -206,12 +219,15 @@ public function testPrepareWithUpdateStaticColumn() $this->column->expects($this->atLeastOnce()) ->method('getData') ->with('config') - ->willReturn([]); + ->willReturn([ + 'editor' => 'text' + ]); $this->column->expects($this->at(3)) ->method('setData') ->with( 'config', [ + 'editor' => 'text', 'options' => [ [ 'label' => 'Label', @@ -220,11 +236,12 @@ public function testPrepareWithUpdateStaticColumn() ] ] ); - $this->column->expects($this->at(5)) + $this->column->expects($this->at(6)) ->method('setData') ->with( 'config', [ + 'editor' => 'text', 'visible' => true ] ); diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index c0eadc9ffe4aa..36b2f42d3b020 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -9,6 +9,8 @@ use Magento\Customer\Ui\Component\ColumnFactory; use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; +use Magento\Customer\Api\CustomerMetadataInterface; class Columns extends \Magento\Ui\Component\Listing\Columns { @@ -18,10 +20,14 @@ class Columns extends \Magento\Ui\Component\Listing\Columns /** @var AttributeRepository */ protected $attributeRepository; + /** @var InlineEditUpdater */ + protected $inlineEditUpdater; + /** * @param ContextInterface $context * @param ColumnFactory $columnFactory * @param AttributeRepository $attributeRepository + * @param InlineEditUpdater $inlineEditor * @param array $components * @param array $data */ @@ -29,12 +35,14 @@ public function __construct( ContextInterface $context, ColumnFactory $columnFactory, AttributeRepository $attributeRepository, + InlineEditUpdater $inlineEditor, array $components = [], array $data = [] ) { parent::__construct($context, $components, $data); $this->columnFactory = $columnFactory; $this->attributeRepository = $attributeRepository; + $this->inlineEditUpdater = $inlineEditor; } /** @@ -123,6 +131,16 @@ public function updateColumn(array $attributeData, $newAttributeCode) $component->setData('config', $config); } } else { + if ($attributeData['entity_type_code'] == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER + && !empty($component->getData('config')['editor']) + ) { + $this->inlineEditUpdater->applyEditing( + $component, + $attributeData[AttributeMetadata::FRONTEND_INPUT], + $attributeData[AttributeMetadata::VALIDATION_RULES], + $attributeData[AttributeMetadata::REQUIRED] + ); + } $component->setData( 'config', array_merge( From 9d4978f748b256a09f4223b2b6e57502f19ec5ec Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 17:35:53 +0300 Subject: [PATCH 35/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Ui/Component/ColumnFactory.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index c1b984ced81eb..e25b1105ea2ef 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -78,14 +78,12 @@ public function create(array $attributeData, $columnName, $context, array $confi 'context' => $context, ]; $column = $this->componentFactory->create($columnName, 'column', $arguments); - if ($attributeData['entity_type_code'] == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { - $this->inlineEditUpdater->applyEditing( - $column, - $attributeData[AttributeMetadata::FRONTEND_INPUT], - $attributeData[AttributeMetadata::VALIDATION_RULES], - $attributeData[AttributeMetadata::REQUIRED] - ); - } + $this->inlineEditUpdater->applyEditing( + $column, + $attributeData[AttributeMetadata::FRONTEND_INPUT], + $attributeData[AttributeMetadata::VALIDATION_RULES], + $attributeData[AttributeMetadata::REQUIRED] + ); return $column; } From 49463e1a17922f4f8e1d908fa9e37b339c24189f Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Mon, 7 Sep 2015 19:03:57 +0300 Subject: [PATCH 36/47] MAGETWO-38562: PHP - Customer - Inline editing --- app/code/Magento/Customer/Setup/UpgradeData.php | 6 +++--- .../Ui/Component/Listing/Column/ValidationRules.php | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Setup/UpgradeData.php b/app/code/Magento/Customer/Setup/UpgradeData.php index 44b1342830b58..a33b7751c6885 100644 --- a/app/code/Magento/Customer/Setup/UpgradeData.php +++ b/app/code/Magento/Customer/Setup/UpgradeData.php @@ -210,6 +210,9 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface ]; $this->upgradeAttributes($entityAttributes, $customerSetup); } + $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); + $indexer->reindexAll(); + $this->eavConfig->clear(); $setup->endSetup(); } @@ -229,8 +232,5 @@ protected function upgradeAttributes(array $entityAttributes, CustomerSetup $cus $attribute->save(); } } - $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); - $indexer->reindexAll(); - $this->eavConfig->clear(); } } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php index 478391083d8f2..a2e66be259d0f 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php @@ -21,6 +21,8 @@ class ValidationRules ]; /** + * Return list of validation rules with their value + * * @param boolean $isRequired * @param array $validationRules * @return array @@ -49,6 +51,8 @@ public function getValidationRules($isRequired, $validationRules) } /** + * Return validation class based on rule name or value + * * @param ValidationRuleInterface $rule * @return string */ @@ -61,6 +65,8 @@ protected function getValidationClass(ValidationRuleInterface $rule) } /** + * Return rule value + * * @param ValidationRuleInterface $rule * @return bool|string */ From f7b798a69a3553436a27b5815a7511e63bcb268f Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 8 Sep 2015 12:24:05 +0300 Subject: [PATCH 37/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Adminhtml/Customer/InvalidateToken.php | 5 +- .../Customer/Controller/Adminhtml/Index.php | 8 +-- .../Controller/Adminhtml/Index/InlineEdit.php | 58 ++++++++++++++++++- .../Controller/Adminhtml/Index/Viewfile.php | 5 +- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php index c21d8366fdfbd..92961f2a0d40f 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php @@ -59,7 +59,6 @@ class InvalidateToken extends \Magento\Customer\Controller\Adminhtml\Index * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param CustomerTokenServiceInterface $tokenService - * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -89,7 +88,6 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, - \Psr\Log\LoggerInterface $logger, CustomerTokenServiceInterface $tokenService ) { $this->tokenService = $tokenService; @@ -118,8 +116,7 @@ public function __construct( $resultLayoutFactory, $resultPageFactory, $resultForwardFactory, - $resultJsonFactory, - $logger + $resultJsonFactory ); } diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index.php b/app/code/Magento/Customer/Controller/Adminhtml/Index.php index dd0ed50d3d592..dd1eff1f0efbb 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index.php @@ -143,9 +143,6 @@ abstract class Index extends \Magento\Backend\App\Action */ protected $resultJsonFactory; - /** @var \Psr\Log\LoggerInterface */ - protected $logger; - /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry @@ -172,7 +169,6 @@ abstract class Index extends \Magento\Backend\App\Action * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory - * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -201,8 +197,7 @@ public function __construct( \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory, \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, - \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, - \Psr\Log\LoggerInterface $logger + \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory ) { $this->_coreRegistry = $coreRegistry; $this->_fileFactory = $fileFactory; @@ -228,7 +223,6 @@ public function __construct( $this->resultPageFactory = $resultPageFactory; $this->resultForwardFactory = $resultForwardFactory; $this->resultJsonFactory = $resultJsonFactory; - $this->logger = $logger; parent::__construct($context); } diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index b926d8b45cfde..2ac1295ba0019 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -5,14 +5,56 @@ */ namespace Magento\Customer\Controller\Adminhtml\Index; +use Magento\Backend\App\Action; use Magento\Customer\Ui\Component\Listing\AttributeRepository; use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; -class InlineEdit extends \Magento\Customer\Controller\Adminhtml\Index +class InlineEdit extends \Magento\Backend\App\Action { /** @var CustomerInterface */ private $customer; + /** @var CustomerRepositoryInterface */ + protected $customerRepository; + + /** @var \Magento\Framework\Controller\Result\JsonFactory */ + protected $resultJsonFactory; + + /** @var \Magento\Customer\Model\Customer\Mapper */ + protected $customerMapper; + + /** @var \Magento\Framework\Api\DataObjectHelper */ + protected $dataObjectHelper; + + /** @var \Psr\Log\LoggerInterface */ + protected $logger; + + /** + * @param Action\Context $context + * @param CustomerRepositoryInterface $customerRepository + * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory + * @param \Magento\Customer\Model\Customer\Mapper $customerMapper + * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + * @param \Psr\Log\LoggerInterface $logger + */ + public function __construct( + Action\Context $context, + CustomerRepositoryInterface $customerRepository, + \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, + \Magento\Customer\Model\Customer\Mapper $customerMapper, + \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, + \Psr\Log\LoggerInterface $logger + ) { + $this->customerRepository = $customerRepository; + $this->resultJsonFactory = $resultJsonFactory; + $this->customerMapper = $customerMapper; + $this->dataObjectHelper = $dataObjectHelper; + $this->logger = $logger; + parent::__construct($context); + } + + /** * @return \Magento\Framework\Controller\Result\Json */ @@ -30,7 +72,7 @@ public function execute() } foreach (array_keys($postItems) as $customerId) { - $this->setCustomer($this->_customerRepository->getById($customerId)); + $this->setCustomer($this->customerRepository->getById($customerId)); if ($this->getCustomer()->getDefaultBilling()) { $this->updateDefaultBilling($this->getData($postItems[$customerId])); } @@ -121,7 +163,7 @@ protected function updateDefaultBilling(array $data) protected function saveCustomer(CustomerInterface $customer) { try { - $this->_customerRepository->save($customer); + $this->customerRepository->save($customer); } catch (\Magento\Framework\Exception\InputException $e) { $this->getMessageManager()->addError($this->getErrorWithCustomerId($e->getMessage())); $this->logger->critical($e); @@ -206,4 +248,14 @@ protected function getErrorWithCustomerId($errorText) { return '[Customer ID: ' . $this->getCustomer()->getId() . '] ' . __($errorText); } + + /** + * Customer access rights checking + * + * @return bool + */ + protected function _isAllowed() + { + return $this->_authorization->isAllowed('Magento_Customer::manage'); + } } diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php index 943eb3b8cd995..52a8ea95f9412 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Viewfile.php @@ -58,7 +58,6 @@ class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory * @param \Magento\Framework\Url\DecoderInterface $urlDecoder - * @param \Psr\Log\LoggerInterface $logger * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -88,7 +87,6 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, - \Psr\Log\LoggerInterface $logger, \Magento\Framework\Controller\Result\RawFactory $resultRawFactory, \Magento\Framework\Url\DecoderInterface $urlDecoder ) { @@ -117,8 +115,7 @@ public function __construct( $resultLayoutFactory, $resultPageFactory, $resultForwardFactory, - $resultJsonFactory, - $logger + $resultJsonFactory ); $this->resultRawFactory = $resultRawFactory; $this->urlDecoder = $urlDecoder; From b984659e464fb44c56cd46ee22170b5de4e90070 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 8 Sep 2015 14:59:54 +0300 Subject: [PATCH 38/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Customer/Controller/Adminhtml/Index/InlineEdit.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php index 2ac1295ba0019..f97c48b0ebc1d 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php @@ -10,6 +10,9 @@ use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\CustomerRepositoryInterface; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class InlineEdit extends \Magento\Backend\App\Action { /** @var CustomerInterface */ @@ -54,7 +57,6 @@ public function __construct( parent::__construct($context); } - /** * @return \Magento\Framework\Controller\Result\Json */ From 30a753ac9eb72af7d2e06eda5a5aae056aab979b Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 16:36:40 +0300 Subject: [PATCH 39/47] MAGETWO-40878: Password reset link does not expire when email address changed --- .../Api/AccountManagementInterface.php | 11 -- .../Customer/Controller/Account/EditPost.php | 25 --- .../Customer/Model/AccountManagement.php | 20 -- .../Model/Resource/CustomerRepository.php | 9 + .../Unit/Controller/Account/EditPostTest.php | 186 +----------------- .../Test/Unit/Model/AccountManagementTest.php | 63 ------ .../Model/Resource/CustomerRepositoryTest.php | 18 +- 7 files changed, 24 insertions(+), 308 deletions(-) diff --git a/app/code/Magento/Customer/Api/AccountManagementInterface.php b/app/code/Magento/Customer/Api/AccountManagementInterface.php index 6df298a22e9d3..afd19537fd4c3 100644 --- a/app/code/Magento/Customer/Api/AccountManagementInterface.php +++ b/app/code/Magento/Customer/Api/AccountManagementInterface.php @@ -133,17 +133,6 @@ public function changePassword($email, $currentPassword, $newPassword); */ public function changePasswordById($customerId, $currentPassword, $newPassword); - /** - * Change customer email. - * - * @api - * @param string $email - * @param string $newEmail - * @return bool true on success - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function changeEmail($email, $newEmail); - /** * Send an email to the customer with a password reset link. * diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index 3e5aa10842c1c..ead64bca6175f 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -89,11 +89,6 @@ public function execute() $this->changeCustomerPassword($currentCustomer->getEmail()); } - // Change customer email - if ($currentCustomer->getEmail() !== $customer->getEmail()) { - $this->changeCustomerEmail($currentCustomer->getEmail(), $customer->getEmail()); - } - try { $this->customerRepository->save($customer); } catch (AuthenticationException $e) { @@ -151,24 +146,4 @@ protected function changeCustomerPassword($email) return $this; } - - /** - * Change customer email address - * - * @param string $email - * @param string $newEmail - * @return $this - */ - protected function changeCustomerEmail($email, $newEmail) - { - try { - $this->customerAccountManagement->changeEmail($email, $newEmail); - } catch (AuthenticationException $e) { - $this->messageManager->addError($e->getMessage()); - } catch (\Exception $e) { - $this->messageManager->addException($e, __('Something went wrong while changing the email.')); - } - - return $this; - } } diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 9d7b0d00ac7d2..3f3a18d2b3cad 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -609,26 +609,6 @@ public function changePasswordById($customerId, $currentPassword, $newPassword) return $this->changePasswordForCustomer($customer, $currentPassword, $newPassword); } - /** - * {@inheritdoc} - */ - public function changeEmail($email, $newEmail) - { - try { - $customer = $this->customerRepository->get($email); - } catch (NoSuchEntityException $e) { - throw new InvalidEmailOrPasswordException(__('Invalid login.')); - } - - $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId()); - $customerSecure->setRpToken(null); - $customerSecure->setRpTokenCreatedAt(null); - - $this->customerRepository->save($customer); - - return true; - } - /** * Change customer password. * diff --git a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php index a0c696bf7b588..45bca42044092 100644 --- a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php @@ -184,6 +184,15 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa $customerModel->setPasswordHash($passwordHash); } } + + // If customer email was changed, reset RpToken info + if ($prevCustomerData + && $prevCustomerData->getEmail() !== $customerModel->getEmail() + ) { + $customerModel->setRpToken(null); + $customerModel->setRpTokenCreatedAt(null); + } + $this->customerResourceModel->save($customerModel); $this->customerRegistry->push($customerModel); $customerId = $customerModel->getId(); diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php index ae29ecddb0b6c..85ecabc2c36be 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -167,20 +167,12 @@ public function testNoPostValues() public function testGeneralSave() { $customerId = 1; - $customerEmail = 'user1@example.com'; $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); $currentCustomerMock = $this->getCurrentCustomerMock($address); - $currentCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $newCustomerMock = $this->getNewCustomerMock($customerId, $address); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); $this->validator->expects($this->once()) ->method('validate') @@ -254,14 +246,11 @@ public function testChangePassword( ->getMockForAbstractClass(); $currentCustomerMock = $this->getCurrentCustomerMock($address); - $currentCustomerMock->expects($this->exactly(2)) + $currentCustomerMock->expects($this->once()) ->method('getEmail') ->willReturn($customerEmail); $newCustomerMock = $this->getNewCustomerMock($customerId, $address); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); $this->validator->expects($this->once()) ->method('validate') @@ -392,133 +381,6 @@ public function changePasswordDataProvider() ]; } - /** - * @param string $currentEmail - * @param string $newEmail - * @param [] $errors - * - * @dataProvider changeEmailDataProvider - */ - public function testChangeEmail( - $currentEmail, - $newEmail, - $errors - ) { - $customerId = 1; - - $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') - ->getMockForAbstractClass(); - - $currentCustomerMock = $this->getCurrentCustomerMock($address); - $currentCustomerMock->expects($this->exactly(2)) - ->method('getEmail') - ->willReturn($currentEmail); - - $newCustomerMock = $this->getNewCustomerMock($customerId, $address); - $newCustomerMock->expects($this->exactly(2)) - ->method('getEmail') - ->willReturn($newEmail); - - $this->validator->expects($this->once()) - ->method('validate') - ->with($this->request) - ->willReturn(true); - - $this->request->expects($this->once()) - ->method('isPost') - ->willReturn(true); - $this->request->expects($this->once()) - ->method('getParam') - ->with('change_password') - ->willReturn(false); - $this->request->expects($this->any()) - ->method('getPostValue') - ->willReturn(true); - - $this->session->expects($this->once()) - ->method('getCustomerId') - ->willReturn($customerId); - - // Prepare errors processing - if (!empty($errors)) { - $this->mockChangeEmailErrors($currentEmail, $newEmail, $errors); - } else { - $this->customerAccountManagement->expects($this->once()) - ->method('changeEmail') - ->with($currentEmail, $newEmail) - ->willReturnSelf(); - - $this->messageManager->expects($this->once()) - ->method('addSuccess') - ->with(__('You saved the account information.')) - ->willReturnSelf(); - - $this->resultRedirect->expects($this->once()) - ->method('setPath') - ->with('customer/account') - ->willReturnSelf(); - } - - $this->customerRepository->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($currentCustomerMock); - $this->customerRepository->expects($this->once()) - ->method('save') - ->with($newCustomerMock) - ->willReturnSelf(); - - $this->customerExtractor->expects($this->once()) - ->method('extract') - ->with('customer_account_edit', $this->request) - ->willReturn($newCustomerMock); - - $this->messageManager->expects($this->once()) - ->method('getMessages') - ->willReturn($this->messageCollection); - - $this->messageCollection->expects($this->once()) - ->method('getCount') - ->willReturn($errors); - - $this->assertSame($this->resultRedirect, $this->model->execute()); - } - - /** - * @return array - */ - public function changeEmailDataProvider() - { - return [ - [ - 'current_email' => 'user1@example.com', - 'new_email' => 'user2@example.com', - 'errors' => [ - 'counter' => 0, - 'message' => '', - ], - ], - [ - 'current_email' => 'user1@example.com', - 'new_email' => 'user2@example.com', - 'errors' => [ - 'counter' => 1, - 'message' => 'AuthenticationException', - 'exception' => '\Magento\Framework\Exception\AuthenticationException', - ], - ], - [ - 'current_email' => 'user1@example.com', - 'new_email' => 'user2@example.com', - 'errors' => [ - 'counter' => 1, - 'message' => 'Exception', - 'exception' => '\Exception', - ], - ], - ]; - } - /** * @param int $counter * @param string $message @@ -532,20 +394,12 @@ public function testGeneralException( $exception ) { $customerId = 1; - $customerEmail = 'user1@example.com'; $address = $this->getMockBuilder('Magento\Customer\Api\Data\AddressInterface') ->getMockForAbstractClass(); $currentCustomerMock = $this->getCurrentCustomerMock($address); - $currentCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $newCustomerMock = $this->getNewCustomerMock($customerId, $address); - $newCustomerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); $exception = new $exception(__($message)); @@ -711,44 +565,6 @@ protected function getCurrentCustomerMock($address) return $currentCustomerMock; } - /** - * @param string $currentEmail - * @param string $newEmail - * @param [] $errors - * @return void - */ - protected function mockChangeEmailErrors($currentEmail, $newEmail, $errors) - { - if (!empty($errors['exception'])) { - $exception = new $errors['exception'](__($errors['message'])); - - $this->customerAccountManagement->expects($this->once()) - ->method('changeEmail') - ->with($currentEmail, $newEmail) - ->willThrowException($exception); - - $this->messageManager->expects($this->any()) - ->method('addException') - ->with($exception, __('Something went wrong while changing the email.')) - ->willReturnSelf(); - } - - $this->session->expects($this->once()) - ->method('setCustomerFormData') - ->with(true) - ->willReturnSelf(); - - $this->messageManager->expects($this->any()) - ->method('addError') - ->with($errors['message']) - ->willReturnSelf(); - - $this->resultRedirect->expects($this->once()) - ->method('setPath') - ->with('*/*/edit') - ->willReturnSelf(); - } - /** * @param string $currentPassword * @param string $newPassword diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 7009a4609f862..d5fc01b379051 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1171,67 +1171,4 @@ private function reInitModel() ] ); } - - public function testChangeEmail() - { - $currentEmail = 'user1@example.com'; - $newEmail = 'user1@example.com'; - $customerId = 1; - - $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->getMockForAbstractClass(); - $customerSecureMock = $this->getMockBuilder('Magento\Customer\Model\Data\CustomerSecure') - ->disableOriginalConstructor() - ->setMethods([ - 'setRpToken', - 'setRpTokenCreatedAt', - ]) - ->getMock(); - - $customerMock->expects($this->once()) - ->method('getId') - ->willReturn($customerId); - - $customerSecureMock->expects($this->once()) - ->method('setRpToken') - ->with(null) - ->willReturnSelf(); - $customerSecureMock->expects($this->once()) - ->method('setRpTokenCreatedAt') - ->with(null) - ->willReturnSelf(); - - $this->customerRepository->expects($this->once()) - ->method('get') - ->with($currentEmail) - ->willReturn($customerMock); - $this->customerRepository->expects($this->once()) - ->method('save') - ->with($customerMock) - ->willReturnSelf(); - - $this->customerRegistry->expects($this->once()) - ->method('retrieveSecureData') - ->with($customerId) - ->willReturn($customerSecureMock); - - $this->assertTrue($this->accountManagement->changeEmail($currentEmail, $newEmail)); - } - - /** - * @expectedException \Magento\Framework\Exception\InvalidEmailOrPasswordException - * @expectedExceptionMessage Invalid login - */ - public function testChangeException() - { - $currentEmail = 'user1@example.com'; - $newEmail = 'user1@example.com'; - - $this->customerRepository->expects($this->once()) - ->method('get') - ->with($currentEmail) - ->willThrowException(new NoSuchEntityException(__('NoSuchEntityException'))); - - $this->accountManagement->changeEmail($currentEmail, $newEmail); - } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php index 98ecda6bc26b2..687a81b43c2c2 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php @@ -225,6 +225,8 @@ public function testSave() $storeId = 2; $this->prepareMocksForValidation(true); + $customerEmail = 'user1@example.com'; + $region = $this->getMockForAbstractClass('Magento\Customer\Api\Data\RegionInterface', [], '', false); $address = $this->getMockForAbstractClass( 'Magento\Customer\Api\Data\AddressInterface', @@ -381,12 +383,20 @@ public function testSave() $customerSecureData->expects($this->once()) ->method('getPasswordHash') ->willReturn('passwordHash'); - $customerModel->expects($this->once()) + + $customerModel->expects($this->exactly(2)) ->method('setRpToken') - ->with('rpToken'); - $customerModel->expects($this->once()) + ->willReturnMap([ + ['rpToken', $customerModel], + [null, $customerModel], + ]); + $customerModel->expects($this->exactly(2)) ->method('setRpTokenCreatedAt') - ->with('rpTokenCreatedAt'); + ->willReturnMap([ + ['rpTokenCreatedAt', $customerModel], + [null, $customerModel], + ]); + $customerModel->expects($this->once()) ->method('setPasswordHash') ->with('passwordHash'); From b2af6f2763a1032811b9a9bc574305f64cbb7227 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Tue, 8 Sep 2015 18:36:36 +0300 Subject: [PATCH 40/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Listing/Column/InlineEditUpdater.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php index 7794ecffd9338..a9a06e6378ed9 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php @@ -50,13 +50,18 @@ public function applyEditing( ) { if (in_array($frontendInput, $this->editableFields)) { $config = $column->getConfiguration(); - $config['editor'] = [ - 'editorType' => $config['dataType'] - ]; + if (!(isset($config['editor']) && isset($config['editor']['editorType']))) { + $config['editor'] = [ + 'editorType' => $config['dataType'] + ]; + } + $validationRules = $this->validationRules->getValidationRules($isRequired, $validationRules); - if (!empty($validationRules)) { - $config['editor']['validation'] = $validationRules; + + if (!empty($config['editor']['validation'])) { + $validationRules = array_merge($config['editor']['validation'], $validationRules); } + $config['editor']['validation'] = $validationRules; $column->setData('config', $config); } return $column; From 52826772aa78adc0499a6928406f5c04e91da870 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 18:54:59 +0300 Subject: [PATCH 41/47] MAGETWO-40878: Password reset link does not expire when email address changed --- .../Customer/Test/Unit/Controller/Account/EditPostTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php index 85ecabc2c36be..9d28b50d55092 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -280,7 +280,7 @@ public function testChangePassword( ->willReturn($customerId); // Prepare errors processing - if (!empty($errors)) { + if ($errors['counter'] > 0) { $this->mockChangePasswordErrors($currentPassword, $newPassword, $errors, $customerEmail); } else { $this->customerAccountManagement->expects($this->once()) @@ -319,7 +319,7 @@ public function testChangePassword( $this->messageCollection->expects($this->once()) ->method('getCount') - ->willReturn($errors); + ->willReturn($errors['counter']); $this->assertSame($this->resultRedirect, $this->model->execute()); From 6100b37fa249e2bf3b12e92c1e7121854e72fc4c Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 20:23:27 +0300 Subject: [PATCH 42/47] MAGETWO-39754: "Forgot Your Password" did not validate the existence of customer or admin user's email address --- .../Controller/Account/ForgotPasswordPost.php | 22 +- .../Controller/Account/ForgotPasswordPost.php | 257 ++++++++++++++++++ 2 files changed, 267 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php index 89b3b2384bea9..6cd9cb762a6d1 100644 --- a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php @@ -54,9 +54,8 @@ public function execute() if ($email) { if (!\Zend_Validate::is($email, 'EmailAddress')) { $this->_getSession()->setForgottenEmail($email); - $this->messageManager->addError(__('Please correct the email address.')); - $resultRedirect->setPath('*/*/forgotpassword'); - return $resultRedirect; + $this->messageManager->addErrorMessage(__('Please correct the email address.')); + return $resultRedirect->setPath('*/*/forgotpassword'); } try { @@ -67,19 +66,18 @@ public function execute() } catch (NoSuchEntityException $e) { // Do nothing, we don't want anyone to use this action to determine which email accounts are registered. } catch (\Exception $exception) { - $this->messageManager->addException($exception, __('We\'re unable to send the password reset email.')); - $resultRedirect->setPath('*/*/forgotpassword'); - return $resultRedirect; + $this->messageManager->addExceptionMessage($exception, __('We\'re unable to send the password reset email.')); + return $resultRedirect->setPath('*/*/forgotpassword'); } // @codingStandardsIgnoreStart - $this->messageManager->addSuccess(__('We\'ll email you a link to reset your password.')); + $this->messageManager->addSuccessMessage( + __('If there is an account associated with %1 you will receive an email with a link to reset your password.', $this->escaper->escapeHtml($email)) + ); // @codingStandardsIgnoreEnd - $resultRedirect->setPath('*/*/'); - return $resultRedirect; + return $resultRedirect->setPath('*/*/'); } else { - $this->messageManager->addError(__('Please enter your email.')); - $resultRedirect->setPath('*/*/forgotpassword'); - return $resultRedirect; + $this->messageManager->addErrorMessage(__('Please enter your email.')); + return $resultRedirect->setPath('*/*/forgotpassword'); } } } diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php new file mode 100644 index 0000000000000..2d6876d622b66 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php @@ -0,0 +1,257 @@ +prepareContext(); + + $this->session = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->getMock(); + + $this->pageFactory = $this->getMockBuilder('Magento\Framework\View\Result\PageFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->accountManagement = $this->getMockBuilder('Magento\Customer\Api\AccountManagementInterface') + ->getMockForAbstractClass(); + + $this->escaper = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->getMock(); + + $this->controller = new ForgotPasswordPost( + $this->context, + $this->session, + $this->pageFactory, + $this->accountManagement, + $this->escaper + ); + } + + public function testExecuteEmptyEmail() + { + $this->request->expects($this->once()) + ->method('getPost') + ->with('email') + ->willReturn(null); + + $this->messageManager->expects($this->once()) + ->method('addErrorMessage') + ->with(__('Please enter your email.')) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/forgotpassword') + ->willReturnSelf(); + + $this->assertSame($this->resultRedirect, $this->controller->execute()); + } + + public function testExecute() + { + $email = 'user1@example.com'; + + $this->request->expects($this->once()) + ->method('getPost') + ->with('email') + ->willReturn($email); + + $this->accountManagement->expects($this->once()) + ->method('initiatePasswordReset') + ->with($email, AccountManagement::EMAIL_RESET) + ->willReturnSelf(); + + $this->escaper->expects($this->once()) + ->method('escapeHtml') + ->with($email) + ->willReturn($email); + + // @codingStandardsIgnoreStart + $this->messageManager->expects($this->once()) + ->method('addSuccessMessage') + ->with(__('If there is an account associated with %1 you will receive an email with a link to reset your password.', $email)) + ->willReturnSelf(); + // @codingStandardsIgnoreEnd + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->controller->execute(); + } + + public function testExecuteNoSuchEntityException() + { + $email = 'user1@example.com'; + + $this->request->expects($this->once()) + ->method('getPost') + ->with('email') + ->willReturn($email); + + $this->accountManagement->expects($this->once()) + ->method('initiatePasswordReset') + ->with($email, AccountManagement::EMAIL_RESET) + ->willThrowException(new NoSuchEntityException(__('NoSuchEntityException'))); + + $this->escaper->expects($this->once()) + ->method('escapeHtml') + ->with($email) + ->willReturn($email); + + // @codingStandardsIgnoreStart + $this->messageManager->expects($this->once()) + ->method('addSuccessMessage') + ->with(__('If there is an account associated with %1 you will receive an email with a link to reset your password.', $email)) + ->willReturnSelf(); + // @codingStandardsIgnoreEnd + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->controller->execute(); + } + + public function testExecuteException() + { + $email = 'user1@example.com'; + $exception = new \Exception(__('Exception')); + + $this->request->expects($this->once()) + ->method('getPost') + ->with('email') + ->willReturn($email); + + $this->accountManagement->expects($this->once()) + ->method('initiatePasswordReset') + ->with($email, AccountManagement::EMAIL_RESET) + ->willThrowException($exception); + + $this->messageManager->expects($this->once()) + ->method('addExceptionMessage') + ->with($exception, __('We\'re unable to send the password reset email.')) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/forgotpassword') + ->willReturnSelf(); + + $this->controller->execute(); + } + + protected function prepareContext() + { + $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultRedirectFactory = $this->getMockBuilder('Magento\Framework\Controller\Result\RedirectFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->context = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http') + ->disableOriginalConstructor() + ->setMethods([ + 'getPost', + ]) + ->getMock(); + + $this->messageManager = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface') + ->getMockForAbstractClass(); + + $this->resultRedirectFactory->expects($this->any()) + ->method('create') + ->willReturn($this->resultRedirect); + + $this->context->expects($this->any()) + ->method('getResultRedirectFactory') + ->willReturn($this->resultRedirectFactory); + + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->request); + + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManager); + } +} From c95c219a571e03d63232f6060b123ee43382755e Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 20:50:02 +0300 Subject: [PATCH 43/47] MAGETWO-40878: Password reset link does not expire when email address changed --- .../Test/Unit/Model/Resource/CustomerRepositoryTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php index 687a81b43c2c2..9461c4b04d8db 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/CustomerRepositoryTest.php @@ -225,8 +225,6 @@ public function testSave() $storeId = 2; $this->prepareMocksForValidation(true); - $customerEmail = 'user1@example.com'; - $region = $this->getMockForAbstractClass('Magento\Customer\Api\Data\RegionInterface', [], '', false); $address = $this->getMockForAbstractClass( 'Magento\Customer\Api\Data\AddressInterface', From 96fb4d0eefd658d89be6503c76239b342c53399f Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 21:01:41 +0300 Subject: [PATCH 44/47] MAGETWO-39754: "Forgot Your Password" did not validate the existence of customer or admin user's email address --- .../Controller/Account/ForgotPasswordPost.php | 25 ++++++++++++++----- ...ordPost.php => ForgotPasswordPostTest.php} | 21 ++++++++++------ 2 files changed, 33 insertions(+), 13 deletions(-) rename app/code/Magento/Customer/Test/Unit/Controller/Account/{ForgotPasswordPost.php => ForgotPasswordPostTest.php} (93%) diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php index 6cd9cb762a6d1..644a0822846c2 100644 --- a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php @@ -66,18 +66,31 @@ public function execute() } catch (NoSuchEntityException $e) { // Do nothing, we don't want anyone to use this action to determine which email accounts are registered. } catch (\Exception $exception) { - $this->messageManager->addExceptionMessage($exception, __('We\'re unable to send the password reset email.')); + $this->messageManager->addExceptionMessage( + $exception, + __('We\'re unable to send the password reset email.') + ); return $resultRedirect->setPath('*/*/forgotpassword'); } - // @codingStandardsIgnoreStart - $this->messageManager->addSuccessMessage( - __('If there is an account associated with %1 you will receive an email with a link to reset your password.', $this->escaper->escapeHtml($email)) - ); - // @codingStandardsIgnoreEnd + $this->messageManager->addSuccessMessage($this->getSuccessMessage($email)); return $resultRedirect->setPath('*/*/'); } else { $this->messageManager->addErrorMessage(__('Please enter your email.')); return $resultRedirect->setPath('*/*/forgotpassword'); } } + + /** + * Retrieve success message + * + * @param string $email + * @return \Magento\Framework\Phrase + */ + protected function getSuccessMessage($email) + { + return __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $this->escaper->escapeHtml($email) + ); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php similarity index 93% rename from app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php rename to app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php index 2d6876d622b66..747c12e9c1c45 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPost.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php @@ -18,7 +18,10 @@ use Magento\Framework\Message\ManagerInterface; use Magento\Framework\View\Result\PageFactory; -class ForgotPasswordPostextends extends \PHPUnit_Framework_TestCase +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ForgotPasswordPostTest extends \PHPUnit_Framework_TestCase { /** * @var ForgotPasswordPost @@ -137,12 +140,14 @@ public function testExecute() ->with($email) ->willReturn($email); - // @codingStandardsIgnoreStart + $message = __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $email + ); $this->messageManager->expects($this->once()) ->method('addSuccessMessage') - ->with(__('If there is an account associated with %1 you will receive an email with a link to reset your password.', $email)) + ->with($message) ->willReturnSelf(); - // @codingStandardsIgnoreEnd $this->resultRedirect->expects($this->once()) ->method('setPath') @@ -171,12 +176,14 @@ public function testExecuteNoSuchEntityException() ->with($email) ->willReturn($email); - // @codingStandardsIgnoreStart + $message = __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $email + ); $this->messageManager->expects($this->once()) ->method('addSuccessMessage') - ->with(__('If there is an account associated with %1 you will receive an email with a link to reset your password.', $email)) + ->with($message) ->willReturnSelf(); - // @codingStandardsIgnoreEnd $this->resultRedirect->expects($this->once()) ->method('setPath') From 4256b2382f711d8a91911a8edf17a7daa504f219 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 8 Sep 2015 21:18:08 +0300 Subject: [PATCH 45/47] MAGETWO-39754: "Forgot Your Password" did not validate the existence of customer or admin user's email address --- .../Magento/Customer/Controller/Account/ForgotPasswordPost.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php index 644a0822846c2..ead592a1a77e7 100644 --- a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php @@ -14,6 +14,9 @@ use Magento\Framework\Escaper; use Magento\Framework\Exception\NoSuchEntityException; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class ForgotPasswordPost extends \Magento\Customer\Controller\Account { /** @var AccountManagementInterface */ From 90b22047215e0ccf53cc3896f350b48ed315f4cd Mon Sep 17 00:00:00 2001 From: Oleksandr Karpenko Date: Wed, 9 Sep 2015 12:08:04 +0300 Subject: [PATCH 46/47] MAGETWO-38562: PHP - Customer - Inline editing --- .../Ui/Component/Listing/Column/InlineEditUpdater.php | 8 ++++++-- .../view/adminhtml/ui_component/customer_listing.xml | 4 +--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php index a9a06e6378ed9..31b3bbab0a67a 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/InlineEditUpdater.php @@ -50,14 +50,18 @@ public function applyEditing( ) { if (in_array($frontendInput, $this->editableFields)) { $config = $column->getConfiguration(); + + $editorType = $config['dataType']; + if (isset($config['editor']) && is_string($config['editor'])) { + $editorType = $config['editor']; + } if (!(isset($config['editor']) && isset($config['editor']['editorType']))) { $config['editor'] = [ - 'editorType' => $config['dataType'] + 'editorType' => $editorType ]; } $validationRules = $this->validationRules->getValidationRules($isRequired, $validationRules); - if (!empty($config['editor']['validation'])) { $validationRules = array_merge($config['editor']['validation'], $validationRules); } diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index bcec4946dff93..2e1b4e5a6f912 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -437,9 +437,7 @@ Magento_Ui/js/grid/columns/column - - text - + text true text left From 5cf9a4281ad3b48fb23cb5e17faaec70a51b724b Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Wed, 9 Sep 2015 13:00:45 +0300 Subject: [PATCH 47/47] MAGETWO-39754: "Forgot Your Password" did not validate the existence of customer or admin user's email address --- .../AssertCustomerForgotPasswordSuccessMessage.php | 3 ++- .../Magento/Customer/Controller/AccountTest.php | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php index 6203469a9a827..318b5e531a92e 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php @@ -15,7 +15,8 @@ */ class AssertCustomerForgotPasswordSuccessMessage extends AbstractConstraint { - const SUCCESS_MESSAGE = "We'll email you a link to reset your password."; + const SUCCESS_MESSAGE = + 'If there is an account associated with %s you will receive an email with a link to reset your password.'; /** * Assert that customer forgot password message is present on customer account forgot password page. diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 84ce983401b04..18a38ca094511 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -322,10 +322,13 @@ public function testForgotPasswordPostAction() $this->dispatch('customer/account/forgotPasswordPost'); $this->assertRedirect($this->stringContains('customer/account/')); + + $message = __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $email + ); $this->assertSessionMessages( - $this->equalTo([ - 'We\'ll email you a link to reset your password.' - ]), + $this->equalTo([$message]), MessageInterface::TYPE_SUCCESS ); }