‪TYPO3CMS  10.4
ConfigurationStatus.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
27 use ‪TYPO3\CMS\Reports\Status as ReportStatus;
29 
34 {
40  public function ‪getStatus()
41  {
42  $statuses = [
43  'emptyReferenceIndex' => $this->‪getReferenceIndexStatus(),
44  ];
45  if ($this->‪isMemcachedUsed()) {
46  $statuses['memcachedConnection'] = $this->‪getMemcachedConnectionStatus();
47  }
49  $statuses['createdFilesWorldWritable'] = $this->‪getCreatedFilesWorldWritableStatus();
50  $statuses['createdDirectoriesWorldWritable'] = $this->‪getCreatedDirectoriesWorldWritableStatus();
51  }
52  if ($this->‪isMysqlUsed()) {
53  $statuses['mysqlDatabaseUsesUtf8'] = $this->‪getMysqlDatabaseUtf8Status();
54  }
55  return $statuses;
56  }
57 
63  protected function ‪getReferenceIndexStatus()
64  {
65  $value = $this->‪getLanguageService()->‪getLL('status_ok');
66  $message = '';
67  $severity = ReportStatus::OK;
68 
69  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
70  $count = $queryBuilder
71  ->count('*')
72  ->from('sys_refindex')
73  ->execute()
74  ->fetchColumn(0);
75 
76  $registry = GeneralUtility::makeInstance(Registry::class);
77  $lastRefIndexUpdate = $registry->get('core', 'sys_refindex_lastUpdate');
79  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
80  if (!$count && $lastRefIndexUpdate) {
81  $value = $this->‪getLanguageService()->‪getLL('status_empty');
82  $severity = ReportStatus::WARNING;
83  $url = (string)$uriBuilder->buildUriFromRoute('system_dbint') . '&id=0&SET[function]=refindex';
84  $message = sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.backend_reference_index'), '<a href="' . htmlspecialchars($url) . '">', '</a>', ‪BackendUtility::datetime($lastRefIndexUpdate));
85  }
86  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_referenceIndex'), $value, $message, $severity);
87  }
88 
94  protected function ‪isMemcachedUsed()
95  {
96  $memcachedUsed = false;
97  $memcachedServers = $this->‪getConfiguredMemcachedServers();
98  if (!empty($memcachedServers)) {
99  $memcachedUsed = true;
100  }
101  return $memcachedUsed;
102  }
103 
109  protected function ‪getConfiguredMemcachedServers()
110  {
111  $configurations = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] ?? [];
112  $memcachedServers = [];
113  foreach ($configurations as $table => $conf) {
114  if (is_array($conf)) {
115  foreach ($conf as $key => $value) {
116  if ($value === MemcachedBackend::class) {
117  $memcachedServers = $configurations[$table]['options']['servers'];
118  break;
119  }
120  }
121  }
122  }
123  return $memcachedServers;
124  }
125 
131  protected function ‪getMemcachedConnectionStatus()
132  {
133  $value = $this->‪getLanguageService()->‪getLL('status_ok');
134  $message = '';
135  $severity = ReportStatus::OK;
136  $failedConnections = [];
137  $defaultMemcachedPort = ini_get('memcache.default_port');
138  $memcachedServers = $this->‪getConfiguredMemcachedServers();
139  if (function_exists('memcache_connect') && is_array($memcachedServers)) {
140  foreach ($memcachedServers as $testServer) {
141  $configuredServer = $testServer;
142  if (strpos($testServer, 'unix://') === 0) {
143  $host = $testServer;
144  $port = 0;
145  } else {
146  if (strpos($testServer, 'tcp://') === 0) {
147  $testServer = substr($testServer, 6);
148  }
149  if (strpos($testServer, ':') !== false) {
150  [$host, $port] = explode(':', $testServer, 2);
151  } else {
152  $host = $testServer;
153  $port = $defaultMemcachedPort;
154  }
155  }
156  $memcachedConnection = @memcache_connect($host, $port);
157  if ($memcachedConnection != null) {
158  memcache_close();
159  } else {
160  $failedConnections[] = $configuredServer;
161  }
162  }
163  }
164  if (!empty($failedConnections)) {
165  $value = $this->‪getLanguageService()->‪getLL('status_connectionFailed');
166  $severity = ReportStatus::WARNING;
167  $message = $this->‪getLanguageService()->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.memcache_not_usable') . '<br /><br /><ul><li>' . implode('</li><li>', $failedConnections) . '</li></ul>';
168  }
169  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_memcachedConfiguration'), $value, $message, $severity);
170  }
171 
178  {
179  $value = $this->‪getLanguageService()->‪getLL('status_ok');
180  $message = '';
181  $severity = ReportStatus::OK;
182  if ((int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] % 10 & 2) {
183  $value = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'];
184  $severity = ReportStatus::WARNING;
185  $message = $this->‪getLanguageService()->‪getLL('status_CreatedFilePermissions.writable');
186  }
187  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_CreatedFilePermissions'), $value, $message, $severity);
188  }
189 
196  {
197  $value = $this->‪getLanguageService()->‪getLL('status_ok');
198  $message = '';
199  $severity = ReportStatus::OK;
200  if ((int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'] % 10 & 2) {
201  $value = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'];
202  $severity = ReportStatus::WARNING;
203  $message = $this->‪getLanguageService()->‪getLL('status_CreatedDirectoryPermissions.writable');
204  }
205  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_CreatedDirectoryPermissions'), $value, $message, $severity);
206  }
207 
213  protected function ‪isMysqlUsed()
214  {
215  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
216  ->getConnectionByName(‪ConnectionPool::DEFAULT_CONNECTION_NAME);
217 
218  return strpos($connection->getServerVersion(), 'MySQL') === 0;
219  }
220 
226  protected function ‪getMysqlDatabaseUtf8Status()
227  {
228  $collationConstraint = null;
229  $charset = '';
230  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
231  ->getConnectionByName(‪ConnectionPool::DEFAULT_CONNECTION_NAME);
233  $queryBuilder = $connection->createQueryBuilder();
234  $defaultDatabaseCharset = (string)$queryBuilder->select('DEFAULT_CHARACTER_SET_NAME')
235  ->from('information_schema.SCHEMATA')
236  ->where(
237  $queryBuilder->expr()->eq(
238  'SCHEMA_NAME',
239  $queryBuilder->createNamedParameter($connection->getDatabase(), \PDO::PARAM_STR)
240  )
241  )
242  ->setMaxResults(1)
243  ->execute()
244  ->fetchColumn();
245 
246  $severity = ReportStatus::OK;
247  $statusValue = $this->‪getLanguageService()->‪getLL('status_ok');
248  // also allow utf8mb4
249  if (strpos($defaultDatabaseCharset, 'utf8') !== 0) {
250  // If the default character set is e.g. latin1, BUT all tables in the system are UTF-8,
251  // we assume that TYPO3 has the correct charset for adding tables, and everything is fine
252  $queryBuilder = $connection->createQueryBuilder();
253  $nonUtf8TableCollationsFound = $queryBuilder->select('table_collation')
254  ->from('information_schema.tables')
255  ->where(
256  $queryBuilder->expr()->andX(
257  $queryBuilder->expr()->eq('table_schema', $queryBuilder->quote($connection->getDatabase())),
258  $queryBuilder->expr()->notLike('table_collation', $queryBuilder->quote('utf8%'))
259  )
260  )
261  ->setMaxResults(1)
262  ->execute();
263 
264  if ($nonUtf8TableCollationsFound->rowCount() > 0) {
265  $message = sprintf($this->‪getLanguageService()
266  ->getLL('status_MysqlDatabaseCharacterSet_Unsupported'), $defaultDatabaseCharset);
267  $severity = ReportStatus::ERROR;
268  $statusValue = $this->‪getLanguageService()->‪getLL('status_wrongValue');
269  } else {
270  $message = $this->‪getLanguageService()->‪getLL('status_MysqlDatabaseCharacterSet_Info');
271  $severity = ReportStatus::INFO;
272  $statusValue = $this->‪getLanguageService()->‪getLL('status_info');
273  }
274  } elseif (isset(‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][‪ConnectionPool::DEFAULT_CONNECTION_NAME]['tableoptions'])) {
275  $message = $this->‪getLanguageService()->‪getLL('status_MysqlDatabaseCharacterSet_Ok');
276 
277  $tableOptions = ‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][‪ConnectionPool::DEFAULT_CONNECTION_NAME]['tableoptions'];
278  if (isset($tableOptions['collate'])) {
279  $collationConstraint = $queryBuilder->expr()->neq('table_collation', $queryBuilder->quote($tableOptions['collate']));
280  $charset = $tableOptions['collate'];
281  } elseif (isset($tableOptions['charset'])) {
282  $collationConstraint = $queryBuilder->expr()->notLike('table_collation', $queryBuilder->quote($tableOptions['charset'] . '%'));
283  $charset = $tableOptions['charset'];
284  }
285 
286  if (isset($collationConstraint)) {
287  $queryBuilder = $connection->createQueryBuilder();
288  $wrongCollationTablesFound = $queryBuilder->select('table_collation')
289  ->from('information_schema.tables')
290  ->where(
291  $queryBuilder->expr()->andX(
292  $queryBuilder->expr()->eq('table_schema', $queryBuilder->quote($connection->getDatabase())),
293  $collationConstraint
294  )
295  )
296  ->setMaxResults(1)
297  ->execute();
298 
299  if ($wrongCollationTablesFound->rowCount() > 0) {
300  $message = sprintf($this->‪getLanguageService()->getLL('status_MysqlDatabaseCharacterSet_MixedCollations'), $charset);
301  $severity = ReportStatus::ERROR;
302  $statusValue = $this->‪getLanguageService()->‪getLL('status_checkFailed');
303  } else {
304  if (isset($tableOptions['collate'])) {
305  $collationConstraint = $queryBuilder->expr()->neq('collation_name', $queryBuilder->quote($tableOptions['collate']));
306  } elseif (isset($tableOptions['charset'])) {
307  $collationConstraint = $queryBuilder->expr()->notLike('collation_name', $queryBuilder->quote($tableOptions['charset'] . '%'));
308  }
309 
310  $queryBuilder = $connection->createQueryBuilder();
311  $wrongCollationColumnsFound = $queryBuilder->select('collation_name')
312  ->from('information_schema.columns')
313  ->where(
314  $queryBuilder->expr()->andX(
315  $queryBuilder->expr()->eq('table_schema', $queryBuilder->quote($connection->getDatabase())),
316  $collationConstraint
317  )
318  )
319  ->setMaxResults(1)
320  ->execute();
321 
322  if ($wrongCollationColumnsFound->rowCount() > 0) {
323  $message = sprintf($this->‪getLanguageService()->getLL('status_MysqlDatabaseCharacterSet_MixedCollations'), $charset);
324  $severity = ReportStatus::ERROR;
325  $statusValue = $this->‪getLanguageService()->‪getLL('status_checkFailed');
326  }
327  }
328  }
329  } else {
330  $message = $this->‪getLanguageService()->‪getLL('status_MysqlDatabaseCharacterSet_Ok');
331  }
332 
333  return GeneralUtility::makeInstance(
334  ReportStatus::class,
335  $this->‪getLanguageService()->getLL('status_MysqlDatabaseCharacterSet'),
336  $statusValue,
337  $message,
338  $severity
339  );
340  }
341 
345  protected function ‪getLanguageService()
346  {
347  return ‪$GLOBALS['LANG'];
348  }
349 }
‪TYPO3\CMS\Reports\StatusProviderInterface
Definition: StatusProviderInterface.php:22
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\isMysqlUsed
‪bool isMysqlUsed()
Definition: ConfigurationStatus.php:213
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getMemcachedConnectionStatus
‪TYPO3 CMS Reports Status getMemcachedConnectionStatus()
Definition: ConfigurationStatus.php:131
‪TYPO3\CMS\Backend\Utility\BackendUtility\datetime
‪static string datetime($value)
Definition: BackendUtility.php:989
‪TYPO3\CMS\Core\Registry
Definition: Registry.php:33
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getCreatedFilesWorldWritableStatus
‪TYPO3 CMS Reports Status getCreatedFilesWorldWritableStatus()
Definition: ConfigurationStatus.php:177
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:292
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\isMemcachedUsed
‪bool isMemcachedUsed()
Definition: ConfigurationStatus.php:94
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus
Definition: ConfigurationStatus.php:34
‪TYPO3\CMS\Core\Database\ConnectionPool\DEFAULT_CONNECTION_NAME
‪const DEFAULT_CONNECTION_NAME
Definition: ConnectionPool.php:50
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Reports\Status
Definition: Status.php:24
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getLanguageService
‪LanguageService getLanguageService()
Definition: ConfigurationStatus.php:345
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:38
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getMysqlDatabaseUtf8Status
‪ReportStatus getMysqlDatabaseUtf8Status()
Definition: ConfigurationStatus.php:226
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getConfiguredMemcachedServers
‪array getConfiguredMemcachedServers()
Definition: ConfigurationStatus.php:109
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getReferenceIndexStatus
‪TYPO3 CMS Reports Status getReferenceIndexStatus()
Definition: ConfigurationStatus.php:63
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Reports\Report\Status
Definition: ConfigurationStatus.php:16
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Cache\Backend\MemcachedBackend
Definition: MemcachedBackend.php:46
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:154
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getCreatedDirectoriesWorldWritableStatus
‪TYPO3 CMS Reports Status getCreatedDirectoriesWorldWritableStatus()
Definition: ConfigurationStatus.php:195
‪TYPO3\CMS\Reports\Report\Status\ConfigurationStatus\getStatus
‪array getStatus()
Definition: ConfigurationStatus.php:40