1<?php 2 3namespace Drupal\Core\Path; 4 5use Drupal\Core\Database\Connection; 6use Drupal\Core\Database\Query\Condition; 7use Drupal\Core\Database\Query\SelectInterface; 8use Drupal\Core\Language\LanguageInterface; 9 10/** 11 * Provides the default path alias lookup operations. 12 * 13 * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use 14 * \Drupal\path_alias\AliasRepository instead. 15 * 16 * @see https://www.drupal.org/node/3092086 17 */ 18class AliasRepository implements AliasRepositoryInterface { 19 20 /** 21 * The database connection. 22 * 23 * @var \Drupal\Core\Database\Connection 24 */ 25 protected $connection; 26 27 /** 28 * Constructs an AliasRepository object. 29 * 30 * @param \Drupal\Core\Database\Connection $connection 31 * A database connection for reading and writing path aliases. 32 */ 33 public function __construct(Connection $connection) { 34 $this->connection = $connection; 35 36 // This is used as base class by the new class, so we do not trigger 37 // deprecation notices when that or any child class is instantiated. 38 $new_class = 'Drupal\path_alias\AliasRepository'; 39 if (!is_a($this, $new_class) && class_exists($new_class)) { 40 @trigger_error('The \\' . __CLASS__ . ' class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \\' . $new_class . '. See https://drupal.org/node/3092086', E_USER_DEPRECATED); 41 } 42 } 43 44 /** 45 * {@inheritdoc} 46 */ 47 public function preloadPathAlias($preloaded, $langcode) { 48 $select = $this->getBaseQuery() 49 ->fields('base_table', ['path', 'alias']); 50 51 if (!empty($preloaded)) { 52 $conditions = new Condition('OR'); 53 foreach ($preloaded as $preloaded_item) { 54 $conditions->condition('base_table.path', $this->connection->escapeLike($preloaded_item), 'LIKE'); 55 } 56 $select->condition($conditions); 57 } 58 59 $this->addLanguageFallback($select, $langcode); 60 61 // We order by ID ASC so that fetchAllKeyed() returns the most recently 62 // created alias for each source. Subsequent queries using fetchField() must 63 // use ID DESC to have the same effect. 64 $select->orderBy('base_table.id', 'ASC'); 65 66 return $select->execute()->fetchAllKeyed(); 67 } 68 69 /** 70 * {@inheritdoc} 71 */ 72 public function lookupBySystemPath($path, $langcode) { 73 // See the queries above. Use LIKE for case-insensitive matching. 74 $select = $this->getBaseQuery() 75 ->fields('base_table', ['id', 'path', 'alias', 'langcode']) 76 ->condition('base_table.path', $this->connection->escapeLike($path), 'LIKE'); 77 78 $this->addLanguageFallback($select, $langcode); 79 80 $select->orderBy('base_table.id', 'DESC'); 81 82 return $select->execute()->fetchAssoc() ?: NULL; 83 } 84 85 /** 86 * {@inheritdoc} 87 */ 88 public function lookupByAlias($alias, $langcode) { 89 // See the queries above. Use LIKE for case-insensitive matching. 90 $select = $this->getBaseQuery() 91 ->fields('base_table', ['id', 'path', 'alias', 'langcode']) 92 ->condition('base_table.alias', $this->connection->escapeLike($alias), 'LIKE'); 93 94 $this->addLanguageFallback($select, $langcode); 95 96 $select->orderBy('base_table.id', 'DESC'); 97 98 return $select->execute()->fetchAssoc() ?: NULL; 99 } 100 101 /** 102 * {@inheritdoc} 103 */ 104 public function pathHasMatchingAlias($initial_substring) { 105 $query = $this->getBaseQuery(); 106 $query->addExpression(1); 107 108 return (bool) $query 109 ->condition('base_table.path', $this->connection->escapeLike($initial_substring) . '%', 'LIKE') 110 ->range(0, 1) 111 ->execute() 112 ->fetchField(); 113 } 114 115 /** 116 * Returns a SELECT query for the path_alias base table. 117 * 118 * @return \Drupal\Core\Database\Query\SelectInterface 119 * A Select query object. 120 */ 121 protected function getBaseQuery() { 122 $query = $this->connection->select('path_alias', 'base_table'); 123 $query->condition('base_table.status', 1); 124 125 return $query; 126 } 127 128 /** 129 * Adds path alias language fallback conditions to a select query object. 130 * 131 * @param \Drupal\Core\Database\Query\SelectInterface $query 132 * A Select query object. 133 * @param string $langcode 134 * Language code to search the path with. If there's no path defined for 135 * that language it will search paths without language. 136 */ 137 protected function addLanguageFallback(SelectInterface $query, $langcode) { 138 // Always get the language-specific alias before the language-neutral one. 139 // For example 'de' is less than 'und' so the order needs to be ASC, while 140 // 'xx-lolspeak' is more than 'und' so the order needs to be DESC. 141 $langcode_list = [$langcode, LanguageInterface::LANGCODE_NOT_SPECIFIED]; 142 if ($langcode === LanguageInterface::LANGCODE_NOT_SPECIFIED) { 143 array_pop($langcode_list); 144 } 145 elseif ($langcode > LanguageInterface::LANGCODE_NOT_SPECIFIED) { 146 $query->orderBy('base_table.langcode', 'DESC'); 147 } 148 else { 149 $query->orderBy('base_table.langcode', 'ASC'); 150 } 151 $query->condition('base_table.langcode', $langcode_list, 'IN'); 152 } 153 154} 155