-
Notifications
You must be signed in to change notification settings - Fork 9.4k
$product->getUrlInStore() does not allow to override the scope in backend context #21876
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
Conversation
Hi @Nazar65. Thank you for your contribution
For more details, please, review the Magento Contributor Assistant documentation |
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.
@orlangur thanks, i'm will refactor it. |
@orlangur wait a little bit i'm still working on this . |
Hi @orlangur all done ✔️ i'm rechecked and run some test, seems like works correctly from frontend and adminhtml |
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.
Thanks for the pull request @Nazar65 Please see my code review comments
Also, as for original issue - I believe it can be solved by setting current store to the store manager \Magento\Store\Model\StoreManager::setCurrentStore
* @param $scope string | ||
* @return \Magento\Store\Model\Store | ||
*/ | ||
protected function getScope($scope = null) |
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.
Adding protected functions is backward incompatible and we cannot accept that to a patch release.
Also, the proposed implementation is against CQRS principle (getter should not change the state of the system)
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.
Adding protected functions is backward incompatible
What? That's something new to me. Is it documented and then announced somewhere?
Hi @sivaschenko thanks for reviewing, but |
@sivaschenko with |
@sivaschenko i'm found a better solution, give me some time to test it, thanks 👍 |
$result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); | ||
$customScope | ||
? $result = $this->getData('scope')->getBaseUrl($this->_getType(), $this->_isSecure()) | ||
: $result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); |
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.
Who taught you this?)
Please use ternary operator normally, $result = $customScope ? ... : ...
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.
Still not fixed.
My observation, to get correct product url in adminhtml we need create the url object for the product ->
So after that we have correct url without admin in url. like this -> |
Hi @orlangur Hi @sivaschenko can you review new changes ? |
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.
@@ -63,6 +63,7 @@ public function beforeSetRouteParams( | |||
) { | |||
if (isset($data['_scope'])) { | |||
$subject->setScope($data['_scope']); | |||
$subject->setRouteParam('_scope',$data['_scope']); |
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.
There should be a space here according to PSR-2 but I'm not sure if Travis is not broken currently.
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.
ok
$result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); | ||
$customScope | ||
? $result = $this->getData('scope')->getBaseUrl($this->_getType(), $this->_isSecure()) | ||
: $result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); |
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.
Still not fixed.
@@ -478,8 +483,8 @@ public function getBaseUrl($params = []) | |||
) { | |||
$this->getRouteParamsResolver()->setType(UrlInterface::URL_TYPE_DIRECT_LINK); | |||
} | |||
|
|||
$result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); | |||
$result = $customScope ? $this->getData('scope')->getBaseUrl($this->_getType(), $this->_isSecure()) |
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.
Please explain the logic. Why we cannot always use $this->getData('scope')
?
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.
@orlangur Because this metod have usages in many methods and not always sets "_scope" to the dataObjects, and method _getScope() checks if _scope not exist in dataObject then they give us a hardcoded admin "_scope", so basically I added a 1 more scenario where we can get _scope from data object, and this scenario will not break some tests, i think
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.
I think _getScope
can be used instead of getData('scope')
- it's basically the same plus handling the case when scope is not set.
@orlangur I'm tested this a couple day and this works perfect with my custom module, so i'm will write some tests, and will finish on this. |
HI @orlangur @sivaschenko i'm finished the implementation and cover with intergation tests, seems like works fine. |
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.
Hi @Nazar65 thanks for updates, please see my review notes
dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php
Outdated
Show resolved
Hide resolved
@@ -478,8 +483,8 @@ public function getBaseUrl($params = []) | |||
) { | |||
$this->getRouteParamsResolver()->setType(UrlInterface::URL_TYPE_DIRECT_LINK); | |||
} | |||
|
|||
$result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); | |||
$result = $customScope ? $this->getData('scope')->getBaseUrl($this->_getType(), $this->_isSecure()) |
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.
I think _getScope
can be used instead of getData('scope')
- it's basically the same plus handling the case when scope is not set.
Hi @sivaschenko thank you for you review notes that's what i needed. now finally bug in this method Framework/Url -> seems like use |
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.
Hi @Nazar65 thanks for the update, see my code review comments
* | ||
* @param array $params | ||
*/ | ||
private function setRequestScope($params) :void |
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.
private function setRequestScope($params) :void | |
private function setRequestScope(array $params): void |
@@ -478,8 +488,7 @@ public function getBaseUrl($params = []) | |||
) { | |||
$this->getRouteParamsResolver()->setType(UrlInterface::URL_TYPE_DIRECT_LINK); | |||
} | |||
|
|||
$result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); | |||
$result = self::_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); |
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.
I don't think this change from $this->_getScope()
to self::_getScope()
is needed. Can you please provide more details on why do you think it is necessary
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.
@sivaschenko with self::
we get _getScope()
in Framework/Url
2 - with $this
we get _getScope()
in Model/Url wich returns admin scope.
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.
But this is not good idea to use one method, when we need to call product url in admin scope, i thinks would be better to use previous solution with $this->getData('_scope') and if
statement, because some tests will fails with this
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.
I think this solution will be better and not break any functional
$result = $this->setRequestScope($params)->getBaseUrl($this->_getType(), $this->_isSecure());
private function setRequestScope($params)
{
$customScope = $this->getRouteParamsResolver()->getRouteParam('_scope');
if (isset($params['_scope']) ) {
$this->setScope($params['_scope']);
} else if ($customScope) {
$this->setScope($customScope);
return $this->getData('scope');
}
return $this->_getScope();
}
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.
Hi @Nazar65 , please see my propositions the in review comments.
{ | ||
$customScope = $this->getRouteParamsResolver()->getRouteParam('_scope'); | ||
|
||
if (isset($params['_scope'])) { |
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.
What do you think about introducing a setScope
method to \Magento\Backend\Model\Url
to be able to assign custom scope to _scope
property? (it's better to also keep parent method call for backward compatibility purposes)
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.
@sivaschenko yes, that's what i needed, now it looks fine, i'm little bit confused by overriding method _getScope()
@sivaschenko done ✔️ |
Hi @sivaschenko, thank you for the review. |
✔️ QA Passed |
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.
Hi @Nazar65 can you please recheck the integration tests, they are falling with the following results
Magento\Catalog\Model\Product\UrlTest::testGetUrlInStoreWithSecondStore
Magento\Framework\Exception\NoSuchEntityException: The product that was requested doesn't exist. Verify the product and try again.
/var/www/html/app/code/Magento/Catalog/Model/ProductRepository.php:276
/var/www/html/dev/tests/integration/tmp/sandbox--3c335e531fab12e41ef1a983a92177df/generated/code/Magento/Catalog/Model/ProductRepository/Interceptor.php:24
/var/www/html/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php:68
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.
Hi @Nazar65 thanks for the update!
Please correct the test to utilize the data provider functionality
dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php
Outdated
Show resolved
Hide resolved
dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php
Show resolved
Hide resolved
dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php
Outdated
Show resolved
Hide resolved
@sivaschenko done ✔️ |
Hi @sivaschenko, thank you for the review. |
Hi @Nazar65, thank you for your contribution! |
… scope in backend context magento#21876
Description (*)
Magento always uses the 'admin' scope (and the default base url) to retrieve product url and returns incorrect url.
By calling the method $product->getUrlInStore(['_scope' => 2, '_nosid' => true]); I'm always retreiving the product's url with default scope in it. (for example http://default.website/catalog/product/view/...)
Fixed Issues (if relevant)
Manual testing scenarios (*)
On backend edit page try to get product url from second website
Same steps on frontend.
Contribution checklist (*)