shor-tcut/ezseo

This package remembers removed locations to render a proper 410-pages

v1.0.1 2018-07-20 15:57 UTC

README

Purpose and general

ShorTcutEzSeoBundle is created to reach the following goals:

  • storing information of deleted locations (but not deleting the content)
  • catching all not existing URLs as fallback
  • generate a proper 410-page instead of a general 404-page and deliver additional information for the customer how to proceed
  • if you do not provide a custom layout and logic for a 404/410 page the bundle will deliver fallback pages
  • this bundle can also be used to create redirects or a niceurl-handler

Thanks to Etecture GmbH and CMS to makes this library OpenSource so we can improve this step by step.

Limitations

The current state works for eZ Publish 5.x installations. The handling of 404 is there different than in eZ Platform.

Installation

  • Copy the bundle and activate the bundle in the kernel (in eZ Publish 5 it is the method EzPublishKernel::registerBundles())
  • require in composer.json composer require shor-tcut/ezseo
  • generate the db ezpublish/console doctrine:schema:update (or bin/console or whatever)

Configuration options

Service Tags

Page Delivery

Service tag: sc.seo.handle

Possible attributes: priority

A service tagged with that tag should implement Service\Handle\HandleInterface. The HandleInterface::handle method gets a response object which can be altered (status code is already set so you can use it to distinguish between 404 and 410). This method returns a boolean value. If false is returned the services with lower priotities will not be used anymore (this should happen in the most cases).

Routing

Service tag: sc.seo.custom_routing

Possible attributes: method

If you have a customised routing service in your installation (instead of the default chain router) you can configure it here. The default method name is generate.

Parameters

sc_seo.default.legacy_siteaccesses In eZ Publish 5.x installations you may have some legacy siteaccesses (e.g. the admin site access). You have to exclude these siteaccesses because the 404 ends always in the legacy stack.

sc_seo.default.uri_exclude_pattern

The URLs of the deleted locations will be saved with the different translated URL-pattern. In case the siteaccess is in your URL it would be good to exclude that siteaccess to make the decision only dependent to the translation and not the siteaccess.

Example: Your siteaccess is (like in a lot of sites) the language code:

www.example.com/en/my/special/object

The URL would be: /en/my/special/object In that case it would be good to exclude /en because you can also reach the same object with /de/my/special/object! The pattern to exclude that prefix (example configuration) would be:

sc_seo.default.uri_exclude_pattern: ["^/[a-z]{2}"]

or simply

sc_seo.default.uri_exclude_pattern: "^/[a-z]{2}"

How to remember locations

You have to call that process manually (currently): $locationMemoryService->addFromLocation($location, $siteAccesses)

The location is the location that will be removed (but not the object itself, otherwise it is not possible to suggest other content objects). $siteaccess can be an array to remember the multilingual URLs. If omitted the default siteaccess will be used.

How to use the memories

/**
 * @param Response $response
 * @param MemoryEntity|null $memory
 * @return bool
 */
public function handle(Response &$response, MemoryEntity $memory = null): bool
{
    // please note: $response->getStatusCode is 410 in case $memory is not null.
    // but you can change that, if you want to. This improves SEO rankings.
    
    $view = null;    
    $params = ["foo" => "bar"];
    
    $action = $memory ? $memory->getAction() : LocationMemory::ACTION_NONE;

    switch ($action) {
    
        case LocationMemory::ACTION_GONE:
            $memoryData = $memory->getData(false);
            $contentId = $memoryData->getContentId();
            // do something awesome here or suggest other content
            $view = $this-renderView("410.html.twig", $params);
            break;
            
        case LocationMemory::ACTION_REDIRECT:
            // todo
            break;
            
        default:
            break;
    }

    if (!$view) {
        $view = $this->renderView('error404.html.twig', $params);
    }
    
    $response = $response->setContent($view);
    
    // if you return false, the chain will be interrupted and no other handle will be called. 
    // returning true gives you the possibility to alter the response object.
    return false; 
}

Possible improvements

  • eZ Platform integration
  • generate links entries for hidden locations (not in every router)
  • create new signal for removing locations, direct integration into the core