0

For the detail pages of tx_news records as well as a calendar extension I wrote myself I want the record date in the URL as I had it until TYPO3 8LTS with the realURL extension: /path-to/my-page/yyyy/mm/dd/extension-record-path-segment/. I managed to have the link created but with the cHash attached.

My routeEnhancers settings for the tx_news_pi1 in /typo3conf/sites/my-site/config.yaml are as follows:

routeEnhancers:
  NewsPlugin:
    type: Extbase
    limitToPages: [7]
    extension: News
    plugin: Pi1
    routes:
      - { routePath: '/{year}/{month}/{day}/{news}', _controller: 'News::detail' }
    defaultController: 'News::detail'
    requirements:
      year: '^20[0-9]{2}$'
      month: '^[01][0-9]$'
      day: '^[0-3][0-9]$'
    aspects:
      news:
        type: PersistedAliasMapper
        tableName: 'tx_news_domain_model_news'
        routeFieldName: 'path_segment'

I added the requirements section with quite strict regular expressions because the description in the T3 changelog mentions this as needed in order to avoid the cHash.

I also tried using StaticRangeMappers in the aspects section for year, month, and day (as described in this answer) but that results in the PersistedAliasMapper being ignored and showing the UID of the news record instead. Or sometimes even in a TYPO3 exception (1/1) #1537696772 OverflowException: Possible range of all mappers is larger than 10000 items (it even did so when I removed them for month and day and set the range for year to only 2016–2019).

      year:
        type: StaticRangeMapper
        start: '2016'
        end: '2100'
      month:
        type: StaticRangeMapper
        start: '01'
        end: '12'
      day:
        type: StaticRangeMapper
        start: '01'
        end: '31'
      event:
        type: PersistedAliasMapper
        tableName: 'tx_thesimplecal_domain_model_events'
        routeFieldName: 'path_segment'

EDIT: I have updated this post to be shorter as magically some of the originally mentioned errors disappeared.

clive beckett
  • 152
  • 16

2 Answers2

2

The reason for this problem is that the month comes as string with a leading zero but the StaticRangeMapper buildes the range without leading 0s and does not map a month like 01. The mapping stops as soon one value cannot be mapped and now the uid of the news record is not mapped since this would happen after the mapping of the month.

A simple solution is to write a StaticMonthMapper

class StaticMonthMapper implements StaticMappableAspectInterface, \Countable
{
/**
 * @var array
 */
protected $settings;


/**
 * @param array $settings
 * @throws \InvalidArgumentException
 */
public function __construct(array $settings)
{
    $this->settings = $settings;
}

/**
 * {@inheritdoc}
 */
public function count(): int
{
    return 12;
}

/**
 * {@inheritdoc}
 */
public function generate(string $value): ?string
{
    return $this->respondWhenInRange($value);
}

/**
 * {@inheritdoc}
 */
public function resolve(string $value): ?string
{
    return $this->respondWhenInRange($value);
}

/**
 * @param string $value
 * @return string|null
 */
protected function respondWhenInRange(string $value): ?string
{
    switch ($value) {
        case '01':
        case '02':
        case '03':
        case '04':
        case '05':
        case '06':
        case '07':
        case '08':
        case '09':
        case '10':
        case '11':
        case '12':
            return $value;
        default:
            return null;
    }
}
}

and register it with

$GLOBALS['TYPO3_CONF_VARS']['SYS']['routing']['aspects']['StaticMonthMapper'] = \Package\Namespace\StaticMonthMapper::class;

This can be used in the site config. For the days parameter a similar mapper can be created.

year:
    type: StaticRangeMapper
    start: '2016'
    end: '2100'
month:
    type: StaticMonthMapper
bingo-fuel
  • 136
  • 3
  • Thank you! That seems to work in general … but when adding the StaticMonthMapper as well as a similar StaticDayMapper, I get the OverflowException again: `Possible range of all mappers is larger than 10000 items`. One tiny addition to the class, however, in case anyone wants to try it: between namespace and class declaration, add `use TYPO3\CMS\Core\Routing\Aspect\StaticMappableAspectInterface;` – clive beckett Sep 13 '19 at 08:53
  • 2
    Try to remove the \Countable interface from the StaticMonthMapper and Day mappers. The PageRouter check if the sum of all countable static routing interfaces is limited to 1000 to prevent cache flooding attacks but if you remove the Countable interface they are not considered for the sum. – bingo-fuel Sep 17 '19 at 06:45
0

The whole concept with the new routing is a little bit different now :-)

Basically, the idea now is, to create a slug for a certain record and store it in the database, rather than creating/parsing strings on request time. This is also done with paths and pages in v9, just have a look at the slug field in your pages table.

So, there is a new type of TCA field in the backend now, called slug. You can configure it to be created from multiple database fields. Hint: Be aware, the editor needs write permission to all the fields you like to generate the slug from. There is a bug with readonly fields, so keep that in mind! If the field is then correctly stored in the database, you can use the route like that:

routeEnhancers:
  News:
    type: Extbase
    limitToPages:
      - <YOUR-DETAIL-PID-HERE>
    extension: <YOUR-EXTENSION-NAME>
    plugin: <YOUR-PLUGIN-NAME>
    routes:
      -
        routePath: '/{news_title}'
        _controller: 'News::show'
        _arguments:
          offer_title: news
    defaultController: 'News::show'
    aspects:
      news_title:
        type: PersistedAliasMapper
        tableName: <YOUR-TABLE-NAME>
        routeFieldName: slug
        routeValuePrefix: ''

All the other fancy mappers are for very special cases.

Michael
  • 2,309
  • 1
  • 23
  • 34
  • Thanks, Michael! I have used that TCA field in my calendar extension – without the date as I want two other fields to be separated by a dash but the date fields separated by a backslash `my-page/yyyy/mm/dd/{speaker}-{title}`. However, I could live with a general fieldSeparator there. But for tx_news the slug field is already given as `path_segment` and defined to be generated from the title field. So I’d have to add the date manually everytime? – clive beckett Feb 18 '19 at 09:58
  • You could either overwrite the TCA for path_segment or define an additional field "slug" which is then built as you like. I guess that is way faster than using your own mapper. You could also define 3 fields for each part of the date and use a `PersistedPatternMapper`, but I have not tried that myself. – Michael Feb 18 '19 at 11:54
  • Thanks again, Michael. The `PersistedPatternMapper` is a compromise that I might have to live with. But I still think it should be possible to create a URL `my-page/yyyy/mm/dd/path-segment – and it isn’t with the `PersistedPatternMapper`. After all you _can_ combine different query parameters for other use cases. Besides a calendar could potentially have a repeated event on different dates that goes by the same title. Plus: the date does not belong into path_segment field in my opinion. – clive beckett Feb 22 '19 at 16:45