[!!!][TASK] Remove ExtJS Debugging and $GLOBALS['error'] 17/53817/5
authorBenni Mack <benni@typo3.org>
Mon, 28 Aug 2017 04:48:14 +0000 (06:48 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 7 Sep 2017 22:08:55 +0000 (00:08 +0200)
The global variable $GLOBAL['error'] is used only in ExtJS-context for ExtDirect
(via ExtDirectDebug) however, but evaluates at every request.

This is the first of a series of patches to remove ExtJS in total.

The global methods debugBegin() and debugEnd() are removed as well.

Resolves: #37180
Releases: master
Change-Id: I00843d85660e85c213ac66059abdd84344c4fe3f
Reviewed-on: https://review.typo3.org/53817
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
15 files changed:
typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php
typo3/sysext/core/Classes/ExtDirect/ExtDirectDebug.php [deleted file]
typo3/sysext/core/Classes/ExtDirect/ExtDirectRouter.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst [new file with mode: 0644]
typo3/sysext/core/Resources/PHP/GlobalDebugFunctions.php
typo3/sysext/core/Tests/Unit/Core/SystemEnvironmentBuilderTest.php
typo3/sysext/frontend/Classes/Http/RequestHandler.php
typo3/sysext/install/Classes/Controller/Action/Ajax/ExtensionScannerScanFile.php
typo3/sysext/install/Classes/ExtensionScanner/Php/Matcher/FunctionCallMatcher.php [new file with mode: 0644]
typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayGlobalMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/FunctionCallMatcher.php [new file with mode: 0644]
typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/Fixtures/FunctionCallMatcherFixture.php [new file with mode: 0644]
typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/Fixtures/MethodCallMatcherFixture.php
typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/FunctionCallMatcherTest.php [new file with mode: 0644]

index 9df3726..136b0a6 100644 (file)
@@ -213,7 +213,6 @@ class SystemEnvironmentBuilder
     protected static function initializeGlobalVariables()
     {
         // Unset variable(s) in global scope (security issue #13959)
-        unset($GLOBALS['error']);
         $GLOBALS['TYPO3_MISC'] = [];
         $GLOBALS['T3_VAR'] = [];
         $GLOBALS['T3_SERVICES'] = [];
diff --git a/typo3/sysext/core/Classes/ExtDirect/ExtDirectDebug.php b/typo3/sysext/core/Classes/ExtDirect/ExtDirectDebug.php
deleted file mode 100644 (file)
index 5d96f22..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\ExtDirect;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Ext Direct Debug
- */
-class ExtDirectDebug
-{
-    /**
-     * Internal debug message array
-     *
-     * @var array
-     */
-    protected $debugMessages = [];
-
-    /**
-     * destructor
-     *
-     * Currently empty, but automatically registered and called during
-     * ExtDirect shutdown.
-     *
-     * @see http://forge.typo3.org/issues/25278
-     */
-    public function __destruct()
-    {
-    }
-
-    /**
-     * Adds a new message of any data type to the internal debug message array.
-     *
-     * @param mixed $message
-     */
-    public function debug($message)
-    {
-        $this->debugMessages[] = $message;
-    }
-
-    /**
-     * Returns the internal debug messages as a string.
-     *
-     * @return string
-     */
-    public function toString()
-    {
-        $messagesAsString = '';
-        if (!empty($this->debugMessages)) {
-            $messagesAsString = \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($this->debugMessages);
-        }
-        return $messagesAsString;
-    }
-}
index 7055d68..310720c 100644 (file)
@@ -32,7 +32,6 @@ class ExtDirectRouter
      */
     public function routeAction(ServerRequestInterface $request, ResponseInterface $response)
     {
-        $GLOBALS['error'] = GeneralUtility::makeInstance(\TYPO3\CMS\Core\ExtDirect\ExtDirectDebug::class);
         $isForm = false;
         $isUpload = false;
         $rawPostData = file_get_contents('php://input');
@@ -85,7 +84,6 @@ class ExtDirectRouter
                     }
                     $extResponse[$index]['type'] = 'rpc';
                     $extResponse[$index]['result'] = $this->processRpc($singleRequest, $namespace);
-                    $extResponse[$index]['debug'] = $GLOBALS['error']->toString();
                 } catch (\Exception $exception) {
                     $extResponse[$index]['type'] = 'exception';
                     $extResponse[$index]['message'] = $exception->getMessage();
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst
new file mode 100644 (file)
index 0000000..f4280c5
--- /dev/null
@@ -0,0 +1,34 @@
+.. include:: ../../Includes.txt
+
+===============================================================
+Breaking: #37180 - ExtDirectDebug and $GLOBALS['error'] removed
+===============================================================
+
+See :issue:`37180`
+
+Description
+===========
+
+The class :php:`TYPO3\CMS\Core\ExtDirect\ExtDirectDebug` has been removed and within the change, also the usage of the
+global variable :php:`$GLOBALS['error']` has been removed.
+
+The following global methods are removed as well:
+
+- :php:`debugBegin()`
+- :php:`debugEnd()`
+
+
+Impact
+======
+
+Accessing the class :php:`TYPO3\CMS\Core\ExtDirect\ExtDirectDebug`, the global variable :php:`$GLOBALS['error']` or the
+global methods :php:`debugBegin()` and :php:`debugEnd()` will lead to an exception.
+
+
+Affected Installations
+======================
+
+All instances, that use the mentioned class, global methods or access the global variable.
+The extension scanner of the install tool will find affected extensions.
+
+.. index:: PHP-API, FullyScanned
index a50802e..0224fb3 100644 (file)
@@ -10,7 +10,7 @@
         \TYPO3\CMS\Core\Utility\DebugUtility::debug($var, $debugTitle);
     }
 
-    // Debug function which calls $GLOBALS['error'] error handler if available
+    // Debug function
     function debug($variable = '', $name = '*variable*', $line = '*line*', $file = '*file*', $recursiveDepth = 3, $debugLevel = E_DEBUG)
     {
         // If you wish to use the debug()-function, and it does not output something,
         if (!\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'])) {
             return;
         }
-        if (is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debug'])) {
-            $GLOBALS['error']->debug($variable, $name, $line, $file, $recursiveDepth, $debugLevel);
-        } else {
-            $title = $name === '*variable*' ? '' : $name;
-            $group = $line === '*line*' ? null : $line;
-            \TYPO3\CMS\Core\Utility\DebugUtility::debug($variable, $title, $group);
-        }
-    }
-
-    function debugBegin()
-    {
-        if (is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debugBegin'])) {
-            $GLOBALS['error']->debugBegin();
-        }
-    }
-
-    function debugEnd()
-    {
-        if (is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debugEnd'])) {
-            $GLOBALS['error']->debugEnd();
-        }
+        $title = $name === '*variable*' ? '' : $name;
+        $group = $line === '*line*' ? null : $line;
+        \TYPO3\CMS\Core\Utility\DebugUtility::debug($variable, $title, $group);
     }
index feeb8cd..92988a3 100644 (file)
@@ -108,16 +108,6 @@ class SystemEnvironmentBuilderTest extends \TYPO3\TestingFramework\Core\Unit\Uni
     /**
      * @test
      */
-    public function initializeGlobalVariablesUnsetsGlobalErrorArray()
-    {
-        $GLOBALS['error'] = 'foo';
-        $this->subject->_call('initializeGlobalVariables');
-        $this->assertFalse(isset($GLOBALS['error']));
-    }
-
-    /**
-     * @test
-     */
     public function initializeGlobalVariablesSetsGlobalTypo3MiscArray()
     {
         unset($GLOBALS['TYPO3_MISC']);
index c54cb4c..7215158 100644 (file)
@@ -261,10 +261,6 @@ class RequestHandler implements RequestHandlerInterface
             $response = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\Response::class);
             $response->getBody()->write($this->controller->content);
         }
