Merge pull request #22438 from eileenmcnaughton/format
[civicrm-core.git] / Civi / Schema / Traits / MagicGetterSetterTrait.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 namespace Civi\Schema\Traits;
13
14 use Civi\Api4\Utils\ReflectionUtils;
15
16 /**
17 * Automatically define getter/setter methods for public and protected fields.
18 *
19 * BASIC USAGE
20 *
21 * - Choose a class
22 * - Add the trait (`use MagicGetterSetterTrait;`).
23 * - Add a public or protected property (`protected $fooBar;`).
24 * - When using the class, you may now call `setFooBar($value)` and `getFooBar()`.
25 *
26 * TIPS AND TRICKS
27 *
28 * - To provide better hints/DX in IDEs, you may add the `@method` notations
29 * to the class docblock. There are several examples of this in APIv4
30 * (see e.g. `AbstractAction.php` or `AbstractQueryAction.php`).
31 * - When/if you need to customize the behavior of a getter/setter, then simply
32 * add your own method. This takes precedence over magic mehods.
33 * - If a field name begins with `_`, then it will be excluded.
34 *
35 * @package Civi\Schema\Traits
36 */
37 trait MagicGetterSetterTrait {
38
39 /**
40 * Magic function to provide getters/setters.
41 *
42 * @param string $method
43 * @param array $arguments
44 * @return static|mixed
45 * @throws \CRM_Core_Exception
46 */
47 public function __call($method, $arguments) {
48 $mode = substr($method, 0, 3);
49 $prop = lcfirst(substr($method, 3));
50 $props = static::getMagicProperties();
51 if (isset($props[$prop])) {
52 switch ($mode) {
53 case 'get':
54 return $this->$prop;
55
56 case 'set':
57 if (count($arguments) < 1) {
58 throw new \CRM_Core_Exception(sprintf('Missing required parameter for method %s::%s()', static::CLASS, $method));
59 }
60 $this->$prop = $arguments[0];
61 return $this;
62 }
63 }
64
65 throw new \CRM_Core_Exception(sprintf('Unknown method: %s::%s()', static::CLASS, $method));
66 }
67
68 /**
69 * Get a list of class properties for which magic methods are supported.
70 *
71 * @return array
72 * List of supported properties, keyed by property name.
73 * Array(string $propertyName => bool $true).
74 */
75 protected static function getMagicProperties(): array {
76 // Thread-local cache of class metadata. Class metadata is immutable at runtime, so this is strictly write-once. It should ideally be reused across varied test-functions.
77 static $caches = [];
78 $CLASS = static::CLASS;
79 $cache =& $caches[$CLASS];
80 if ($cache === NULL) {
81 $cache = [];
82 foreach (ReflectionUtils::findStandardProperties(static::CLASS) as $property) {
83 /** @var \ReflectionProperty $property */
84 $cache[$property->getName()] = TRUE;
85 }
86 }
87 return $cache;
88 }
89
90 }