-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor contact module #8420
Refactor contact module #8420
Changes from 17 commits
47a4681
e1d47cc
962c06d
fb902c6
352dcef
c8fbb70
36261ea
ec3fad1
0c78857
b4f68b0
5854390
854f16d
22004d7
cdf8725
28d939f
7a01613
0261088
a5c69d0
f5ac9f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
/** | ||
* Contact module base controller | ||
*/ | ||
namespace Magento\Contact\Api; | ||
|
||
/** | ||
* Contact module configuration | ||
*/ | ||
interface ConfigInterface | ||
{ | ||
/** | ||
* Recipient email config path | ||
*/ | ||
const XML_PATH_EMAIL_RECIPIENT = 'contact/email/recipient_email'; | ||
|
||
/** | ||
* Sender email config path | ||
*/ | ||
const XML_PATH_EMAIL_SENDER = 'contact/email/sender_email_identity'; | ||
|
||
/** | ||
* Email template config path | ||
*/ | ||
const XML_PATH_EMAIL_TEMPLATE = 'contact/email/email_template'; | ||
|
||
/** | ||
* Enabled config path | ||
*/ | ||
const XML_PATH_ENABLED = 'contact/contact/enabled'; | ||
|
||
/** | ||
* Check if contacts module is enabled | ||
* | ||
* @return bool | ||
*/ | ||
public function isEnabled(); | ||
|
||
/** | ||
* Return email template identifier | ||
* | ||
* @return string | ||
*/ | ||
public function emailTemplate(); | ||
|
||
/** | ||
* Return email sender address | ||
* | ||
* @return string | ||
*/ | ||
public function emailSender(); | ||
|
||
/** | ||
* Return email recipient address | ||
* | ||
* @return mixed | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Service Contracts does not allow usage of "mixed" type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch, should have been |
||
*/ | ||
public function emailRecipient(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
/** | ||
* Contact module base controller | ||
*/ | ||
namespace Magento\Contact\Api; | ||
|
||
interface MailInterface | ||
{ | ||
/** | ||
* Send email from contact form | ||
* | ||
* @param string $replyTo Reply-to email address | ||
* @param array $variables Email template variables | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Service Contracts does not allow usage of "array" type, it should be more specific, i.e. "String[]" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but email template variables can be anything, from strings and integers to objects. How would you deal with it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now understand that these rules only apply to service contracts in the sense of interfaces that can be exposed as web API, so I assume that I can leave the signature as it is, after moving the interfaces out of |
||
* @return void | ||
*/ | ||
public function send($replyTo, $variables); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,16 @@ | |
*/ | ||
namespace Magento\Contact\Controller\Index; | ||
|
||
use Magento\Framework\App\Request\DataPersistorInterface; | ||
use Magento\Contact\Api\ConfigInterface; | ||
use Magento\Contact\Api\MailInterface; | ||
use Magento\Framework\App\Action\Context; | ||
use Magento\Framework\App\ObjectManager; | ||
use Magento\Framework\App\Request\DataPersistorInterface; | ||
use Magento\Framework\Controller\Result\Redirect; | ||
use Magento\Framework\Exception\LocalizedException; | ||
use Magento\Framework\HTTP\PhpEnvironment\Request; | ||
use Magento\Framework\Mail\Template\TransportBuilder; | ||
use Magento\Framework\Translate\Inline\StateInterface; | ||
|
||
class Post extends \Magento\Contact\Controller\Index | ||
{ | ||
|
@@ -16,75 +24,60 @@ class Post extends \Magento\Contact\Controller\Index | |
*/ | ||
private $dataPersistor; | ||
|
||
/** | ||
* @var Context | ||
*/ | ||
private $context; | ||
|
||
/** | ||
* @var MailInterface | ||
*/ | ||
private $mail; | ||
|
||
/** | ||
* @param Context $context | ||
* @param MailInterface $mail | ||
* @param ConfigInterface $contactsConfig | ||
* @param DataPersistorInterface $dataPersistor | ||
*/ | ||
public function __construct( | ||
Context $context, | ||
MailInterface $mail, | ||
ConfigInterface $contactsConfig, | ||
DataPersistorInterface $dataPersistor | ||
) { | ||
parent::__construct($context, $contactsConfig); | ||
$this->context = $context; | ||
$this->mail = $mail; | ||
$this->dataPersistor = $dataPersistor; | ||
} | ||
|
||
/** | ||
* Post user question | ||
* | ||
* @return void | ||
* @throws \Exception | ||
* @return Redirect | ||
*/ | ||
public function execute() | ||
{ | ||
$post = $this->getRequest()->getPostValue(); | ||
if (!$post) { | ||
$this->_redirect('*/*/'); | ||
return; | ||
if (! $this->isPostRequest()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extra space here after "!" |
||
return $this->resultRedirectFactory->create()->setPath('*/*/'); | ||
} | ||
|
||
$this->inlineTranslation->suspend(); | ||
try { | ||
$postObject = new \Magento\Framework\DataObject(); | ||
$postObject->setData($post); | ||
|
||
$error = false; | ||
|
||
if (!\Zend_Validate::is(trim($post['name']), 'NotEmpty')) { | ||
$error = true; | ||
} | ||
if (!\Zend_Validate::is(trim($post['comment']), 'NotEmpty')) { | ||
$error = true; | ||
} | ||
if (!\Zend_Validate::is(trim($post['email']), 'EmailAddress')) { | ||
$error = true; | ||
} | ||
if (\Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) { | ||
$error = true; | ||
} | ||
if ($error) { | ||
throw new \Exception(); | ||
} | ||
|
||
$storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; | ||
$transport = $this->_transportBuilder | ||
->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_TEMPLATE, $storeScope)) | ||
->setTemplateOptions( | ||
[ | ||
'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, | ||
'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, | ||
] | ||
) | ||
->setTemplateVars(['data' => $postObject]) | ||
->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_SENDER, $storeScope)) | ||
->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT, $storeScope)) | ||
->setReplyTo($post['email']) | ||
->getTransport(); | ||
|
||
$transport->sendMessage(); | ||
$this->inlineTranslation->resume(); | ||
$this->sendEmail($this->validatedParams()); | ||
$this->messageManager->addSuccess( | ||
__('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.') | ||
); | ||
$this->getDataPersistor()->clear('contact_us'); | ||
$this->_redirect('contact/index'); | ||
return; | ||
} catch (LocalizedException $e) { | ||
$this->messageManager->addErrorMessage($e->getMessage()); | ||
$this->getDataPersistor()->set('contact_us', $this->getRequest()->getParams()); | ||
} catch (\Exception $e) { | ||
$this->inlineTranslation->resume(); | ||
$this->messageManager->addError( | ||
$this->messageManager->addErrorMessage( | ||
__('We can\'t process your request right now. Sorry, that\'s all we know.') | ||
); | ||
$this->getDataPersistor()->set('contact_us', $post); | ||
$this->_redirect('contact/index'); | ||
return; | ||
$this->getDataPersistor()->set('contact_us', $this->getRequest()->getParams()); | ||
} | ||
return $this->resultRedirectFactory->create()->setPath('contact/index'); | ||
} | ||
|
||
/** | ||
|
@@ -101,4 +94,46 @@ private function getDataPersistor() | |
|
||
return $this->dataPersistor; | ||
} | ||
|
||
/** | ||
* @param array $post Post data from contact form | ||
* @return void | ||
*/ | ||
private function sendEmail($post) | ||
{ | ||
$this->mail->send($post['email'], ['data' => new \Magento\Framework\DataObject($post)]); | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
private function isPostRequest() | ||
{ | ||
/** @var Request $request */ | ||
$request = $this->getRequest(); | ||
return !empty($request->getPostValue()); | ||
} | ||
|
||
/** | ||
* @return array | ||
* @throws \Exception | ||
*/ | ||
private function validatedParams() | ||
{ | ||
$request = $this->getRequest(); | ||
if (trim($request->getParam('name')) === '') { | ||
throw new LocalizedException(__('Name is missing')); | ||
} | ||
if (trim($request->getParam('comment')) === '') { | ||
throw new LocalizedException(__('Comment is missing')); | ||
} | ||
if (false === \strpos($request->getParam('email'), '@')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are losing quite a bit of functionality here vs Zend_Validate_EmailAddress. Maybe the better approach would be to switch to the ZF2 component https://github.com/zendframework/zend-validator/blob/master/src/EmailAddress.php#L492 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did that on purpose because I don't believe in email address validation via regular expressions (relevant: https://hackernoon.com/the-100-correct-way-to-validate-email-addresses-7c4818f24643). If there's a decision to use the MX check, the ZF2 email validator would be useful again. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great article - you got me convinced. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we not using php's native
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joe-vortex same reason that I dropped Zend_Validate_EmailAddress. The top comment on http://php.net/manual/en/function.filter-var.php already gives an example |
||
throw new LocalizedException(__('Invalid email address')); | ||
} | ||
if (trim($request->getParam('hideit')) !== '') { | ||
throw new \Exception(); | ||
} | ||
|
||
return $request->getParams(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface is neither Service Interface (does not describe operations on data) nor Data Interface (it does not consist only of getters and setters for the fields). Also, it does not looks like it makes sense to expose it as Web API.
Let's move these two interfaces out of Api namespace to the Model. Please add @api annotation to the interface to indicate that this is backward compatible module's interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the review. I did not intend to expose the interfaces to the web api, they were only meant as service contracts. I was not aware of the convention to distinguish between
Api
namespace and@api
annotation, will change it as suggested