/var/www/html_us/wp-content/plugins/woocommerce/src/Internal/Traits/AccessiblePrivateMethods.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<?php

namespace Automattic\WooCommerce\Internal\Traits;

/**
 * DON'T USE THIS TRAIT. It will be removed in WooCommerce 10.5.
 * Instead, make the hook target methods public and mark them with an @internal annotation.
 *
 * This trait allows making private methods of a class accessible from outside.
 * This is useful to define hook handlers with the [$this, 'method'] or [__CLASS__, 'method'] syntax
 * without having to make the method public (and thus having to keep it forever for backwards compatibility).
 *
 * Example:
 *
 * class Foobar {
 *   use AccessiblePrivateMethods;
 *
 *   public function __construct() {
 *     self::add_action('some_action', [$this, 'handle_some_action']);
 *   }
 *
 *   public static function init() {
 *     self::add_filter('some_filter', [__CLASS__, 'handle_some_filter']);
 *   }
 *
 *   private function handle_some_action() {
 *   }
 *
 *   private static function handle_some_filter() {
 *   }
 * }
 *
 * For this to work the callback must be an array and the first element of the array must be either '$this', '__CLASS__',
 * or another instance of the same class; otherwise the method won't be marked as accessible
 * (but the corresponding WordPress 'add_action' and 'add_filter' functions will still be called).
 *
 * No special procedure is needed to remove hooks set up with these methods, the regular 'remove_action'
 * and 'remove_filter' functions provided by WordPress can be used as usual.
 *
 * @deprecated 9.6.0 Make the hook target methods public and mark them with an @internal annotation. This trait will be removed in WooCommerce 10.5.
 */
trait AccessiblePrivateMethods {

    
//phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
    /**
     * List of instance methods marked as externally accessible.
     *
     * @var array
     */
    
private $_accessible_private_methods = array();

    
/**
     * List of static methods marked as externally accessible.
     *
     * @var array
     */
    
private static $_accessible_static_private_methods = array();
    
//phpcs:enable PSR2.Classes.PropertyDeclaration.Underscore

    /**
     * Register a WordPress action.
     * If the callback refers to a private or protected instance method in this class, the method is marked as externally accessible.
     *
     * $callback can be a standard callable, or a string representing the name of a method in this class.
     *
     * @param string          $hook_name       The name of the action to add the callback to.
     * @param callable|string $callback        The callback to be run when the action is called.
     * @param int             $priority        Optional. Used to specify the order in which the functions
     *                                         associated with a particular action are executed.
     *                                         Lower numbers correspond with earlier execution,
     *                                         and functions with the same priority are executed
     *                                         in the order in which they were added to the action. Default 10.
     * @param int             $accepted_args   Optional. The number of arguments the function accepts. Default 1.
     */
    
protected static function add_actionstring $hook_name$callbackint $priority 10int $accepted_args ): void {
        
self::process_callback_before_hooking$callback );
        
add_action$hook_name$callback$priority$accepted_args );
    }

    
/**
     * Register a WordPress filter.
     * If the callback refers to a private or protected instance method in this class, the method is marked as externally accessible.
     *
     * $callback can be a standard callable, or a string representing the name of a method in this class.
     *
     * @param string          $hook_name       The name of the filter to add the callback to.
     * @param callable|string $callback        The callback to be run when the filter is called.
     * @param int             $priority        Optional. Used to specify the order in which the functions
     *                                         associated with a particular filter are executed.
     *                                         Lower numbers correspond with earlier execution,
     *                                         and functions with the same priority are executed
     *                                         in the order in which they were added to the filter. Default 10.
     * @param int             $accepted_args   Optional. The number of arguments the function accepts. Default 1.
     */
    
protected static function add_filterstring $hook_name$callbackint $priority 10int $accepted_args ): void {
        
self::process_callback_before_hooking$callback );
        
add_filter$hook_name$callback$priority$accepted_args );
    }

    
/**
     * Do the required processing to a callback before invoking the WordPress 'add_action' or 'add_filter' function.
     *
     * @param callable $callback The callback to process.
     * @return void
     */
    
protected static function process_callback_before_hooking$callback ): void {
        if ( ! 
is_array$callback ) || count$callback ) < ) {
            return;
        }

        
$first_item $callback[0];
        if ( 
__CLASS__ === $first_item ) {
            static::
mark_static_method_as_accessible$callback[1] );
        } elseif ( 
is_object$first_item ) && get_class$first_item ) === __CLASS__ ) {
            
$first_item->mark_method_as_accessible$callback[1] );
        }
    }

    
/**
     * Register a private or protected instance method of this class as externally accessible.
     *
     * @param string $method_name Method name.
     * @return bool True if the method has been marked as externally accessible, false if the method doesn't exist.
     */
    
protected function mark_method_as_accessiblestring $method_name ): bool {
        
// Note that an "is_callable" check would be useless here:
        // "is_callable" always returns true if the class implements __call.
        
if ( method_exists$this$method_name ) ) {
            
$this->_accessible_private_methods$method_name ] = $method_name;
            return 
true;
        }

        return 
false;
    }

    
/**
     * Register a private or protected static method of this class as externally accessible.
     *
     * @param string $method_name Method name.
     * @return bool True if the method has been marked as externally accessible, false if the method doesn't exist.
     */
    
protected static function mark_static_method_as_accessiblestring $method_name ): bool {
        if ( 
method_exists__CLASS__$method_name ) ) {
            static::
$_accessible_static_private_methods$method_name ] = $method_name;
            return 
true;
        }

        return 
false;
    }

    
/**
     * Undefined/inaccessible instance method call handler.
     *
     * @param string $name Called method name.
     * @param array  $arguments Called method arguments.
     * @return mixed
     * @throws \Error The called instance method doesn't exist or is private/protected and not marked as externally accessible.
     */
    
public function __call$name$arguments ) {
        if ( isset( 
$this->_accessible_private_methods$name ] ) ) {
            return 
call_user_func_array( array( $this$name ), $arguments );
        } elseif ( 
is_callable( array( 'parent''__call' ) ) ) {
            return 
parent::__call$name$arguments );
        } elseif ( 
method_exists$this$name ) ) {
            throw new 
\Error'Call to private method ' get_class$this ) . '::' $name );
        } else {
            throw new 
\Error'Call to undefined method ' get_class$this ) . '::' $name );
        }
    }

    
/**
     * Undefined/inaccessible static method call handler.
     *
     * @param string $name Called method name.
     * @param array  $arguments Called method arguments.
     * @return mixed
     * @throws \Error The called static method doesn't exist or is private/protected and not marked as externally accessible.
     */
    
public static function __callStatic$name$arguments ) {
        if ( isset( static::
$_accessible_static_private_methods$name ] ) ) {
            return 
call_user_func_array( array( __CLASS__$name ), $arguments );
        } elseif ( 
is_callable( array( 'parent''__callStatic' ) ) ) {
            return 
parent::__callStatic$name$arguments );
        } elseif ( 
'add_action' === $name || 'add_filter' === $name ) {
            
$proper_method_name 'add_static_' substr$name);
            throw new 
\Error__CLASS__ '::' $name " can't be called statically, did you mean '$proper_method_name'?" );
        } elseif ( 
method_exists__CLASS__$name ) ) {
            throw new 
\Error'Call to private method ' __CLASS__ '::' $name );
        } else {
            throw new 
\Error'Call to undefined method ' __CLASS__ '::' $name );
        }
    }
}