coreshop / CoreShop

CoreShop - Pimcore enhanced eCommerce
http://www.coreshop.org
Other
276 stars 157 forks source link

Nice Urls Macro #413

Closed solverat closed 6 years ago

solverat commented 6 years ago
Q A
Bug report? no
Feature request? no
BC Break report? no
RFC? yes

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:

So instead of

{{ path('coreshop_category_list', {name: category.getName, category: category.getId}) }}

we should use

{% import '@CoreShopFrontend/Common/Macro/routing.html.twig' as routing %}
{{ routing.nice_path('coreshop_category_list', {name: category.getName, category: category.getId}) }}

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.

dpfaffenbauer commented 6 years ago

Only viable solution would be a template helper that generates routes + a separate service. What do you think about that?

dpfaffenbauer commented 6 years ago

btw, you can already do that anyway. Why create a separate service for that when this is already symfony standard?

solverat commented 6 years ago

After some research. Basically we should use the pimcore link generator.

Service

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);
    }
}

Twig

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') }}

Link Generator

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.

dpfaffenbauer commented 6 years ago

sounds good, I'll have a look at that.

dpfaffenbauer commented 6 years ago

@solverat can you check the PR please?

dpfaffenbauer commented 6 years ago

done