[FEATURE] Add trait to detect public deprecated methods
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Compatibility / PublicMethodDeprecationTrait.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Core\Compatibility;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 /**
19 * Trait to support the logging of deprecation of public INSTANCE methods.
20 *
21 * This is useful due to the long list of PHP4 methods that have been set to
22 * public previously, which should be removed or moved to "protected" / "private".
23 *
24 * Usage:
25 *
26 * 1. Use this trait for the class with the method to change the visibility status or to be removed.
27 * 2. Add the class methods with deprecated public visibility to $deprecatedPublicMethods.
28 * 3. Set these methods to protected or private.
29 * 4. Add the phpDoc tag "@private" to the method so IDEs understand that.
30 *
31 * With the next major release remove the "@private" tag and remove the methods from
32 * $deprecatedPublicMethods. Remove the trait use after removing the last deprecation.
33 *
34 * Note:
35 *
36 * - Only use this trait in classes only that do not define their own magic __call() method.
37 * - Do not use this trait for static methods.
38 *
39 * Example usage:
40 *
41 *
42 * class MyControllerClass {
43 * use PublicMethodDeprecationTrait;
44 *
45 * /**
46 * * List previously publicly accessible variables
47 * * @var array
48 * *...
49 * private $deprecatedPublicMethods = [
50 * 'myMethod' => 'Using MyControllerClass::myMethod() is deprecated and will not be possible anymore in TYPO3 v10. Use MyControllerClass:myOtherMethod() instead.'
51 * ];
52 *
53 * /**
54 * * This is my method.
55 * *
56 * * @deprecated (if deprecated)
57 * * @private (if switched to private)
58 * /
59 * protected function myMethod($arg1, $arg2);
60 * }
61 */
62
63 /**
64 * This trait has no public methods by default, ensure to add a $deprecatedPublicMethods property
65 * to your class when using this trait.
66 */
67 trait PublicMethodDeprecationTrait
68 {
69 /**
70 * Checks if the method of the given name is available, calls it but throws a deprecation.
71 * If the method does not exist, a fatal error is thrown.
72 *
73 * Unavailable protected methods must return in a fatal error as usual.
74 * Marked methods are called and a deprecation entry is thrown.
75 *
76 * __call() is not called for public methods.
77 *
78 * @property array $deprecatedPublicMethods List of deprecated public methods
79 * @param string $methodName
80 * @param array $arguments
81 * @return mixed
82 */
83 public function __call(string $methodName, array $arguments)
84 {
85 if (method_exists($this, $methodName) && isset($this->deprecatedPublicMethods[$methodName])) {
86 trigger_error($this->deprecatedPublicMethods[$methodName], E_USER_DEPRECATED);
87 return $this->$methodName(...$arguments);
88 }
89
90 // Do the same behaviour as calling $myObject->method();
91 if (method_exists($this, $methodName)) {
92 throw new \Error('Call to protected/private method ' . self::class . '::' . $methodName . '()');
93 }
94
95 throw new \Error('Call to undefined method ' . self::class . '::' . $methodName . '()');
96 }
97 }