dolibarr 21.0.0-alpha
doldeprecationhandler.class.php
1<?php
2/* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
27trait DolDeprecationHandler
28{
29 // Define the following in the class using the trait
30 // to allow properties to not be defined when referenced.
31 // So only deprecated value generate exceptions.
32 //
33 // protected $enableDynamicProperties = true;
34
35 // Define the following in the class using the trait
36 // to disallow Dolibarr deprecation warnings.
37 //
38 // protected $enableDeprecatedReporting = false;
39
46 public function __get($name)
47 {
48 $deprecatedProperties = $this->deprecatedProperties();
49 if (isset($deprecatedProperties[$name])) {
50 $newProperty = $deprecatedProperties[$name];
51 $msg = "DolDeprecationHandler: Accessing deprecated property '".$name."' on class ".get_class($this).". Use '".$newProperty."' instead.".self::getCallerInfoString();
52 dol_syslog($msg);
53 if ($this->isDeprecatedReportingEnabled()) {
54 trigger_error($msg, E_USER_DEPRECATED);
55 }
56 return $this->$newProperty;
57 }
58 if ($this->isDynamicPropertiesEnabled()) {
59 return null; // If the property is set, then __get is not called.
60 }
61 $msg = "DolDeprecationHandler: Undefined property '".$name."'".self::getCallerInfoString();
62 dol_syslog($msg);
63 trigger_error($msg, E_USER_NOTICE);
64 return $this->$name; // Returning value anyway (graceful degradation)
65 }
66
74 public function __set($name, $value)
75 {
76 $deprecatedProperties = $this->deprecatedProperties();
77 if (isset($deprecatedProperties[$name])) {
78 $newProperty = $deprecatedProperties[$name];
79 // Setting is for compatibility, should not be a problem and should be reported only in paranoid mode
80 /*
81 $msg = "DolDeprecationHandler: Setting value to the deprecated property '".$name."'. Use '".$newProperty."' instead.".self::getCallerInfoString();
82 dol_syslog($msg);
83 if ($this->isDeprecatedReportingEnabled()) {
84 trigger_error($msg, E_USER_DEPRECATED);
85 }
86 */
87
88 $this->$newProperty = $value;
89 return;
90 }
91 if (!$this->isDynamicPropertiesEnabled()) {
92 $msg = "DolDeprecationHandler: Undefined property '".$name."'".self::getCallerInfoString();
93 trigger_error($msg, E_USER_NOTICE);
94 $this->$name = $value; // Setting anyway for graceful degradation
95 } else {
96 $this->$name = $value;
97 }
98 }
99
106 public function __unset($name)
107 {
108 $deprecatedProperties = $this->deprecatedProperties();
109 if (isset($deprecatedProperties[$name])) {
110 $newProperty = $deprecatedProperties[$name];
111 // Unsetting is for compatibility, should not be a problem and should be reported only in paranoid mode
112 /*
113 $msg = "DolDeprecationHandler: Unsetting deprecated property '".$name."'. Use '".$newProperty."' instead.".self::getCallerInfoString();
114 dol_syslog($msg);
115 if ($this->isDeprecatedReportingEnabled()) {
116 trigger_error($msg, E_USER_DEPRECATED);
117 }
118 */
119 unset($this->$newProperty);
120 return;
121 }
122 if (!$this->isDynamicPropertiesEnabled()) {
123 $msg = "DolDeprecationHandler: Undefined property '".$name."'.".self::getCallerInfoString();
124 dol_syslog($msg);
125 trigger_error($msg, E_USER_NOTICE);
126 }
127 }
128
135 public function __isset($name)
136 {
137 $deprecatedProperties = $this->deprecatedProperties();
138 if (isset($deprecatedProperties[$name])) {
139 $newProperty = $deprecatedProperties[$name];
140 $msg = "DolDeprecationHandler: Accessing deprecated property '".$name."' on class ".get_class($this).". Use '".$newProperty."' instead.".self::getCallerInfoString();
141 dol_syslog($msg);
142 if ($this->isDeprecatedReportingEnabled()) {
143 trigger_error($msg, E_USER_DEPRECATED);
144 }
145 return isset($newProperty);
146 } elseif ($this->isDynamicPropertiesEnabled()) {
147 return isset($this->$name);
148 }
149 $msg = "DolDeprecationHandler: Undefined property '".$name."'.".self::getCallerInfoString();
150 dol_syslog($msg);
151 // trigger_error("Undefined property '$name'.".self::getCallerInfoString(), E_USER_NOTICE);
152 return isset($this->$name);
153 }
154
162 public function __call($name, $arguments)
163 {
164 $deprecatedMethods = $this->deprecatedMethods();
165 if (isset($deprecatedMethods[$name])) {
166 $newMethod = $deprecatedMethods[$name];
167 if ($this->isDeprecatedReportingEnabled()) {
168 trigger_error("Calling deprecated method '".$name."' on class ".get_class($this).". Use '".$newMethod."' instead.".self::getCallerInfoString(), E_USER_DEPRECATED);
169 }
170 if (method_exists($this, $newMethod)) {
171 return call_user_func_array([$this, $newMethod], $arguments);
172 } else {
173 trigger_error("Replacement method '".$newMethod."' not implemented.", E_USER_NOTICE);
174 }
175 }
176 trigger_error("Call to undefined method '".$name."'.".self::getCallerInfoString(), E_USER_ERROR);
177 }
178
179
185 private function isDeprecatedReportingEnabled()
186 {
187 // By default, if enableDeprecatedReporting is set, use that value.
188
189 if (property_exists($this, 'enableDeprecatedReporting')) {
190 // If the property exists, then we use it.
191 return (bool) $this->enableDeprecatedReporting;
192 }
193
194 return (error_reporting() & E_DEPRECATED) === E_DEPRECATED;
195 }
196
202 private function isDynamicPropertiesEnabled()
203 {
204 // By default, if enableDynamicProperties is set, use that value.
205
206 if (property_exists($this, 'enableDynamicProperties')) {
207 // If the property exists, then we use it.
208 return (bool) $this->enableDynamicProperties;
209 }
210
211 // Otherwise it depends on a choice
212
213 // 1. Return true to accept DynamicProperties in all cases.
214 return true;
215 // 2. Accept dynamic properties only when not testing
216 // return !class_exists('PHPUnit\Framework\TestSuite')
217 // 3. Accept dynamic properties only when deprecation notifications are disabled
218 // return $this->isDeprecatedReportingEnabled();
219 // 4. Do not accept dynamic properties (should be the default eventually).
220 // return false;
221 }
222
230 protected function deprecatedProperties()
231 {
232 // Define deprecated properties and their replacements
233 return array(
234 // 'oldProperty' => 'newProperty',
235 // Add deprecated properties and their replacements in subclass implementation
236 );
237 }
238
246 protected function deprecatedMethods()
247 {
248 // Define deprecated methods and their replacements
249 return array(
250 // 'oldMethod' => 'newMethod',
251 // Add deprecated methods and their replacements in subclass implementation
252 );
253 }
254
255
261 final protected static function getCallerInfoString()
262 {
263 $backtrace = debug_backtrace();
264 $msg = "";
265 if (count($backtrace) >= 2) {
266 $trace = $backtrace[1];
267 if (isset($trace['file'], $trace['line'])) {
268 $msg = " From {$trace['file']}:{$trace['line']}.";
269 }
270 }
271 return $msg;
272 }
273}
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.