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