From 8f2fe557210e5a9a54152dd74362f73a63a199cb Mon Sep 17 00:00:00 2001
From: Susanne Moog <look@susi.dev>
Date: Thu, 26 Mar 2020 12:54:08 +0100
Subject: [PATCH] [TASK] Update EnvironmentStatus OpcodeCache info

The original implementation was meant to handle different variants of
opcaches. As of now, only the native PHP opcache is still supported.

This patch cleans up the settings and setup check and adds an
additional check whether clearing is possible or deactivated via
disable_functions.

Resolves: #90838
Releases: master
Change-Id: I12bde7cf160be548904737acee5c1d39faadeba0
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63932
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../Classes/Service/OpcodeCacheService.php    | 34 +++++++++++--------
 .../Classes/SystemEnvironment/SetupCheck.php  | 23 ++++---------
 2 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/typo3/sysext/core/Classes/Service/OpcodeCacheService.php b/typo3/sysext/core/Classes/Service/OpcodeCacheService.php
index ac3287115bbc..bdd12e2cf35d 100644
--- a/typo3/sysext/core/Classes/Service/OpcodeCacheService.php
+++ b/typo3/sysext/core/Classes/Service/OpcodeCacheService.php
@@ -1,4 +1,5 @@
 <?php
+
 namespace TYPO3\CMS\Core\Service;
 
 /*
@@ -30,25 +31,19 @@ class OpcodeCacheService
     public function getAllActive()
     {
         $supportedCaches = [
-            // The ZendOpcache aka OPcache since PHP 5.5
-            // http://php.net/manual/de/book.opcache.php
             'OPcache' => [
                 'active' => extension_loaded('Zend OPcache') && ini_get('opcache.enable') === '1',
                 'version' => phpversion('Zend OPcache'),
-                'canReset' => true, // opcache_reset() ... it seems that it doesn't reset for current run.
-                // From documentation this function exists since first version (7.0.0) but from Changelog
-                // this function exists since OPcache 7.0.2
-                // http://pecl.php.net/package-changelog.php?package=ZendOpcache&release=7.0.2
-                // PHP 7.0 onward is delivered minimum OPcache 7.0.6-dev
-                'canInvalidate' => true,
-                'error' => false,
-                'clearCallback' => function ($fileAbsPath) {
-                    if ($fileAbsPath !== null) {
-                        opcache_invalidate($fileAbsPath);
-                    } else {
-                        opcache_reset();
+                'warning' => self::isClearable() ? false : 'Either opcache_invalidate or opcache_reset are disabled in this installation. Clearing will not work.',
+                'clearCallback' => static function ($fileAbsPath) {
+                    if (self::isClearable()) {
+                        if ($fileAbsPath !== null) {
+                            opcache_invalidate($fileAbsPath);
+                        } else {
+                            opcache_reset();
+                        }
                     }
-                }
+                },
             ],
         ];
 
@@ -73,4 +68,13 @@ class OpcodeCacheService
             $callback($fileAbsPath);
         }
     }
+
+    /**
+     * @return bool
+     */
+    protected static function isClearable(): bool
+    {
+        $disabled = explode(',', ini_get('disable_functions'));
+        return !(in_array('opcache_invalidate', $disabled, true) || in_array('opcache_reset', $disabled, true));
+    }
 }
diff --git a/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php
index 90b8dda698dd..561a187c8dd6 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php
@@ -15,7 +15,6 @@ namespace TYPO3\CMS\Install\SystemEnvironment;
  */
 
 use TYPO3\CMS\Core\Core\Environment;
-use TYPO3\CMS\Core\Information\Typo3Information;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
 use TYPO3\CMS\Core\Service\OpcodeCacheService;
@@ -192,8 +191,6 @@ class SetupCheck implements CheckInterface
      */
     protected function checkSomePhpOpcodeCacheIsLoaded()
     {
-        // Link to our wiki page, so we can update opcode cache issue information independent of TYPO3 CMS releases.
-        $wikiLink = 'For more information take a look in our wiki ' . Typo3Information::URL_OPCACHE . '.';
         $opcodeCaches = GeneralUtility::makeInstance(OpcodeCacheService::class)->getAllActive();
         if (empty($opcodeCaches)) {
             // Set status to notice. It needs to be notice so email won't be triggered.
@@ -202,8 +199,7 @@ class SetupCheck implements CheckInterface
                     . ' memory and do not require to recompile a script each time it is accessed.'
                     . ' This can be a massive performance improvement and can reduce the load on a'
                     . ' server in general. A parse time reduction by factor three for fully cached'
-                    . ' pages can be achieved easily if using an opcode cache.'
-                    . LF . $wikiLink,
+                    . ' pages can be achieved easily if using an opcode cache.',
                 'No PHP opcode cache loaded',
                 FlashMessage::NOTICE
             ));
@@ -213,24 +209,17 @@ class SetupCheck implements CheckInterface
             foreach ($opcodeCaches as $opcodeCache => $properties) {
                 $message .= 'Name: ' . $opcodeCache . ' Version: ' . $properties['version'];
                 $message .= LF;
-                if ($properties['error']) {
-                    $status = FlashMessage::ERROR;
-                    $message .= ' This opcode cache is marked as malfunctioning by the TYPO3 CMS Team.';
-                } elseif ($properties['canInvalidate']) {
-                    $message .= ' This opcode cache should work correctly and has good performance.';
+                if ($properties['warning']) {
+                    $status = FlashMessage::WARNING;
+                    $message .= ' ' . $properties['warning'];
                 } else {
-                    // Set status to notice if not already error set. It needs to be notice so email won't be triggered.
-                    if ($status !== FlashMessage::ERROR) {
-                        $status = FlashMessage::NOTICE;
-                    }
-                    $message .= ' This opcode cache may work correctly but has medium performance.';
+                    $message .= ' This opcode cache should work correctly and has good performance.';
                 }
                 $message .= LF;
             }
-            $message .= $wikiLink;
             // Set title of status depending on severity
             switch ($status) {
-                case FlashMessage::ERROR:
+                case FlashMessage::WARNING:
                     $title = 'A possibly malfunctioning PHP opcode cache is loaded';
                     break;
                 case FlashMessage::OK:
-- 
GitLab