-        // Debugging Output
-        if (isset($GLOBALS['error']) && is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debugOutput'])) {
-            $GLOBALS['error']->debugOutput();
-        }
         GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, ['_FLUSH' => true]);
         return $response;
     }
index 2f8f399..ecc904d 100644 (file)
@@ -29,6 +29,7 @@ use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\ArrayGlobalMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\ClassConstantMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\ClassNameMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\ConstantMatcher;
+use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\FunctionCallMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\InterfaceMethodChangedMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\MethodArgumentDroppedMatcher;
 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\MethodArgumentDroppedStaticMatcher;
@@ -71,6 +72,10 @@ class ExtensionScannerScanFile extends AbstractAjaxAction
             'configurationFile' => 'EXT:install/Configuration/ExtensionScanner/Php/ConstantMatcher.php',
         ],
         [
+            'class' => FunctionCallMatcher::class,
+            'configurationFile' => 'EXT:install/Configuration/ExtensionScanner/Php/FunctionCallMatcher.php',
+        ],
+        [
             'class' => InterfaceMethodChangedMatcher::class,
             'configurationFile' => 'EXT:install/Configuration/ExtensionScanner/Php/InterfaceMethodChangedMatcher.php',
         ],
diff --git a/typo3/sysext/install/Classes/ExtensionScanner/Php/Matcher/FunctionCallMatcher.php b/typo3/sysext/install/Classes/ExtensionScanner/Php/Matcher/FunctionCallMatcher.php
new file mode 100644 (file)
index 0000000..dcc3568
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Install\ExtensionScanner\Php\Matcher;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use PhpParser\Node;
+use PhpParser\Node\Expr\FuncCall;
+use PhpParser\Node\Name\FullyQualified;
+
+/**
+ * Find usages of global function calls which were removed / deprecated.
+ * This is a strong match.
+ */
+class FunctionCallMatcher extends AbstractCoreMatcher
+{
+    /**
+     * Prepare $this->flatMatcherDefinitions once
+     *
+     * @param array $matcherDefinitions Incoming main configuration
+     */
+    public function __construct(array $matcherDefinitions)
+    {
+        $this->matcherDefinitions = $matcherDefinitions;
+        $this->validateMatcherDefinitions(['numberOfMandatoryArguments', 'maximumNumberOfArguments']);
+    }
+
+    /**
+     * Called by PhpParser.
+     * Test for "removedFunction()" (strong match)
+     *
+     * @param Node $node
+     */
+    public function enterNode(Node $node)
+    {
+        // Match method call (not static)
+        if (!$this->isFileIgnored($node)
+            && !$this->isLineIgnored($node)
+            && $node instanceof FuncCall
+            && $node->name instanceof FullyQualified
+            && in_array($node->name->toString(), array_keys($this->matcherDefinitions), true)
+        ) {
+            $functionName = $node->name->toString();
+            $matchDefinition = $this->matcherDefinitions[$functionName];
+
+            $numberOfArguments = count($node->args);
+            $isArgumentUnpackingUsed = $this->isArgumentUnpackingUsed($node->args);
+
+            if ($isArgumentUnpackingUsed
+                || ($numberOfArguments >= $matchDefinition['numberOfMandatoryArguments']
+                    && $numberOfArguments <= $matchDefinition['maximumNumberOfArguments'])
+            ) {
+                $this->matches[] = [
+                    'restFiles' => $matchDefinition['restFiles'],
+                    'line' => $node->getAttribute('startLine'),
+                    'message' => 'Call to function "' . $functionName . '"',
+                    'indicator' => 'strong',
+                ];
+            }
+        }
+    }
+}
index e537282..9915668 100644 (file)
@@ -5,4 +5,9 @@ return [
             'Breaking-80929-TYPO3_DBMovedToExtension.rst',
         ],
     ],
