1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\Redirects\Repository;
19
20use TYPO3\CMS\Core\Database\ConnectionPool;
21use TYPO3\CMS\Core\Database\Query\QueryBuilder;
22use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
23use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25/**
26 * Class for accessing redirect records from the database
27 * @internal
28 */
29class RedirectRepository
30{
31    /**
32     * @var Demand
33     */
34    protected $demand;
35
36    /**
37     * With a possible demand object
38     *
39     * @param Demand|null $demand
40     */
41    public function __construct(Demand $demand = null)
42    {
43        $this->demand = $demand ?? new Demand();
44    }
45
46    /**
47     * Used within the backend module, which also includes the hidden records, but never deleted records.
48     *
49     * @return array
50     */
51    public function findRedirectsByDemand(): array
52    {
53        return $this->getQueryBuilderForDemand()
54            ->setMaxResults($this->demand->getLimit())
55            ->setFirstResult($this->demand->getOffset())
56            ->execute()
57            ->fetchAll();
58    }
59
60    /**
61     * @return int
62     */
63    public function countRedirectsByByDemand(): int
64    {
65        return $this->getQueryBuilderForDemand()->execute()->rowCount();
66    }
67
68    /**
69     * Prepares the QueryBuilder with Constraints from the Demand
70     *
71     * @return QueryBuilder
72     */
73    protected function getQueryBuilderForDemand(): QueryBuilder
74    {
75        $queryBuilder = $this->getQueryBuilder();
76        $queryBuilder
77            ->select('*')
78            ->from('sys_redirect')
79            ->orderBy('source_host')
80            ->addOrderBy('source_path');
81
82        $constraints = [];
83        if ($this->demand->hasSourceHost()) {
84            $constraints[] =$queryBuilder->expr()->eq(
85                'source_host',
86                $queryBuilder->createNamedParameter($this->demand->getSourceHost(), \PDO::PARAM_STR)
87            );
88        }
89
90        if ($this->demand->hasSourcePath()) {
91            $escapedLikeString = '%' . $queryBuilder->escapeLikeWildcards($this->demand->getSourcePath()) . '%';
92            $constraints[] = $queryBuilder->expr()->like(
93                'source_path',
94                $queryBuilder->createNamedParameter($escapedLikeString, \PDO::PARAM_STR)
95            );
96        }
97
98        if ($this->demand->hasTarget()) {
99            $escapedLikeString = '%' . $queryBuilder->escapeLikeWildcards($this->demand->getTarget()) . '%';
100            $constraints[] = $queryBuilder->expr()->like(
101                'target',
102                $queryBuilder->createNamedParameter($escapedLikeString, \PDO::PARAM_STR)
103            );
104        }
105
106        if ($this->demand->hasStatusCode()) {
107            $constraints[] =$queryBuilder->expr()->eq(
108                'target_statuscode',
109                $queryBuilder->createNamedParameter($this->demand->getStatusCode(), \PDO::PARAM_INT)
110            );
111        }
112
113        if (!empty($constraints)) {
114            $queryBuilder->where(...$constraints);
115        }
116        return $queryBuilder;
117    }
118
119    /**
120     * Used for the filtering in the backend
121     *
122     * @return array
123     */
124    public function findHostsOfRedirects(): array
125    {
126        return $this->getQueryBuilder()
127            ->select('source_host as name')
128            ->from('sys_redirect')
129            ->orderBy('source_host')
130            ->groupBy('source_host')
131            ->execute()
132            ->fetchAll();
133    }
134
135    /**
136     * Used for the filtering in the backend
137     *
138     * @return array
139     */
140    public function findStatusCodesOfRedirects(): array
141    {
142        return $this->getQueryBuilder()
143            ->select('target_statuscode as code')
144            ->from('sys_redirect')
145            ->orderBy('target_statuscode')
146            ->groupBy('target_statuscode')
147            ->execute()
148            ->fetchAll();
149    }
150
151    /**
152     * @return QueryBuilder
153     */
154    protected function getQueryBuilder(): QueryBuilder
155    {
156        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_redirect');
157        $queryBuilder->getRestrictions()
158            ->removeAll()
159            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
160        return $queryBuilder;
161    }
162}
163