Problem/Motivation

See #2672142: Update assertAlias() to use alias manager so it works with 8.1.x

Pathauto has quite a few direct queries against {url_alias}.

Someone might want to move that to a different storage, e.g. MongoDB and then pathauto would break.

Proposed resolution

We should evaluate them and try to get rid of them, possibly try getting support for e.g. IN conditions for load() into core.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Berdir created an issue. See original summary.

sharique’s picture

Assigned: Unassigned » sharique
Status: Active » Needs review
StatusFileSize
new6.13 KB

I did some work on it, replaced query with helper at few places, please review and let me know, if this is correct way.

Bambell’s picture

StatusFileSize
new8.86 KB
new8.79 KB

I tried refactoring AliasStorageHelper, but didn't end up doing much. I simplified loadBySource(); the original implementation would return the alias for a given source path and language and would fallback to undefined language if nothing was found, but I'm not sure this behavior is appropriate. I changed this to simply query for an exact match for the given language. I also removed unused function exists() and broke down functions that supported the wildcard character *.

url_alias is now referenced only in truncate(), loadBySourcePrefix(), countAliasesBySourcePrefix() and countAliasesBySourcePrefix(). The reference in loadBySourcePrefix() (and potentially more) could be eliminated and the code greatly simplified if core wouldn't escape the value being matched in Drupal\Core\Path\AliasStorage::delete() :

$query->condition($field, $this->connection->escapeLike($value), 'LIKE');

Not sure why they're doing that. It prevents using %. Same for load().

Other than that, I'm not seeing much more room for improvement, as far as I can tell.

sharique’s picture

+++ b/src/AliasStorageHelperInterface.php
@@ -52,37 +52,27 @@ interface AliasStorageHelperInterface {
+  public function truncate();

My 2 cent point, instead of truncate, better name it deleteAllAliases, for simple to understand, what function does with name.

berdir’s picture

Status: Needs review » Needs work

The problem is that we already have deleteAll(). deleteAll() and deleteAllAliases() doing something different wouldn't make sense.

What we could do is rename the current deleteAll() to deleteBySourcePrefix() because that's what it does and then have deleteAll() actually delete all.

  1. +++ b/src/AliasStorageHelper.php
    @@ -155,40 +155,27 @@ class AliasStorageHelper implements AliasStorageHelperInterface {
       public function loadBySource($source, $language = LanguageInterface::LANGCODE_NOT_SPECIFIED) {
    -    // @todo convert this to be a query on alias storage.
    -    $pid = $this->database->queryRange("SELECT pid FROM {url_alias} WHERE source = :source AND langcode IN (:language, :language_none) ORDER BY langcode DESC, pid DESC", 0, 1, array(
    -      ':source' => $source,
    -      ':language' => $language,
    -      ':language_none' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
    -    ))->fetchField();
    -    return $this->aliasStorage->load(array('pid' => $pid));
    +    return $this->aliasStorage->load([
    +      'source' => $source,
    +      'langcode' => $language,
    +    ]);
       }
    

    the behavior with langcode and fallback is important, we can't just remove that. Because that's how the system works when resolving an alias, it first checks the current language then falls back to language-unspecific.

  2. +++ b/src/AliasStorageHelper.php
    @@ -223,12 +210,15 @@ class AliasStorageHelper implements AliasStorageHelperInterface {
    +  public function countAliasesBySourcePrefix($source) {
    +    return $this->database->select('url_alias')->condition('source', $source . '%', 'LIKE')->countQuery()->execute()->fetchField();
       }
    

    since the class is called AliasStorageHelper and most methods don't have Alias in the name, I think we should be consistent and always leave it out.

Bambell’s picture

Status: Needs work » Needs review
StatusFileSize
new11.36 KB
new9.3 KB

Makes sense. I renamed truncate() to deleteAll() and deleteAll() to deleteBySourcePrefix(). I added fallback to undefined language for load() and renamed some other functions as well. I moved the visibility of deleteMultiple() from public to protected, because the interface is already a bit confusing, in my opinion, and I can't think of a use case for this outside of the class (there is no operation to get multiple pid's). Moved some other things around as well.

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/src/AliasStorageHelper.php
    @@ -182,43 +191,57 @@ class AliasStorageHelper implements AliasStorageHelperInterface {
    +   *
    +   * @param integer[] $pids
    +   *   An array of path IDs to delete.
    

    just int, not integer.

  2. +++ b/src/Form/PathautoAdminDelete.php
    @@ -101,12 +101,12 @@ class PathautoAdminDelete extends FormBase {
    -      $storage_helper->deleteAll((string)$alias_type->getSourcePrefix());
    +      $storage_helper->deleteBySourcePrefix((string)$alias_type->getSourcePrefix());
    

    space after (string)

Looks good to me. One thing that I think we should also do here is to add the backend_overridable tag to the storage helper service in services.yml, see https://www.drupal.org/node/2306083. That makes it easier for e.g. redis to provide an alternative backend.

Bambell’s picture

Status: Needs work » Needs review
StatusFileSize
new11.98 KB
new1.89 KB

Here we go.

berdir’s picture

Status: Needs review » Needs work

Looks good but waited too long, needs a reroll now.

Bambell’s picture

Status: Needs work » Needs review
StatusFileSize
new12 KB

Here we go, re-rolled.

Bambell’s picture

berdir’s picture

Status: Needs review » Fixed

Thanks, committed.

  • Berdir committed 539c647 on 8.x-1.x authored by Bambell
    Issue #2672150 by Bambell, Sharique: Use alias manager and storage...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.