+    '$GLOBALS[\'error\']' => [
+        'restFiles' => [
+            'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+        ],
+    ],
 ];
index 5e07e23..afd4a0e 100644 (file)
@@ -349,6 +349,11 @@ return [
             'Important-82229-FluidImplementationOfCmsVariableProviderRemoved.rst',
         ],
     ],
+    'TYPO3\CMS\Core\ExtDirect\ExtDirectDebug' => [
+        'restFiles' => [
+            'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+        ],
+    ],
 
     // Removed interfaces
     'TYPO3\CMS\Backend\Form\DatabaseFileIconsHookInterface' => [
diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/FunctionCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/FunctionCallMatcher.php
new file mode 100644 (file)
index 0000000..063657f
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+return [
+    // Removed global functions
+    'debugBegin' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+        ],
+    ],
+    'debugEnd' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+        ],
+    ],
+];
diff --git a/typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/Fixtures/FunctionCallMatcherFixture.php b/typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/Fixtures/FunctionCallMatcherFixture.php
new file mode 100644 (file)
index 0000000..ead0193
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Install\Tests\Unit\ExtensionScanner\Php\Matcher\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+
+/**
+ * Fixture file
+ */
+class FunctionCallMatcherFixture
+{
+    public function aMethod()
+    {
+        // Matches
+        \debugBegin();
+
+        // No match: Not a global call
+        debugBegin();
+        // No match: Only 1 arg is too much
+        debugBegin('foo');
+        // No match: Class context
+        $foo->debugBegin();
+        // No match: Line ignored
+        // @extensionScannerIgnoreLine
+        debugBegin();
+        // @extensionScannerIgnoreLine
+        $bar->bar(\debugBegin());
+    }
+}
index 9371e33..9c13b53 100644 (file)
@@ -34,6 +34,8 @@ class MethodCallMatcherFixture
         // Match: Too many args but some could be empty arrays
         $foo->confirmMsg(...$arg1, ...$arg2, ...$arg3, ...$arg4, ...$arg5, ...$arg6);
 
