--- /dev/null
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\Compatibility;
+
+/*
+ * 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!
+ */
+
+/**
+ * Trait to support the logging of deprecation of public INSTANCE methods.
+ *
+ * This is useful due to the long list of PHP4 methods that have been set to
+ * public previously, which should be removed or moved to "protected" / "private".
+ *
+ * Usage:
+ *
+ * 1. Use this trait for the class with the method to change the visibility status or to be removed.
+ * 2. Add the class methods with deprecated public visibility to $deprecatedPublicMethods.
+ * 3. Set these methods to protected or private.
+ * 4. Add the phpDoc tag "@private" to the method so IDEs understand that.
+ *
+ * With the next major release remove the "@private" tag and remove the methods from
+ * $deprecatedPublicMethods. Remove the trait use after removing the last deprecation.
+ *
+ * Note:
+ *
+ * - Only use this trait in classes only that do not define their own magic __call() method.
+ * - Do not use this trait for static methods.
+ *
+ * Example usage:
+ *
+ *
+ * class MyControllerClass {
+ * use PublicMethodDeprecationTrait;
+ *
+ * /**
+ * * List previously publicly accessible variables
+ * * @var array
+ * *...
+ * private $deprecatedPublicMethods = [
+ * 'myMethod' => 'Using MyControllerClass::myMethod() is deprecated and will not be possible anymore in TYPO3 v10. Use MyControllerClass:myOtherMethod() instead.'
+ * ];
+ *
+ * /**
+ * * This is my method.
+ * *
+ * * @deprecated (if deprecated)
+ * * @private (if switched to private)
+ * /
+ * protected function myMethod($arg1, $arg2);
+ * }
+ */
+
+/**
+ * This trait has no public methods by default, ensure to add a $deprecatedPublicMethods property
+ * to your class when using this trait.
+ */
+trait PublicMethodDeprecationTrait
+{
+ /**
+ * Checks if the method of the given name is available, calls it but throws a deprecation.
+ * If the method does not exist, a fatal error is thrown.
+ *
+ * Unavailable protected methods must return in a fatal error as usual.
+ * Marked methods are called and a deprecation entry is thrown.
+ *
+ * __call() is not called for public methods.
+ *
+ * @property array $deprecatedPublicMethods List of deprecated public methods
+ * @param string $methodName
+ * @param array $arguments
+ * @return mixed
+ */
+ public function __call(string $methodName, array $arguments)
+ {
+ if (method_exists($this, $methodName) && isset($this->deprecatedPublicMethods[$methodName])) {
+ trigger_error($this->deprecatedPublicMethods[$methodName], E_USER_DEPRECATED);
+ return $this->$methodName(...$arguments);
+ }
+
+ // Do the same behaviour as calling $myObject->method();
+ if (method_exists($this, $methodName)) {
+ throw new \Error('Call to protected/private method ' . self::class . '::' . $methodName . '()');
+ }
+
+ throw new \Error('Call to undefined method ' . self::class . '::' . $methodName . '()');
+ }
+}
--- /dev/null
+.. include:: ../../Includes.txt
+
+===========================================================
+Feature: #85247 - Trait to detect public deprecated methods
+===========================================================
+
+See :issue:`85247`
+
+Description
+===========
+
+The trait :php:`TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait` has been added
+to allow setting public methods to protected in a backwards compatible way.
+
+The core uses this trait to set public methods that to should be protected or private but
+are accessible codewise for historical reasons, while extensions using the methods do not
+break, but a deprecation note is logged.
+
+Classes using this trait have a property :php:`$deprecatedPublicMethods` that lists all
+methods covered by the trait.
+
+
+Impact
+======
+
+Core classes using this trait log deprecation notes if an extension uses a method that
+has been made protected using the trait functionality.
+
+.. index:: PHP-API
\ No newline at end of file
--- /dev/null
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\Tests\UnitDeprecated\Compatibility\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\Core\Compatibility\PublicMethodDeprecationTrait;
+
+/**
+ * Test class using public method deprecation trait test fixture
+ */
+class PublicMethodDeprecationTraitTextFixture
+{
+ use PublicMethodDeprecationTrait;
+
+ protected $deprecatedPublicMethods = [
+ 'methodMadeProtected' => 'Deprecation text',
+ 'methodMadeProtectedWithArguments' => 'Deprecation text',
+ 'methodMadeProtectedWithReturn' => 'Deprecation text',
+ ];
+
+ public function standardPublicMethod(): void
+ {
+ throw new \RuntimeException('test', 1528822131);
+ }
+
+ protected function standardProtectedMethod(): void
+ {
+ // empty
+ }
+
+ /**
+ * @private
+ */
+ protected function methodMadeProtected(): void
+ {
+ throw new \RuntimeException('test', 1528822485);
+ }
+
+ /**
+ * @private
+ */
+ protected function methodMadeProtectedWithReturn(): string
+ {
+ return 'foo';
+ }
+
+ /**
+ * @private
+ * @param string $arg1
+ * @param string $arg2
+ */
+ protected function methodMadeProtectedWithArguments(string $arg1, string $arg2): void
+ {
+ if ($arg1 === 'foo' && $arg2 === 'bar') {
+ throw new \RuntimeException('test', 1528822486);
+ }
+ }
+}
--- /dev/null
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\Tests\UnitDeprecated\Compatibility;
+
+/*
+ * 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\Core\Tests\UnitDeprecated\Compatibility\Fixtures\PublicMethodDeprecationTraitTextFixture;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class PublicMethodDeprecationTraitTest extends UnitTestCase
+{
+ /**
+ * @test
+ */
+ public function publicMethodCanBeCalled(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionCode(1528822131);
+ (new PublicMethodDeprecationTraitTextFixture())->standardPublicMethod();
+ }
+
+ /**
+ * @test
+ */
+ public function protectedMethodNotHandledByTraitThrowsError(): void
+ {
+ $this->expectException(\Error::class);
+ (new PublicMethodDeprecationTraitTextFixture())->standardProtectedMethod();
+ }
+
+ /**
+ * @test
+ */
+ public function notExistingMethodThrowsError(): void
+ {
+ $this->expectException(\Error::class);
+ (new PublicMethodDeprecationTraitTextFixture())->doesNotExist();
+ }
+
+ /**
+ * @test
+ */
+ public function methodMadeProtectedCanBeCalled(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionCode(1528822485);
+ (new PublicMethodDeprecationTraitTextFixture())->methodMadeProtected();
+ }
+
+ /**
+ * @test
+ */
+ public function methodMadeProtectedReturnsValue(): void
+ {
+ $this->assertEquals('foo', (new PublicMethodDeprecationTraitTextFixture())->methodMadeProtectedWithReturn());
+ }
+
+ /**
+ * @test
+ */
+ public function methodMadeProtectedCanBeCalledWithArguments(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionCode(1528822486);
+ (new PublicMethodDeprecationTraitTextFixture())->methodMadeProtectedWithArguments('foo', 'bar');
+ }
+}
use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+/**
+ * Test case
+ */
class PublicPropertyDeprecationTraitTest extends UnitTestCase
{
/**