Closed solverat closed 6 years ago
Only viable solution would be a template helper that generates routes + a separate service. What do you think about that?
btw, you can already do that anyway. Why create a separate service for that when this is already symfony standard?
After some research. Basically we should use the pimcore link generator.
First, we need a global CoreShop service called LinkGenerator
. This one can be injected and used to create urls in php context (links in mails for example):
<?php
class LinkGenerator
{
public function getLink($entity, string $name, array $params)
{
$params['routeName'] = $name;
$params['entity'] = $entity;
if (!$entity instanceof Concrete) {
// no valid entity. use the default path
return $this->urlGenerator->generate($name, $params);
}
if ($linkGenerator = $entity->getClass()->getLinkGenerator()) {
$_params = array_merge($params, [
'document' => $this->documentResolver->getDocument();
'context' => $this
]);
return $linkGenerator->generate($entity, $_params);
}
// no link generator found. use the default path
return $this->urlGenerator->generate($name, $params);
}
}
Create a Twig Extension (which calls getLink()
from the service above) to generate links in templates:
{# 1.
for routes with link generator
#}
{{ coreshop_link(product, 'coreshop_product_detail') }}
{# 2.
for routes without a default link generator:
will trigger the symfony's default url generator
until a developer adds a linkgenerator to the cart class
#}
{{ coreshop_link(cart, 'coreshop_cart_add', {product: product.id}) }}
{# 3.
for routes without a link generator
#}
{{ coreshop_link(null, 'coreshop_index') }}
Then CoreShop should provide a link generator service for each class (product
, category
should be enough?) Add the services to the link generator in pimcore class configuration.
For example the product link generator
<?php
class ProductDetailLinkGenerator implements LinkGeneratorInterface
{
public function generate(Concrete $object, array $params = []): string
{
if (isset($params['document']) && $params['document'] instanceof Document) {
// do something with given document
}
$staticRoute = Staticroute::getByName($params['coreshop_product_detail']);
$path = $staticRoute->assemble([
// generates nice slugs like my-awesome-url
'name' => $this->slugify($object->getName(),
'product' => $object->getId()
]);
return $path;
}
public function slugify($string)
{
return strtolower(trim(preg_replace('~[^0-9a-z]+~i', '-', html_entity_decode(preg_replace('~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', '$1', htmlentities($string, ENT_QUOTES, 'UTF-8')), ENT_QUOTES, 'UTF-8')), '-'));
}
}
That's it. If you want to modify the Link Generator, just create your own and change the service in the pimcore class configuration.
sounds good, I'll have a look at that.
@solverat can you check the PR please?
done
The default coreshop routing creates ugly urls like:
shop/fr/Monogram%20Canvas%20Montaigne%20BB~p62
.Suggestion
We should implement a macro file which allows devs to create nice looking urls without changing all the templates. Affected routes:
coreshop_product_detail
coreshop_category_list
So instead of
we should use
By default the macro will return the same url to prevent BC breaks.
Open Question
What about routes which get generated via api (without template engine), they also should get transformed the same way.