+        \confirmMsg();
+
         // No match: Only 3 args given
         $foo->confirmMsg('arg1', 'arg2', 'arg3');
         // No match: Too many arguments given
diff --git a/typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/FunctionCallMatcherTest.php b/typo3/sysext/install/Tests/Unit/ExtensionScanner/Php/Matcher/FunctionCallMatcherTest.php
new file mode 100644 (file)
index 0000000..1636f5c
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Install\Tests\Unit\ExtensionScanner\Php\Matcher;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitor\NameResolver;
+use PhpParser\ParserFactory;
+use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\FunctionCallMatcher;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class FunctionCallMatcherTest extends UnitTestCase
+{
+    /**
+     * @test
+     */
+    public function hitsFromFixtureAreFound()
+    {
+        $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
+        $fixtureFile = __DIR__ . '/Fixtures/FunctionCallMatcherFixture.php';
+        $statements = $parser->parse(file_get_contents($fixtureFile));
+
+        $traverser = new NodeTraverser();
+        $traverser->addVisitor(new NameResolver());
+
+        $configuration = [
+            'debugBegin' => [
+                'numberOfMandatoryArguments' => 0,
+                'maximumNumberOfArguments' => 0,
+                'restFiles' => [
+                    'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+                ],
+            ],
+        ];
+        $subject = new FunctionCallMatcher($configuration);
+        $traverser->addVisitor($subject);
+        $traverser->traverse($statements);
+        $expectedHitLineNumbers = [
+            28,
+        ];
+        $actualHitLineNumbers = [];
+        foreach ($subject->getMatches() as $hit) {
+            $actualHitLineNumbers[] = $hit['line'];
+        }
+        $this->assertEquals($expectedHitLineNumbers, $actualHitLineNumbers);
+    }
+
+    /**
+     * @test
+     */
+    public function matchIsIgnoredIfIgnoreFileIsSet()
+    {
+        $phpCode = <<<'EOC'
+<?php
+/**
+ * Some comment
+ * @extensionScannerIgnoreFile This file is ignored
+ */
+class foo
+{
+    public function aTest()
+    {
+        // This valid match should not match since the entire file is ignored
+        debugBegin();
+    }
+}
+EOC;
+
+        $parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
+        $statements = $parser->parse($phpCode);
+
+        $traverser = new NodeTraverser();
+        $configuration = [
+            'debugBegin' => [
+                'numberOfMandatoryArguments' => 0,
+                'maximumNumberOfArguments' => 0,
+                'restFiles' => [
+                    'Breaking-37180-RemovedExtDirectDebugAndGLOBALSerror.rst',
+                ],
+            ],
+        ];
+        $subject = new FunctionCallMatcher($configuration);
+        $traverser->addVisitor($subject);
+        $traverser->traverse($statements);
+
+        $this->assertEmpty($subject->getMatches());
+    }
+}