Completed
Push — master ( 61fc74...2dfe55 )
by Fabien
10:06
created

PidCheck::getQueryBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Fab\Vidi\View\Check;
4
5
/*
6
 * This file is part of the Fab/Vidi project under GPLv2 or later.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.md file that was distributed with this source code.
10
 */
11
12
use TYPO3\CMS\Core\Database\ConnectionPool;
13
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
14
use TYPO3\CMS\Core\Utility\GeneralUtility;
15
use Fab\Vidi\View\AbstractComponentView;
16
use TYPO3\CMS\Frontend\Page\PageRepository;
17
use Fab\Vidi\Module\Parameter;
18
use Fab\Vidi\Tca\Tca;
19
20
/**
21
 * View which renders check.
22
 */
23
class PidCheck extends AbstractComponentView
24
{
25
26
    /**
27
     * The data type (table)
28
     *
29
     * @var string
30
     */
31
    protected $dataType = '';
32
33
    /**
34
     * The configured pid for the data type
35
     *
36
     * @var int
37
     */
38
    protected $configuredPid = 0;
39
40
    /**
41
     * The page record of the configured pid
42
     *
43
     * @var array
44
     */
45
    protected $page = null;
46
47
    /**
48
     * A collection of speaking error messages why the pid is invalid.
49
     *
50
     * @var array
51
     */
52
    protected $errors = [];
53
54
    /**
55
     * Pseudo-Constructor, which ensures all dependencies are injected when called.
56
     */
57
    public function initializeObject(): void
58
    {
59
        $this->dataType = $this->getModuleLoader()->getDataType();
60
        $this->configuredPid = $this->getConfiguredPid();
61
    }
62
63
    /**
64
     * Renders warnings if storagePid is not properly configured.
65
     *
66
     * @return string
67
     */
68
    public function render()
69
    {
70
        $result = '';
71
72
        $this->validateRootLevel();
73
        $this->validatePageExist();
74
        $this->validateDoktype();
75
76
        if (!empty($this->errors)) {
77
            $result .= $this->formatMessagePidIsNotValid();
78
        }
79
80
        return $result;
81
    }
82
83
    /**
84
     * Format a message whenever the storage is offline.
85
     *
86
     * @return string
87
     */
88
    protected function formatMessagePidIsNotValid(): string
89
    {
90
        $error = implode('<br />', $this->errors);
91
        $result = <<< EOF
92
			<div class="alert alert-warning">
93
				<div class="alert-title">
94
					Page id "{$this->configuredPid}" has found to be a wrong configuration for "{$this->dataType}"
95
				</div>
96
				<div class="alert-message">
97
					<p>{$error}</p>
98
					New records cannot be created with this page id. The configuration can be changed at different levels:
99
					<ul>
100
						<li>Settings in the Extension Manager as fallback configuration.</li>
101
						<li>In some ext_tables.php file, by allowing this record type on any pages.<br />
102
						\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('{$this->dataType}')
103
						</li>
104
						<li>By User TSconfig:</li>
105
					</ul>
106
<pre>
107
# User TSconfig to be placed in your ext_tables.php:
108
TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig('
109
110
	# Default pid for "{$this->dataType}" in Vidi:
111
	tx_vidi.dataType.{$this->dataType}.storagePid = xx
112
');
113
</pre>
114
115
				</div>
116
			</div>
117
EOF;
118
119
        return $result;
120
    }
121
122
    /**
123
     * Check if pid is 0 and given table is allowed on root level.
124
     *
125
     * @return void
126
     */
127
    protected function validateRootLevel(): void
128
    {
129
        if ($this->configuredPid > 0) {
130
            return;
131
        }
132
133
        $isRootLevel = (bool)Tca::table()->get('rootLevel');
134
        if (!$isRootLevel) {
135
            $this->errors[] = sprintf(
136
                'You are not allowed to use page id "0" unless you set $GLOBALS[\'TCA\'][\'%1$s\'][\'ctrl\'][\'rootLevel\'] = 1;',
137
                $this->dataType
138
            );
139
        }
140
    }
141
142
    /**
143
     * Check if a page exists for the configured pid
144
     *
145
     * @return void
146
     */
147
    protected function validatePageExist(): void
148
    {
149
        if ($this->configuredPid === 0) {
150
            return;
151
        }
152
153
        $page = $this->getPage();
154
        if (empty($page)) {
155
            $this->errors[] = sprintf(
156
                'No page found for the configured page id "%s".',
157
                $this->configuredPid
158
            );
159
        }
160
    }
161
162
    /**
163
     * Check if configured page is a sysfolder and if it is allowed.
164
     *
165
     * @return void
166
     */
167
    protected function validateDoktype(): void
168
    {
169
        if ($this->configuredPid === 0) {
170
            return;
171
        }
172
173
        $page = $this->getPage();
174
        if (!empty($page)
175
            && (int)$page['doktype'] !== PageRepository::DOKTYPE_SYSFOLDER
176
            && !$this->isTableAllowedOnStandardPages()
177
            && $this->getModuleLoader()->hasComponentInDocHeader(\Fab\Vidi\View\Button\NewButton::class)) {
178
            $this->errors[] = sprintf(
179
                'The page with the id "%s" either has to be of the type "folder" (doktype=254) or the table "%s" has to be allowed on standard pages.',
180
                $this->configuredPid,
181
                $this->dataType
182
            );
183
        }
184
    }
185
186
    /**
187
     * Check if given table is allowed on standard pages
188
     *
189
     * @return bool
190
     * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages()
191
     */
192
    protected function isTableAllowedOnStandardPages(): bool
193
    {
194
        $allowedTables = explode(',', $GLOBALS['PAGES_TYPES']['default']['allowedTables']);
195
        return in_array($this->dataType, $allowedTables, true);
196
    }
197
198
    /**
199
     * Return the default configured pid.
200
     *
201
     * @return int
202
     */
203
    protected function getConfiguredPid(): int
204
    {
205
206
        if (GeneralUtility::_GP(Parameter::PID)) {
207
            $pid = GeneralUtility::_GP(Parameter::PID);
208
        } else {
209
210
            // Get pid from User TSConfig if any.
211
            $tsConfigPath = sprintf('tx_vidi.dataType.%s.storagePid', $this->dataType);
212
            $result = $this->getBackendUser()->getTSConfig($tsConfigPath);
213
            $configuredPid = (int)$result['value'];
214
215
            // If no pid is configured, use default pid from Module Loader
216
            $pid = ($configuredPid) ?: $this->getModuleLoader()->getDefaultPid();
217
        }
218
219
        return $pid;
220
    }
221
222
    /**
223
     * Return a pointer to the database.
224
     *
225
     * @return \Fab\Vidi\Database\DatabaseConnection
226
     */
227
    protected function getDatabaseConnection(): \Fab\Vidi\Database\DatabaseConnection
228
    {
229
        return $GLOBALS['TYPO3_DB'];
230
    }
231
232
    /**
233
     * Returns the page record of the configured pid
234
     *
235
     * @return array
236
     */
237
    public function getPage(): ?array
238
    {
239
        if ($this->page !== null) {
240
            return $this->page;
241
        }
242
243
        $query = $this->getQueryBuilder('pages');
244
        $query->getRestrictions()->removeAll(); // we are in BE context.
245
246
        $page = $query->select('doktype')
247
            ->from('pages')
248
            ->where('deleted = 0',
249
                'uid = ' . $this->configuredPid)
250
            ->execute()
251
            ->fetch();
252
253
        return is_array($page)
254
            ? $page
255
            : [];
256
    }
257
258
    /**
259
     * @param string $tableName
260
     * @return object|QueryBuilder
261
     */
262
    protected function getQueryBuilder($tableName): QueryBuilder
263
    {
264
        /** @var ConnectionPool $connectionPool */
265
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
266
        return $connectionPool->getQueryBuilderForTable($tableName);
267
    }
268
269
}
270