Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
DbStorage.php
Go to the documentation of this file.
1 <?php
8 
14 use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
15 use Psr\Log\LoggerInterface;
18 
25 {
29  const TABLE_NAME = 'url_rewrite';
30 
35 
39  protected $connection;
40 
44  protected $resource;
45 
49  private $logger;
50 
57  public function __construct(
58  UrlRewriteFactory $urlRewriteFactory,
61  LoggerInterface $logger = null
62  ) {
63  $this->connection = $resource->getConnection();
64  $this->resource = $resource;
65  $this->logger = $logger ?: ObjectManager::getInstance()
66  ->get(LoggerInterface::class);
67 
68  parent::__construct($urlRewriteFactory, $dataObjectHelper);
69  }
70 
77  protected function prepareSelect(array $data)
78  {
79  $select = $this->connection->select();
80  $select->from($this->resource->getTableName(self::TABLE_NAME));
81 
82  foreach ($data as $column => $value) {
83  $select->where($this->connection->quoteIdentifier($column) . ' IN (?)', $value);
84  }
85 
86  return $select;
87  }
88 
92  protected function doFindAllByData(array $data)
93  {
94  return $this->connection->fetchAll($this->prepareSelect($data));
95  }
96 
100  protected function doFindOneByData(array $data)
101  {
102  if (array_key_exists(UrlRewrite::REQUEST_PATH, $data)
103  && is_string($data[UrlRewrite::REQUEST_PATH])
104  ) {
105  $result = null;
106 
107  $requestPath = $data[UrlRewrite::REQUEST_PATH];
108 
110  rtrim($requestPath, '/'),
111  rtrim($requestPath, '/') . '/',
112  ];
113 
114  $resultsFromDb = $this->connection->fetchAll($this->prepareSelect($data));
115 
116  if (count($resultsFromDb) === 1) {
117  $resultFromDb = current($resultsFromDb);
119 
120  // If request path matches the DB value or it's redirect - we can return result from DB
121  $canReturnResultFromDb = ($resultFromDb[UrlRewrite::REQUEST_PATH] === $requestPath
122  || in_array((int)$resultFromDb[UrlRewrite::REDIRECT_TYPE], $redirectTypes, true));
123 
124  // Otherwise return 301 redirect to request path from DB results
125  $result = $canReturnResultFromDb ? $resultFromDb : [
126  UrlRewrite::ENTITY_TYPE => 'custom',
127  UrlRewrite::ENTITY_ID => '0',
128  UrlRewrite::REQUEST_PATH => $requestPath,
131  UrlRewrite::STORE_ID => $resultFromDb[UrlRewrite::STORE_ID],
132  UrlRewrite::DESCRIPTION => null,
134  UrlRewrite::METADATA => null,
135  ];
136  } else {
137  // If we have 2 results - return the row that matches request path
138  foreach ($resultsFromDb as $resultFromDb) {
139  if ($resultFromDb[UrlRewrite::REQUEST_PATH] === $requestPath) {
140  $result = $resultFromDb;
141  break;
142  }
143  }
144  }
145 
146  return $result;
147  }
148 
149  return $this->connection->fetchRow($this->prepareSelect($data));
150  }
151 
158  private function deleteOldUrls(array $urls): void
159  {
160  $oldUrlsSelect = $this->connection->select();
161  $oldUrlsSelect->from(
162  $this->resource->getTableName(self::TABLE_NAME)
163  );
165  foreach ($urls as $url) {
166  $oldUrlsSelect->orWhere(
167  $this->connection->quoteIdentifier(
169  ) . ' = ?',
170  $url->getEntityType()
171  );
172  $oldUrlsSelect->where(
173  $this->connection->quoteIdentifier(
175  ) . ' = ?',
176  $url->getEntityId()
177  );
178  $oldUrlsSelect->where(
179  $this->connection->quoteIdentifier(
181  ) . ' = ?',
182  $url->getStoreId()
183  );
184  }
185 
186  // prevent query locking in a case when nothing to delete
187  $checkOldUrlsSelect = clone $oldUrlsSelect;
188  $checkOldUrlsSelect->reset(Select::COLUMNS);
189  $checkOldUrlsSelect->columns('count(*)');
190  $hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect);
191 
192  if ($hasOldUrls) {
193  $this->connection->query(
194  $oldUrlsSelect->deleteFromSelect(
195  $this->resource->getTableName(self::TABLE_NAME)
196  )
197  );
198  }
199  }
200 
204  protected function doReplace(array $urls)
205  {
206  $this->deleteOldUrls($urls);
207 
208  $data = [];
209  foreach ($urls as $url) {
210  $data[] = $url->toArray();
211  }
212  try {
213  $this->insertMultiple($data);
214  } catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
216  $urlConflicted = [];
217  foreach ($urls as $url) {
218  $urlFound = $this->doFindOneByData(
219  [
220  UrlRewrite::REQUEST_PATH => $url->getRequestPath(),
221  UrlRewrite::STORE_ID => $url->getStoreId(),
222  ]
223  );
224  if (isset($urlFound[UrlRewrite::URL_REWRITE_ID])) {
225  $urlConflicted[$urlFound[UrlRewrite::URL_REWRITE_ID]] = $url->toArray();
226  }
227  }
228  if ($urlConflicted) {
229  throw new \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException(
230  __('URL key for specified store already exists.'),
231  $e,
232  $e->getCode(),
233  $urlConflicted
234  );
235  } else {
236  throw $e->getPrevious() ?: $e;
237  }
238  }
239 
240  return $urls;
241  }
242 
251  protected function insertMultiple($data)
252  {
253  try {
254  $this->connection->insertMultiple($this->resource->getTableName(self::TABLE_NAME), $data);
255  } catch (\Exception $e) {
256  if (($e->getCode() === self::ERROR_CODE_DUPLICATE_ENTRY)
257  && preg_match('#SQLSTATE\[23000\]: [^:]+: 1062[^\d]#', $e->getMessage())
258  ) {
259  throw new \Magento\Framework\Exception\AlreadyExistsException(
260  __('URL key for specified store already exists.'),
261  $e
262  );
263  }
264  throw $e;
265  }
266  }
267 
275  protected function createFilterDataBasedOnUrls($urls)
276  {
277  $data = [];
278  foreach ($urls as $url) {
279  $entityType = $url->getEntityType();
280  foreach ([UrlRewrite::ENTITY_ID, UrlRewrite::STORE_ID] as $key) {
281  $fieldValue = $url->getByKey($key);
282  if (!isset($data[$entityType][$key]) || !in_array($fieldValue, $data[$entityType][$key])) {
283  $data[$entityType][$key][] = $fieldValue;
284  }
285  }
286  }
287 
288  return $data;
289  }
290 
294  public function deleteByData(array $data)
295  {
296  $this->connection->query(
297  $this->prepareSelect($data)->deleteFromSelect($this->resource->getTableName(self::TABLE_NAME))
298  );
299  }
300 }
__()
Definition: __.php:13
$value
Definition: gender.phtml:16
const COLUMNS
Definition: Select.php:48
__construct(UrlRewriteFactory $urlRewriteFactory, DataObjectHelper $dataObjectHelper, ResourceConnection $resource, LoggerInterface $logger=null)
Definition: DbStorage.php:57