2024-02-13 11:01:56 +01:00
< ? php
2025-02-19 15:20:05 +01:00
/* Copyright ( C ) 2024 - 2025 MDW < mdeweerd @ users . noreply . github . com >
2024-02-13 11:01:56 +01:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
/**
* @ file DeprecationHandler . php
* @ ingroup core
* @ brief trait for handling deprecated properties and methods
*/
/**
* Class for handling deprecated properties and methods
*/
trait DolDeprecationHandler
{
// Define the following in the class using the trait
// to allow properties to not be defined when referenced.
// So only deprecated value generate exceptions.
//
// protected $enableDynamicProperties = true;
2024-04-02 21:29:16 +02:00
// Define the following in the class using the trait
// to disallow Dolibarr deprecation warnings.
//
// protected $enableDeprecatedReporting = false;
2024-02-13 11:01:56 +01:00
/**
* Get deprecated property
*
* @ param string $name Name of property
* @ return mixed Value for replacement property
*/
public function __get ( $name )
{
$deprecatedProperties = $this -> deprecatedProperties ();
if ( isset ( $deprecatedProperties [ $name ])) {
$newProperty = $deprecatedProperties [ $name ];
2024-04-03 00:51:18 +02:00
$msg = " DolDeprecationHandler: Accessing deprecated property ' " . $name . " ' on class " . get_class ( $this ) . " . Use ' " . $newProperty . " ' instead. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
if ( $this -> isDeprecatedReportingEnabled ()) {
trigger_error ( $msg , E_USER_DEPRECATED );
}
return $this -> $newProperty ;
}
if ( $this -> isDynamicPropertiesEnabled ()) {
return null ; // If the property is set, then __get is not called.
}
2024-04-02 23:16:48 +02:00
$msg = " DolDeprecationHandler: Undefined property ' " . $name . " ' " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
trigger_error ( $msg , E_USER_NOTICE );
return $this -> $name ; // Returning value anyway (graceful degradation)
}
/**
* Set deprecated property
*
* @ param string $name Name of property
* @ param mixed $value Value of property
* @ return void
*/
public function __set ( $name , $value )
{
$deprecatedProperties = $this -> deprecatedProperties ();
if ( isset ( $deprecatedProperties [ $name ])) {
$newProperty = $deprecatedProperties [ $name ];
2024-04-02 23:16:48 +02:00
// Setting is for compatibility, should not be a problem and should be reported only in paranoid mode
/*
$msg = " DolDeprecationHandler: Setting value to the deprecated property ' " . $name . " '. Use ' " . $newProperty . " ' instead. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
if ( $this -> isDeprecatedReportingEnabled ()) {
trigger_error ( $msg , E_USER_DEPRECATED );
}
2024-04-02 23:16:48 +02:00
*/
2024-02-13 11:01:56 +01:00
$this -> $newProperty = $value ;
return ;
}
if ( ! $this -> isDynamicPropertiesEnabled ()) {
2024-04-02 23:16:48 +02:00
$msg = " DolDeprecationHandler: Undefined property ' " . $name . " ' " . self :: getCallerInfoString ();
2024-04-03 00:51:18 +02:00
trigger_error ( $msg , E_USER_NOTICE );
2024-02-13 11:01:56 +01:00
$this -> $name = $value ; // Setting anyway for graceful degradation
} else {
$this -> $name = $value ;
}
}
/**
* Unset deprecated property
*
* @ param string $name Name of property
* @ return void
*/
public function __unset ( $name )
{
$deprecatedProperties = $this -> deprecatedProperties ();
if ( isset ( $deprecatedProperties [ $name ])) {
$newProperty = $deprecatedProperties [ $name ];
2024-04-02 23:16:48 +02:00
// Unsetting is for compatibility, should not be a problem and should be reported only in paranoid mode
/*
$msg = " DolDeprecationHandler: Unsetting deprecated property ' " . $name . " '. Use ' " . $newProperty . " ' instead. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
if ( $this -> isDeprecatedReportingEnabled ()) {
trigger_error ( $msg , E_USER_DEPRECATED );
}
2024-04-02 23:16:48 +02:00
*/
2024-02-13 11:01:56 +01:00
unset ( $this -> $newProperty );
return ;
}
if ( ! $this -> isDynamicPropertiesEnabled ()) {
2024-04-03 00:51:18 +02:00
$msg = " DolDeprecationHandler: Undefined property ' " . $name . " '. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
trigger_error ( $msg , E_USER_NOTICE );
}
}
/**
* Test if deprecated property is set
*
* @ param string $name Name of property
* @ return void
*/
public function __isset ( $name )
{
$deprecatedProperties = $this -> deprecatedProperties ();
if ( isset ( $deprecatedProperties [ $name ])) {
$newProperty = $deprecatedProperties [ $name ];
2024-04-03 00:51:18 +02:00
$msg = " DolDeprecationHandler: Accessing deprecated property ' " . $name . " ' on class " . get_class ( $this ) . " . Use ' " . $newProperty . " ' instead. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
if ( $this -> isDeprecatedReportingEnabled ()) {
trigger_error ( $msg , E_USER_DEPRECATED );
}
2025-02-19 15:20:05 +01:00
return isset ( $this -> $newProperty );
2024-02-13 11:01:56 +01:00
} elseif ( $this -> isDynamicPropertiesEnabled ()) {
return isset ( $this -> $name );
}
2024-04-02 23:16:48 +02:00
$msg = " DolDeprecationHandler: Undefined property ' " . $name . " '. " . self :: getCallerInfoString ();
2024-02-13 11:01:56 +01:00
dol_syslog ( $msg );
// trigger_error("Undefined property '$name'.".self::getCallerInfoString(), E_USER_NOTICE);
return isset ( $this -> $name );
}
/**
* Call deprecated method
*
* @ param string $name Name of method
* @ param mixed [] $arguments Method arguments
* @ return mixed
*/
public function __call ( $name , $arguments )
{
$deprecatedMethods = $this -> deprecatedMethods ();
if ( isset ( $deprecatedMethods [ $name ])) {
$newMethod = $deprecatedMethods [ $name ];
if ( $this -> isDeprecatedReportingEnabled ()) {
2024-04-03 00:51:18 +02:00
trigger_error ( " Calling deprecated method ' " . $name . " ' on class " . get_class ( $this ) . " . Use ' " . $newMethod . " ' instead. " . self :: getCallerInfoString (), E_USER_DEPRECATED );
2024-02-13 11:01:56 +01:00
}
if ( method_exists ( $this , $newMethod )) {
return call_user_func_array ([ $this , $newMethod ], $arguments );
} else {
2024-04-02 23:16:48 +02:00
trigger_error ( " Replacement method ' " . $newMethod . " ' not implemented. " , E_USER_NOTICE );
2024-02-13 11:01:56 +01:00
}
}
2024-04-03 00:51:18 +02:00
trigger_error ( " Call to undefined method ' " . $name . " '. " . self :: getCallerInfoString (), E_USER_ERROR );
2024-02-13 11:01:56 +01:00
}
/**
2024-04-02 21:29:16 +02:00
* Indicate if deprecations should be reported . Depends on -> enableDeprecatedReporting . If not set , depends on PHP setup .
2024-02-13 11:01:56 +01:00
*
* @ return bool
*/
private function isDeprecatedReportingEnabled ()
{
2024-04-02 21:29:16 +02:00
// By default, if enableDeprecatedReporting is set, use that value.
if ( property_exists ( $this , 'enableDeprecatedReporting' )) {
// If the property exists, then we use it.
return ( bool ) $this -> enableDeprecatedReporting ;
}
2024-02-13 11:01:56 +01:00
return ( error_reporting () & E_DEPRECATED ) === E_DEPRECATED ;
}
/**
* Indicate if dynamic properties are accepted
*
* @ return bool
*/
private function isDynamicPropertiesEnabled ()
{
// By default, if enableDynamicProperties is set, use that value.
2025-02-19 15:20:05 +01:00
if ( property_exists ( $this , 'enableDynamicProperties' )) { // @phpstan-ignore-line
2024-02-13 11:01:56 +01:00
// If the property exists, then we use it.
return ( bool ) $this -> enableDynamicProperties ;
}
// Otherwise it depends on a choice
// 1. Return true to accept DynamicProperties in all cases.
return true ;
// 2. Accept dynamic properties only when not testing
// return !class_exists('PHPUnit\Framework\TestSuite')
// 3. Accept dynamic properties only when deprecation notifications are disabled
// return $this->isDeprecatedReportingEnabled();
// 4. Do not accept dynamic properties (should be the default eventually).
// return false;
}
/**
* Provide list of deprecated properties
*
* Override this method in subclasses
*
* @ return array < string , string > Mapping of deprecated properties
*/
protected function deprecatedProperties ()
{
// Define deprecated properties and their replacements
return array (
// 'oldProperty' => 'newProperty',
2024-08-13 11:53:21 +02:00
// Add deprecated properties and their replacements in subclass implementation
2024-02-13 11:01:56 +01:00
);
}
/**
* Provide list of deprecated methods
*
* Override this method in subclasses
*
* @ return array < string , string > Mapping of deprecated methods
*/
protected function deprecatedMethods ()
{
// Define deprecated methods and their replacements
return array (
// 'oldMethod' => 'newMethod',
// Add deprecated methods and their replacements in subclass implementation
);
}
/**
* Get caller info
*
* @ return string
*/
final protected static function getCallerInfoString ()
{
$backtrace = debug_backtrace ();
$msg = " " ;
if ( count ( $backtrace ) >= 2 ) {
$trace = $backtrace [ 1 ];
if ( isset ( $trace [ 'file' ], $trace [ 'line' ])) {
$msg = " From { $trace [ 'file' ] } : { $trace [ 'line' ] } . " ;
}
}
return $msg ;
}
}