| Total Complexity | 86 |
| Total Lines | 800 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Complex classes like Check often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Check, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 54 | class Check implements CheckInterface |
||
| 55 | { |
||
| 56 | /** |
||
| 57 | * @var FlashMessageQueue |
||
| 58 | */ |
||
| 59 | protected $messageQueue; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * @var array List of required PHP extensions |
||
| 63 | */ |
||
| 64 | protected $requiredPhpExtensions = [ |
||
| 65 | 'filter', |
||
| 66 | 'gd', |
||
| 67 | 'hash', |
||
| 68 | 'json', |
||
| 69 | 'libxml', |
||
| 70 | 'PDO', |
||
| 71 | 'session', |
||
| 72 | 'SPL', |
||
| 73 | 'standard', |
||
| 74 | 'xml', |
||
| 75 | 'zip', |
||
| 76 | 'zlib', |
||
| 77 | ]; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * @var string[] |
||
| 81 | */ |
||
| 82 | protected $suggestedPhpExtensions = [ |
||
| 83 | 'fileinfo' => 'This extension is used for proper file type detection in the File Abstraction Layer.', |
||
| 84 | 'intl' => 'This extension is used for correct language and locale handling.', |
||
| 85 | 'openssl' => 'This extension is used for sending SMTP mails over an encrypted channel endpoint, and for extensions such as "rsaauth".' |
||
| 86 | ]; |
||
| 87 | |||
| 88 | public function __construct() |
||
| 89 | { |
||
| 90 | $this->messageQueue = new FlashMessageQueue('install'); |
||
| 91 | } |
||
| 92 | |||
| 93 | public function getMessageQueue(): FlashMessageQueue |
||
| 94 | { |
||
| 95 | return $this->messageQueue; |
||
| 96 | } |
||
| 97 | |||
| 98 | /** |
||
| 99 | * Get all status information as array with status objects |
||
| 100 | * |
||
| 101 | * @return FlashMessageQueue |
||
| 102 | */ |
||
| 103 | public function getStatus(): FlashMessageQueue |
||
| 104 | { |
||
| 105 | $this->checkCurrentDirectoryIsInIncludePath(); |
||
| 106 | $this->checkFileUploadEnabled(); |
||
| 107 | $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize(); |
||
| 108 | $this->checkMemorySettings(); |
||
| 109 | $this->checkPhpVersion(); |
||
| 110 | $this->checkMaxExecutionTime(); |
||
| 111 | $this->checkDisableFunctions(); |
||
| 112 | $this->checkDocRoot(); |
||
| 113 | $this->checkOpenBaseDir(); |
||
| 114 | $this->checkXdebugMaxNestingLevel(); |
||
| 115 | |||
| 116 | $this->checkMaxInputVars(); |
||
| 117 | $this->checkReflectionDocComment(); |
||
| 118 | $this->checkWindowsApacheThreadStackSize(); |
||
| 119 | |||
| 120 | foreach ($this->requiredPhpExtensions as $extension) { |
||
| 121 | $this->checkPhpExtension($extension); |
||
| 122 | } |
||
| 123 | |||
| 124 | foreach ($this->suggestedPhpExtensions as $extension => $purpose) { |
||
| 125 | $this->checkPhpExtension($extension, false, $purpose); |
||
| 126 | } |
||
| 127 | |||
| 128 | $this->checkPcreVersion(); |
||
| 129 | $this->checkGdLibTrueColorSupport(); |
||
| 130 | $this->checkGdLibGifSupport(); |
||
| 131 | $this->checkGdLibJpgSupport(); |
||
| 132 | $this->checkGdLibPngSupport(); |
||
| 133 | $this->checkGdLibFreeTypeSupport(); |
||
| 134 | |||
| 135 | return $this->messageQueue; |
||
| 136 | } |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Checks if current directory (.) is in PHP include path |
||
| 140 | */ |
||
| 141 | protected function checkCurrentDirectoryIsInIncludePath() |
||
| 142 | { |
||
| 143 | $includePath = (string)ini_get('include_path'); |
||
| 144 | $delimiter = $this->isWindowsOs() ? ';' : ':'; |
||
| 145 | $pathArray = $this->trimExplode($delimiter, $includePath); |
||
| 146 | if (!in_array('.', $pathArray)) { |
||
| 147 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 148 | 'include_path = ' . implode(' ', $pathArray) . LF |
||
| 149 | . 'Normally the current path \'.\' is included in the' |
||
| 150 | . ' include_path of PHP. Although TYPO3 does not rely on this,' |
||
| 151 | . ' it is an unusual setting that may introduce problems for' |
||
| 152 | . ' some extensions.', |
||
| 153 | 'Current directory (./) is not within PHP include path', |
||
| 154 | FlashMessage::WARNING |
||
| 155 | )); |
||
| 156 | } else { |
||
| 157 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 158 | '', |
||
| 159 | 'Current directory (./) is within PHP include path.' |
||
| 160 | )); |
||
| 161 | } |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Check if file uploads are enabled in PHP |
||
| 166 | */ |
||
| 167 | protected function checkFileUploadEnabled() |
||
| 168 | { |
||
| 169 | if (!ini_get('file_uploads')) { |
||
| 170 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 171 | 'file_uploads=' . ini_get('file_uploads') . LF |
||
| 172 | . 'TYPO3 uses the ability to upload files from the browser in various cases.' |
||
| 173 | . ' If this flag is disabled in PHP, you won\'t be able to upload files.' |
||
| 174 | . ' But it doesn\'t end here, because not only are files not accepted by' |
||
| 175 | . ' the server - ALL content in the forms are discarded and therefore' |
||
| 176 | . ' nothing at all will be editable if you don\'t set this flag!', |
||
| 177 | 'File uploads not allowed in PHP', |
||
| 178 | FlashMessage::ERROR |
||
| 179 | )); |
||
| 180 | } else { |
||
| 181 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 182 | '', |
||
| 183 | 'File uploads allowed in PHP' |
||
| 184 | )); |
||
| 185 | } |
||
| 186 | } |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Check maximum post upload size correlates with maximum file upload |
||
| 190 | */ |
||
| 191 | protected function checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize() |
||
| 192 | { |
||
| 193 | $maximumUploadFilesize = $this->getBytesFromSizeMeasurement((string)ini_get('upload_max_filesize')); |
||
| 194 | $maximumPostSize = $this->getBytesFromSizeMeasurement((string)ini_get('post_max_size')); |
||
| 195 | if ($maximumPostSize > 0 && $maximumPostSize < $maximumUploadFilesize) { |
||
| 196 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 197 | 'upload_max_filesize=' . ini_get('upload_max_filesize') . LF |
||
| 198 | . 'post_max_size=' . ini_get('post_max_size') . LF |
||
| 199 | . 'You have defined a maximum size for file uploads in PHP which' |
||
| 200 | . ' exceeds the allowed size for POST requests. Therefore the' |
||
| 201 | . ' file uploads can also not be larger than ' . ini_get('post_max_size') . '.', |
||
| 202 | 'Maximum size for POST requests is smaller than maximum upload filesize in PHP', |
||
| 203 | FlashMessage::ERROR |
||
| 204 | )); |
||
| 205 | } elseif ($maximumPostSize === $maximumUploadFilesize) { |
||
| 206 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 207 | 'The maximum size for file uploads is set to ' . ini_get('upload_max_filesize'), |
||
| 208 | 'Maximum post upload size correlates with maximum upload file size in PHP' |
||
| 209 | )); |
||
| 210 | } else { |
||
| 211 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 212 | 'The maximum size for file uploads is set to ' . ini_get('upload_max_filesize'), |
||
| 213 | 'Maximum post upload size is higher than maximum upload file size in PHP, which is fine.' |
||
| 214 | )); |
||
| 215 | } |
||
| 216 | } |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Check memory settings |
||
| 220 | */ |
||
| 221 | protected function checkMemorySettings() |
||
| 222 | { |
||
| 223 | $minimumMemoryLimit = 64; |
||
| 224 | $recommendedMemoryLimit = 128; |
||
| 225 | $memoryLimit = $this->getBytesFromSizeMeasurement((string)ini_get('memory_limit')); |
||
| 226 | if ($memoryLimit <= 0) { |
||
| 227 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 228 | 'PHP is configured not to limit memory usage at all. This is a risk' |
||
| 229 | . ' and should be avoided in production setup. In general it\'s best practice to limit this.' |
||
| 230 | . ' To be safe, set a limit in PHP, but with a minimum of ' . $recommendedMemoryLimit . 'MB:' . LF |
||
| 231 | . 'memory_limit=' . $recommendedMemoryLimit . 'M', |
||
| 232 | 'Unlimited memory limit for PHP', |
||
| 233 | FlashMessage::WARNING |
||
| 234 | )); |
||
| 235 | } elseif ($memoryLimit < 1024 * 1024 * $minimumMemoryLimit) { |
||
| 236 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 237 | 'memory_limit=' . ini_get('memory_limit') . LF |
||
| 238 | . 'Your system is configured to enforce a memory limit for PHP scripts lower than ' |
||
| 239 | . $minimumMemoryLimit . 'MB. It is required to raise the limit.' |
||
| 240 | . ' We recommend a minimum PHP memory limit of ' . $recommendedMemoryLimit . 'MB:' . LF |
||
| 241 | . 'memory_limit=' . $recommendedMemoryLimit . 'M', |
||
| 242 | 'PHP Memory limit below ' . $minimumMemoryLimit . 'MB', |
||
| 243 | FlashMessage::ERROR |
||
| 244 | )); |
||
| 245 | } elseif ($memoryLimit < 1024 * 1024 * $recommendedMemoryLimit) { |
||
| 246 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 247 | 'memory_limit=' . ini_get('memory_limit') . LF |
||
| 248 | . 'Your system is configured to enforce a memory limit for PHP scripts lower than ' |
||
| 249 | . $recommendedMemoryLimit . 'MB.' |
||
| 250 | . ' A slim TYPO3 instance without many extensions will probably work, but you should monitor your' |
||
| 251 | . ' system for "allowed memory size of X bytes exhausted" messages, especially if using the backend.' |
||
| 252 | . ' To be on the safe side, we recommend a minimum PHP memory limit of ' |
||
| 253 | . $recommendedMemoryLimit . 'MB:' . LF |
||
| 254 | . 'memory_limit=' . $recommendedMemoryLimit . 'M', |
||
| 255 | 'PHP Memory limit below ' . $recommendedMemoryLimit . 'MB', |
||
| 256 | FlashMessage::WARNING |
||
| 257 | )); |
||
| 258 | } else { |
||
| 259 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 260 | '', |
||
| 261 | 'PHP Memory limit is equal to or more than ' . $recommendedMemoryLimit . 'MB' |
||
| 262 | )); |
||
| 263 | } |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Check minimum PHP version |
||
| 268 | */ |
||
| 269 | protected function checkPhpVersion() |
||
| 270 | { |
||
| 271 | $minimumPhpVersion = '7.2.0'; |
||
| 272 | $currentPhpVersion = PHP_VERSION; |
||
| 273 | if (version_compare($currentPhpVersion, $minimumPhpVersion) < 0) { |
||
| 274 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 275 | 'Your PHP version ' . $currentPhpVersion . ' is too old. TYPO3 CMS does not run' |
||
| 276 | . ' with this version. Update to at least PHP ' . $minimumPhpVersion, |
||
| 277 | 'PHP version too low', |
||
| 278 | FlashMessage::ERROR |
||
| 279 | )); |
||
| 280 | } else { |
||
| 281 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 282 | '', |
||
| 283 | 'PHP version is fine' |
||
| 284 | )); |
||
| 285 | } |
||
| 286 | } |
||
| 287 | |||
| 288 | /** |
||
| 289 | * Check PRCE module is loaded and minimum version |
||
| 290 | */ |
||
| 291 | protected function checkPcreVersion() |
||
| 292 | { |
||
| 293 | $minimumPcreVersion = '8.38'; |
||
| 294 | if (!extension_loaded('pcre')) { |
||
| 295 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 296 | 'TYPO3 CMS uses PHP extension pcre but it is not loaded' |
||
| 297 | . ' in your environment. Change your environment to provide this extension' |
||
| 298 | . ' in with minimum version ' . $minimumPcreVersion . '.', |
||
| 299 | 'PHP extension pcre not loaded', |
||
| 300 | FlashMessage::ERROR |
||
| 301 | )); |
||
| 302 | } else { |
||
| 303 | $installedPcreVersionString = trim(PCRE_VERSION); // '8.39 2016-06-14' |
||
| 304 | $mainPcreVersionString = explode(' ', $installedPcreVersionString); |
||
| 305 | $mainPcreVersionString = $mainPcreVersionString[0]; // '8.39' |
||
| 306 | if (version_compare($mainPcreVersionString, $minimumPcreVersion) < 0) { |
||
| 307 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 308 | 'Your PCRE version ' . PCRE_VERSION . ' is too old. TYPO3 CMS may trigger PHP segmentantion' |
||
| 309 | . ' faults with this version. Update to at least PCRE ' . $minimumPcreVersion, |
||
| 310 | 'PCRE version too low', |
||
| 311 | FlashMessage::ERROR |
||
| 312 | )); |
||
| 313 | } else { |
||
| 314 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 315 | '', |
||
| 316 | 'PHP extension PCRE is loaded and version is fine' |
||
| 317 | )); |
||
| 318 | } |
||
| 319 | } |
||
| 320 | } |
||
| 321 | |||
| 322 | /** |
||
| 323 | * Check maximum execution time |
||
| 324 | */ |
||
| 325 | protected function checkMaxExecutionTime() |
||
| 326 | { |
||
| 327 | $minimumMaximumExecutionTime = 30; |
||
| 328 | $recommendedMaximumExecutionTime = 240; |
||
| 329 | $currentMaximumExecutionTime = ini_get('max_execution_time'); |
||
| 330 | if ($currentMaximumExecutionTime == 0) { |
||
| 331 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 332 | 'max_execution_time=0' . LF |
||
| 333 | . 'While TYPO3 is fine with this, you risk a denial-of-service for your system if for whatever' |
||
| 334 | . ' reason some script hangs in an infinite loop. You are usually on the safe side ' |
||
| 335 | . ' if it is reduced to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF |
||
| 336 | . 'max_execution_time=' . $recommendedMaximumExecutionTime, |
||
| 337 | 'Infinite PHP script execution time', |
||
| 338 | FlashMessage::WARNING |
||
| 339 | )); |
||
| 340 | } elseif ($currentMaximumExecutionTime < $minimumMaximumExecutionTime) { |
||
| 341 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 342 | 'max_execution_time=' . $currentMaximumExecutionTime . LF |
||
| 343 | . 'Your max_execution_time is too low. Some expensive operations in TYPO3 can take longer than that.' |
||
| 344 | . ' It is recommended to raise the limit to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF |
||
| 345 | . 'max_execution_time=' . $recommendedMaximumExecutionTime, |
||
| 346 | 'Low PHP script execution time', |
||
| 347 | FlashMessage::ERROR |
||
| 348 | )); |
||
| 349 | } elseif ($currentMaximumExecutionTime < $recommendedMaximumExecutionTime) { |
||
| 350 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 351 | 'max_execution_time=' . $currentMaximumExecutionTime . LF |
||
| 352 | . 'Your max_execution_time is low. While TYPO3 often runs without problems' |
||
| 353 | . ' with ' . $minimumMaximumExecutionTime . ' seconds,' |
||
| 354 | . ' it may still happen that script execution is stopped before finishing' |
||
| 355 | . ' calculations. You should monitor the system for messages in this area' |
||
| 356 | . ' and maybe raise the limit to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF |
||
| 357 | . 'max_execution_time=' . $recommendedMaximumExecutionTime, |
||
| 358 | 'Low PHP script execution time', |
||
| 359 | FlashMessage::WARNING |
||
| 360 | )); |
||
| 361 | } else { |
||
| 362 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 363 | '', |
||
| 364 | 'Maximum PHP script execution time is equal to or more than ' . $recommendedMaximumExecutionTime |
||
| 365 | )); |
||
| 366 | } |
||
| 367 | } |
||
| 368 | |||
| 369 | /** |
||
| 370 | * Check for disabled functions |
||
| 371 | */ |
||
| 372 | protected function checkDisableFunctions() |
||
| 373 | { |
||
| 374 | $disabledFunctions = trim((string)ini_get('disable_functions')); |
||
| 375 | |||
| 376 | // Filter "disable_functions" |
||
| 377 | $disabledFunctionsArray = $this->trimExplode(',', $disabledFunctions); |
||
| 378 | |||
| 379 | // Array with strings to find |
||
| 380 | $findStrings = [ |
||
| 381 | // Disabled by default on Ubuntu OS but this is okay since the Core does not use them |
||
| 382 | 'pcntl_', |
||
| 383 | ]; |
||
| 384 | foreach ($disabledFunctionsArray as $key => $disabledFunction) { |
||
| 385 | foreach ($findStrings as $findString) { |
||
| 386 | if (strpos($disabledFunction, $findString) !== false) { |
||
| 387 | unset($disabledFunctionsArray[$key]); |
||
| 388 | } |
||
| 389 | } |
||
| 390 | } |
||
| 391 | |||
| 392 | if ($disabledFunctions !== '') { |
||
| 393 | if (!empty($disabledFunctionsArray)) { |
||
| 394 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 395 | 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . LF |
||
| 396 | . 'These function(s) are disabled. TYPO3 uses some of those, so there might be trouble.' |
||
| 397 | . ' TYPO3 is designed to use the default set of PHP functions plus some common extensions.' |
||
| 398 | . ' Possibly these functions are disabled' |
||
| 399 | . ' due to security considerations and most likely the list would include a function like' |
||
| 400 | . ' exec() which is used by TYPO3 at various places. Depending on which exact functions' |
||
| 401 | . ' are disabled, some parts of the system may just break without further notice.', |
||
| 402 | 'Some PHP functions disabled', |
||
| 403 | FlashMessage::ERROR |
||
| 404 | )); |
||
| 405 | } else { |
||
| 406 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 407 | 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . LF |
||
| 408 | . 'These function(s) are disabled. TYPO3 uses currently none of those, so you are good to go.', |
||
| 409 | 'Some PHP functions currently disabled but OK' |
||
| 410 | )); |
||
| 411 | } |
||
| 412 | } else { |
||
| 413 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 414 | '', |
||
| 415 | 'No disabled PHP functions' |
||
| 416 | )); |
||
| 417 | } |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * Check for doc_root ini setting |
||
| 422 | */ |
||
| 423 | protected function checkDocRoot() |
||
| 424 | { |
||
| 425 | $docRootSetting = trim((string)ini_get('doc_root')); |
||
| 426 | if ($docRootSetting !== '') { |
||
| 427 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 428 | 'doc_root=' . $docRootSetting . LF |
||
| 429 | . 'PHP cannot execute scripts' |
||
| 430 | . ' outside this directory. This setting is seldom used and must correlate' |
||
| 431 | . ' with your actual document root. You might be in trouble if your' |
||
| 432 | . ' TYPO3 CMS core code is linked to some different location.' |
||
| 433 | . ' If that is a problem, the setting must be changed.', |
||
| 434 | 'doc_root is set', |
||
| 435 | FlashMessage::NOTICE |
||
| 436 | )); |
||
| 437 | } else { |
||
| 438 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 439 | '', |
||
| 440 | 'PHP doc_root is not set' |
||
| 441 | )); |
||
| 442 | } |
||
| 443 | } |
||
| 444 | |||
| 445 | /** |
||
| 446 | * Check open_basedir |
||
| 447 | */ |
||
| 448 | protected function checkOpenBaseDir() |
||
| 465 | )); |
||
| 466 | } |
||
| 467 | } |
||
| 468 | |||
| 469 | /** |
||
| 470 | * If xdebug is loaded, the default max_nesting_level of 100 must be raised |
||
| 471 | */ |
||
| 472 | protected function checkXdebugMaxNestingLevel() |
||
| 473 | { |
||
| 474 | if (extension_loaded('xdebug')) { |
||
| 475 | $recommendedMaxNestingLevel = 400; |
||
| 476 | $errorThreshold = 250; |
||
| 477 | $currentMaxNestingLevel = ini_get('xdebug.max_nesting_level'); |
||
| 478 | if ($currentMaxNestingLevel < $errorThreshold) { |
||
| 479 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 480 | 'xdebug.max_nesting_level=' . $currentMaxNestingLevel . LF |
||
| 481 | . 'This setting controls the maximum number of nested function calls to protect against' |
||
| 482 | . ' infinite recursion. The current value is too low for TYPO3 CMS and must' |
||
| 483 | . ' be either raised or xdebug has to be unloaded. A value of ' . $recommendedMaxNestingLevel |
||
| 484 | . ' is recommended. Warning: Expect fatal PHP errors in central parts of the CMS' |
||
| 485 | . ' if the value is not raised significantly to:' . LF |
||
| 486 | . 'xdebug.max_nesting_level=' . $recommendedMaxNestingLevel, |
||
| 487 | 'PHP xdebug.max_nesting_level is critically low', |
||
| 488 | FlashMessage::ERROR |
||
| 489 | )); |
||
| 490 | } elseif ($currentMaxNestingLevel < $recommendedMaxNestingLevel) { |
||
| 491 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 492 | 'xdebug.max_nesting_level=' . $currentMaxNestingLevel . LF |
||
| 493 | . 'This setting controls the maximum number of nested function calls to protect against' |
||
| 494 | . ' infinite recursion. The current value is high enough for the TYPO3 CMS core to work' |
||
| 495 | . ' fine, but still some extensions could raise fatal PHP errors if the setting is not' |
||
| 496 | . ' raised further. A value of ' . $recommendedMaxNestingLevel . ' is recommended.' . LF |
||
| 497 | . 'xdebug.max_nesting_level=' . $recommendedMaxNestingLevel, |
||
| 498 | 'PHP xdebug.max_nesting_level is low', |
||
| 499 | FlashMessage::WARNING |
||
| 500 | )); |
||
| 501 | } else { |
||
| 502 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 503 | '', |
||
| 504 | 'PHP xdebug.max_nesting_level ok' |
||
| 505 | )); |
||
| 506 | } |
||
| 507 | } else { |
||
| 508 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 509 | '', |
||
| 510 | 'PHP xdebug extension not loaded' |
||
| 511 | )); |
||
| 512 | } |
||
| 513 | } |
||
| 514 | |||
| 515 | /** |
||
| 516 | * Get max_input_vars status |
||
| 517 | */ |
||
| 518 | protected function checkMaxInputVars() |
||
| 519 | { |
||
| 520 | $recommendedMaxInputVars = 1500; |
||
| 521 | $minimumMaxInputVars = 1000; |
||
| 522 | $currentMaxInputVars = ini_get('max_input_vars'); |
||
| 523 | |||
| 524 | if ($currentMaxInputVars < $minimumMaxInputVars) { |
||
| 525 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 526 | 'max_input_vars=' . $currentMaxInputVars . LF |
||
| 527 | . 'This setting can lead to lost information if submitting forms with lots of data in TYPO3 CMS' |
||
| 528 | . ' (as the install tool does). It is highly recommended to raise this' |
||
| 529 | . ' to at least ' . $recommendedMaxInputVars . ':' . LF |
||
| 530 | . 'max_input_vars=' . $recommendedMaxInputVars, |
||
| 531 | 'PHP max_input_vars too low', |
||
| 532 | FlashMessage::ERROR |
||
| 533 | )); |
||
| 534 | } elseif ($currentMaxInputVars < $recommendedMaxInputVars) { |
||
| 535 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 536 | 'max_input_vars=' . $currentMaxInputVars . LF |
||
| 537 | . 'This setting can lead to lost information if submitting forms with lots of data in TYPO3 CMS' |
||
| 538 | . ' (as the install tool does). It is highly recommended to raise this' |
||
| 539 | . ' to at least ' . $recommendedMaxInputVars . ':' . LF |
||
| 540 | . 'max_input_vars=' . $recommendedMaxInputVars, |
||
| 541 | 'PHP max_input_vars very low', |
||
| 542 | FlashMessage::WARNING |
||
| 543 | )); |
||
| 544 | } else { |
||
| 545 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 546 | '', |
||
| 547 | 'PHP max_input_vars ok' |
||
| 548 | )); |
||
| 549 | } |
||
| 550 | } |
||
| 551 | |||
| 552 | /** |
||
| 553 | * Check doc comments can be fetched by reflection |
||
| 554 | */ |
||
| 555 | protected function checkReflectionDocComment() |
||
| 556 | { |
||
| 557 | $testReflection = new \ReflectionMethod(static::class, __FUNCTION__); |
||
| 558 | if ($testReflection->getDocComment() === false) { |
||
| 559 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 560 | 'TYPO3 CMS core extensions like extbase and fluid heavily rely on method' |
||
| 561 | . ' comment parsing to fetch annotations and add magic belonging to them.' |
||
| 562 | . ' This does not work in the current environment and so we cannot install' |
||
| 563 | . ' TYPO3 CMS.' . LF |
||
| 564 | . ' Here are some possibilities: ' . LF |
||
| 565 | . '* In Zend OPcache you can disable saving/loading comments. If you are using' |
||
| 566 | . ' Zend OPcache (included since PHP 5.5) then check your php.ini settings for' |
||
| 567 | . ' opcache.save_comments and opcache.load_comments and enable them.' . LF |
||
| 568 | . '* In Zend Optimizer+ you can disable saving comments. If you are using' |
||
| 569 | . ' Zend Optimizer+ then check your php.ini settings for' |
||
| 570 | . ' zend_optimizerplus.save_comments and enable it.' . LF |
||
| 571 | . '* The PHP extension eaccelerator is known to break this if' |
||
| 572 | . ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.' |
||
| 573 | . ' This compile flag must be specified, otherwise TYPO3 CMS will not work.' . LF |
||
| 574 | . 'For more information take a look in our wiki ' . Typo3Information::URL_OPCACHE . '.', |
||
| 575 | 'PHP Doc comment reflection broken', |
||
| 576 | FlashMessage::ERROR |
||
| 577 | )); |
||
| 578 | } else { |
||
| 579 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 580 | '', |
||
| 581 | 'PHP Doc comment reflection works' |
||
| 582 | )); |
||
| 583 | } |
||
| 584 | } |
||
| 585 | |||
| 586 | /** |
||
| 587 | * Checks thread stack size if on windows with apache |
||
| 588 | */ |
||
| 589 | protected function checkWindowsApacheThreadStackSize() |
||
| 590 | { |
||
| 591 | if ($this->isWindowsOs() |
||
| 592 | && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === 0 |
||
| 593 | ) { |
||
| 594 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 595 | 'This current value cannot be checked by the system, so please ignore this warning if it' |
||
| 596 | . ' is already taken care of: Fluid uses complex regular expressions which require a lot' |
||
| 597 | . ' of stack space during the first processing.' |
||
| 598 | . ' On Windows the default stack size for Apache is a lot smaller than on UNIX.' |
||
| 599 | . ' You can increase the size to 8MB (default on UNIX) by adding the following configuration' |
||
| 600 | . ' to httpd.conf and restarting Apache afterwards:' . LF |
||
| 601 | . '<IfModule mpm_winnt_module>ThreadStackSize 8388608</IfModule>', |
||
| 602 | 'Windows apache thread stack size', |
||
| 603 | FlashMessage::WARNING |
||
| 604 | )); |
||
| 605 | } else { |
||
| 606 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 607 | '', |
||
| 608 | 'Apache ThreadStackSize is not an issue on UNIX systems' |
||
| 609 | )); |
||
| 610 | } |
||
| 611 | } |
||
| 612 | |||
| 613 | /** |
||
| 614 | * Checks if a specific PHP extension is loaded. |
||
| 615 | * |
||
| 616 | * @param string $extension |
||
| 617 | * @param bool $required |
||
| 618 | * @param string $purpose |
||
| 619 | */ |
||
| 620 | public function checkPhpExtension(string $extension, bool $required = true, string $purpose = '') |
||
| 621 | { |
||
| 622 | if (!extension_loaded($extension)) { |
||
| 623 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 624 | 'TYPO3 uses the PHP extension "' . $extension . '" but it is not loaded' |
||
| 625 | . ' in your environment. Change your environment to provide this extension. ' |
||
| 626 | . $purpose, |
||
| 627 | 'PHP extension "' . $extension . '" not loaded', |
||
| 628 | $required ? FlashMessage::ERROR : FlashMessage::WARNING |
||
| 629 | )); |
||
| 630 | } else { |
||
| 631 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 632 | '', |
||
| 633 | 'PHP extension "' . $extension . '" loaded' |
||
| 634 | )); |
||
| 635 | } |
||
| 636 | } |
||
| 637 | |||
| 638 | /** |
||
| 639 | * Check imagecreatetruecolor to verify gdlib works as expected |
||
| 640 | */ |
||
| 641 | protected function checkGdLibTrueColorSupport() |
||
| 642 | { |
||
| 643 | if (function_exists('imagecreatetruecolor')) { |
||
| 644 | $imageResource = @imagecreatetruecolor(50, 100); |
||
| 645 | if ($this->checkImageResource($imageResource)) { |
||
| 646 | imagedestroy($imageResource); |
||
|
|
|||
| 647 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 648 | '', |
||
| 649 | 'PHP GD library true color works' |
||
| 650 | )); |
||
| 651 | } else { |
||
| 652 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 653 | 'GD is loaded, but calling imagecreatetruecolor() fails.' |
||
| 654 | . ' This must be fixed, TYPO3 CMS won\'t work well otherwise.', |
||
| 655 | 'PHP GD library true color support broken', |
||
| 656 | FlashMessage::ERROR |
||
| 657 | )); |
||
| 658 | } |
||
| 659 | } else { |
||
| 660 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 661 | 'Gdlib is essential for TYPO3 CMS to work properly.', |
||
| 662 | 'PHP GD library true color support missing', |
||
| 663 | FlashMessage::ERROR |
||
| 664 | )); |
||
| 665 | } |
||
| 666 | } |
||
| 667 | |||
| 668 | /** |
||
| 669 | * Check gif support of GD library |
||
| 670 | */ |
||
| 671 | protected function checkGdLibGifSupport() |
||
| 672 | { |
||
| 673 | if (function_exists('imagecreatefromgif') |
||
| 674 | && function_exists('imagegif') |
||
| 675 | && (imagetypes() & IMG_GIF) |
||
| 676 | ) { |
||
| 677 | // Do not use data:// wrapper to be independent of allow_url_fopen |
||
| 678 | $imageResource = @imagecreatefromgif(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.gif'); |
||
| 679 | if ($this->checkImageResource($imageResource)) { |
||
| 680 | imagedestroy($imageResource); |
||
| 681 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 682 | '', |
||
| 683 | 'PHP GD library has gif support' |
||
| 684 | )); |
||
| 685 | } else { |
||
| 686 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 687 | 'GD is loaded, but calling imagecreatefromgif() fails. This must be fixed, TYPO3 CMS won\'t work well otherwise.', |
||
| 688 | 'PHP GD library gif support broken', |
||
| 689 | FlashMessage::ERROR |
||
| 690 | )); |
||
| 691 | } |
||
| 692 | } else { |
||
| 693 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 694 | 'GD must be compiled with gif support. This is essential for TYPO3 CMS to work properly.', |
||
| 695 | 'PHP GD library gif support missing', |
||
| 696 | FlashMessage::ERROR |
||
| 697 | )); |
||
| 698 | } |
||
| 699 | } |
||
| 700 | |||
| 701 | /** |
||
| 702 | * Check jpg support of GD library |
||
| 703 | */ |
||
| 704 | protected function checkGdLibJpgSupport() |
||
| 705 | { |
||
| 706 | if (function_exists('imagecreatefromjpeg') |
||
| 707 | && function_exists('imagejpeg') |
||
| 708 | && (imagetypes() & IMG_JPG) |
||
| 709 | ) { |
||
| 710 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 711 | '', |
||
| 712 | 'PHP GD library has jpg support' |
||
| 713 | )); |
||
| 714 | } else { |
||
| 715 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 716 | 'GD must be compiled with jpg support. This is essential for TYPO3 CMS to work properly.', |
||
| 717 | 'PHP GD library jpg support missing', |
||
| 718 | FlashMessage::ERROR |
||
| 719 | )); |
||
| 720 | } |
||
| 721 | } |
||
| 722 | |||
| 723 | /** |
||
| 724 | * Check png support of GD library |
||
| 725 | */ |
||
| 726 | protected function checkGdLibPngSupport() |
||
| 727 | { |
||
| 728 | if (function_exists('imagecreatefrompng') |
||
| 729 | && function_exists('imagepng') |
||
| 730 | && (imagetypes() & IMG_PNG) |
||
| 731 | ) { |
||
| 732 | // Do not use data:// wrapper to be independent of allow_url_fopen |
||
| 733 | $imageResource = @imagecreatefrompng(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.png'); |
||
| 734 | if ($this->checkImageResource($imageResource)) { |
||
| 735 | imagedestroy($imageResource); |
||
| 736 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 737 | '', |
||
| 738 | 'PHP GD library has png support' |
||
| 739 | )); |
||
| 740 | } else { |
||
| 741 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 742 | 'GD is compiled with png support, but calling imagecreatefrompng() fails.' |
||
| 743 | . ' Check your environment and fix it, png in GD lib is important' |
||
| 744 | . ' for TYPO3 CMS to work properly.', |
||
| 745 | 'PHP GD library png support broken', |
||
| 746 | FlashMessage::ERROR |
||
| 747 | )); |
||
| 748 | } |
||
| 749 | } else { |
||
| 750 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 751 | 'GD must be compiled with png support. This is essential for TYPO3 CMS to work properly', |
||
| 752 | 'PHP GD library png support missing', |
||
| 753 | FlashMessage::ERROR |
||
| 754 | )); |
||
| 755 | } |
||
| 756 | } |
||
| 757 | |||
| 758 | /** |
||
| 759 | * Check gdlib supports freetype |
||
| 760 | */ |
||
| 761 | protected function checkGdLibFreeTypeSupport() |
||
| 762 | { |
||
| 763 | if (function_exists('imagettftext')) { |
||
| 764 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 765 | 'There is a difference between the font size setting which the GD' |
||
| 766 | . ' library should be supplied with. If installation is completed' |
||
| 767 | . ' a test in the install tool helps to find out the value you need.', |
||
| 768 | 'PHP GD library has freetype font support' |
||
| 769 | )); |
||
| 770 | } else { |
||
| 771 | $this->messageQueue->enqueue(new FlashMessage( |
||
| 772 | 'Some core functionality and extension rely on the GD' |
||
| 773 | . ' to render fonts on images. This support is missing' |
||
| 774 | . ' in your environment. Install it.', |
||
| 775 | 'PHP GD library freetype support missing', |
||
| 776 | FlashMessage::ERROR |
||
| 777 | )); |
||
| 778 | } |
||
| 779 | } |
||
| 780 | |||
| 781 | /** |
||
| 782 | * Helper methods |
||
| 783 | */ |
||
| 784 | |||
| 785 | /** |
||
| 786 | * Validate a given IP address. |
||
| 787 | * |
||
| 788 | * @param string $ip IP address to be tested |
||
| 789 | * @return bool |
||
| 790 | */ |
||
| 791 | protected function isValidIp($ip) |
||
| 792 | { |
||
| 793 | return filter_var($ip, FILTER_VALIDATE_IP) !== false; |
||
| 794 | } |
||
| 795 | |||
| 796 | /** |
||
| 797 | * Test if this instance runs on windows OS |
||
| 798 | * |
||
| 799 | * @return bool TRUE if operating system is windows |
||
| 800 | */ |
||
| 801 | protected function isWindowsOs() |
||
| 808 | } |
||
| 809 | |||
| 810 | /** |
||
| 811 | * Helper method to explode a string by delimiter and throw away empty values. |
||
| 812 | * Removes empty values from result array. |
||
| 813 | * |
||
| 814 | * @param string $delimiter Delimiter string to explode with |
||
| 815 | * @param string $string The string to explode |
||
| 816 | * @return array Exploded values |
||
| 817 | */ |
||
| 818 | protected function trimExplode($delimiter, $string) |
||
| 819 | { |
||
| 820 | $explodedValues = explode($delimiter, $string); |
||
| 821 | $explodedValues = is_array($explodedValues) ? $explodedValues : []; |
||
| 822 | $resultWithPossibleEmptyValues = array_map('trim', $explodedValues); |
||
| 823 | $result = []; |
||
| 824 | foreach ($resultWithPossibleEmptyValues as $value) { |
||
| 825 | if ($value !== '') { |
||
| 826 | $result[] = $value; |
||
| 827 | } |
||
| 828 | } |
||
| 829 | return $result; |
||
| 830 | } |
||
| 831 | |||
| 832 | /** |
||
| 833 | * Helper method to get the bytes value from a measurement string like "100k". |
||
| 834 | * |
||
| 835 | * @param string $measurement The measurement (e.g. "100k") |
||
| 836 | * @return int The bytes value (e.g. 102400) |
||
| 837 | */ |
||
| 838 | protected function getBytesFromSizeMeasurement($measurement) |
||
| 849 | } |
||
| 850 | |||
| 851 | private function checkImageResource($imageResource): bool |
||
| 856 |