Completed
Branch FET-10306-introduce_Scripts_cl... (be58f2)
by
unknown
21:17 queued 11:07
created

Registry::getData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 5
c 1
b 0
f 1
nc 2
nop 2
dl 0
loc 7
rs 9.4285
1
<?php
2
namespace EventEspresso\core\services\assets;
3
4
use InvalidArgumentException;
5
6
defined('EVENT_ESPRESSO_VERSION') || exit;
7
8
/**
9
 * Used for registering assets used in EE.
10
 *
11
 * @package    EventEspresso
12
 * @subpackage services\assets
13
 * @author     Darren Ethier
14
 * @since      4.9.24.rc.004
15
 */
16
class Registry
17
{
18
19
    /**
20
     * This holds the jsdata data object that will be exposed on pages that enqueue the `eejs-core` script.
21
     * @var array
22
     */
23
    protected $jsdata = array();
24
25
26
    /**
27
     * Registry constructor.
28
     * Hooking into WP actions for script registry.
29
     */
30
    public function __construct()
31
    {
32
        add_action('wp_enqueue_scripts', array($this, 'scripts'), 100);
33
        add_action('admin_enqueue_scripts', array($this, 'scripts'), 100);
34
    }
35
36
37
    /**
38
     * Callback for the WP script actions.
39
     * Used to register globally accessible core scripts.
40
     * Also used to add the eejs.data object to the source for any js having eejs-core as a dependency.
41
     */
42
    public function scripts()
43
    {
44
        wp_register_script(
45
            'eejs-core',
46
            EE_PLUGIN_DIR_URL . 'core/services/core_assets/eejs-core.js',
47
            array(),
48
            espresso_version(),
49
            true
50
        );
51
        wp_localize_script('eejs-core', 'eejs', array('data'=>$this->jsdata));
52
    }
53
54
55
    /**
56
     * Used to add data to eejs.data object.
57
     *
58
     * Note:  Overriding existing data is not allowed.  To help enforce uniqueness, key/value pairs are added as an element
59
     * of the method/function name for the caller.  So for instance, if this coded is called from a class, something like
60
     * this would be done:
61
62
     * EE_Registry::instance()->AssetsRegistry->addData(__METHOD__, 'my_key', 'my_value');
63
     *
64
     * If this is being called within a function then you'd do:
65
     *
66
     * EE_Registry::instance()->AssetsRegistry->addData(__FUNCTION__, 'my_key', 'my_value');
67
     *
68
     * This method WILL validate whether the incoming method/function name is an actual function or method.
69
     *
70
     * Since `::` and `\` is not accessible via javascript object dot notation. Umlauts (::) will be escaped with a
71
     * double underscore (__) and if the method belongs to a namespaced class, the backslashes will be escaped with a
72
     * single underscore (_).  So if your method was a part of namespaced class resulting in something like this:
73
     * EventEspresso\some\namespace\Class::myMethod
74
     *
75
     * ...then you would be able to access all the data attached to it in your js via:
76
     *
77
     * var myData = eejs.data.EventEspresso_some_namespace_Class__myMethod
78
     *
79
     *
80
     * @param string $method_name  Name of actual method or function.
81
     * @param string $key          Key used to access your data
82
     * @param string|array $value  Value to attach to key
83
     * @throws \InvalidArgumentException
84
     */
85
    public function addData($method_name, $key, $value)
86
    {
87
        $this->verifyMethod($method_name);
88
89
        //convert method name into js friendly string
90
        $method_name = $this->methodNameToJsFriendlyString($method_name);
91
        if ($this->verifyDataNotExisting($method_name, $key, $value)) {
92
            $this->jsdata[$method_name][$key] = $value;
93
        }
94
    }
95
96
97
    /**
98
     * Similar to addData except this allows for users to push values to an existing key where the values on key are
99
     * elements in an array.
100
     *
101
     * When you use this method, the value you include will be appended to the end of an array on $key.
102
     *
103
     * So if the $key was 'test' and you added a value of 'my_data' then it would be represented in the javascript object
104
     * like this,
105
     *
106
     * eejs.data.function_name.test = [
107
     *     my_data,
108
     * ]
109
     *
110
     * If there has already been a scalar value attached to the data object for the given method_name, then
111
     * this will throw an exception.
112
     *
113
     * @see Registry::addData for more info on purpose of $method_name
114
     *
115
     * @param string $method_name  Name of actual method or function.
116
     * @param string $key          Key to attach data to.
117
     * @param string|array $value  Value being registered.
118
     * @throws InvalidArgumentException
119
     */
120
    public function pushData($method_name, $key, $value)
121
    {
122
        $this->verifyMethod($method_name);
123
        $method_name = $this->methodNameToJsFriendlyString($method_name);
124
125
        if (isset($this->jsdata[$method_name], $this->jsdata[$method_name][$key])
126
            && ! is_array($this->jsdata[$method_name][$key])
127
        ) {
128
            throw new invalidArgumentException(
129
                sprintf(
130
                    __(
131
                        'The value for %1$s is already set and it is not an array. The %2$s method can only be used to
132
                         push values to this data element when it is an array.',
133
                        'event_espresso'
134
                    ),
135
                    $key,
136
                    __METHOD__
137
                )
138
            );
139
        }
140
141
        $this->jsdata[$method_name][$key][] = $value;
142
    }
143
144
145
    /**
146
     * Retrieve registered data.
147
     *
148
     * @param string $method_name   Name of actual method or function.
149
     * @param string $key           Name of key to attach data to.
150
     * @return mixed                If there is no for the given key, then false is returned.
151
     */
152
    public function getData($method_name, $key)
153
    {
154
        $method_name = $this->methodNameToJsFriendlyString($method_name);
155
        return isset($this->jsdata[$method_name], $this->jsdata[$method_name][$key])
156
            ? $this->jsdata[$method_name][$key]
157
            : false;
158
    }
159
160
161
    /**
162
     * Verifies the given string represents an actual function or method.
163
     * @param string $method_name
164
     * @throws InvalidArgumentException
165
     */
166
    protected function verifyMethod($method_name)
167
    {
168
        if (! is_callable($method_name)) {
169
            throw new InvalidArgumentException(
170
                sprintf(
171
                    __('The value for $method_name (%1$s) is not valid.  You must send in a valid function/method name that 
172
                    your key value pair for the data will be attached to.', 'event_espresso'),
173
                    $method_name
174
                )
175
            );
176
        }
177
    }
178
179
180
181
182
    /**
183
     * Verifies whether the given data exists already on the jsdata array.
184
     *
185
     * Overriding data is not allowed.
186
     *
187
     * @param string       $method_name  Name representing actual function or method.
188
     * @param string       $key          Index for data.
189
     * @param string|array $value        Value being stored.
190
     * @return bool        If valid then return true.
191
     * @throws InvalidArgumentException if data already exists.
192
     */
193
    protected function verifyDataNotExisting($method_name, $key, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
    {
195
        if (isset($this->jsdata[$method_name], $this->jsdata[$method_name][$key])) {
196
            if (is_array($this->jsdata[$method_name][$key])) {
197
                throw new InvalidArgumentException(
198
                    sprintf(
199
                        __(
200
                            'The value for %1$s already exists in the Registry::eejs object for %2$s.
201
                            Overrides are not allowed. Since the value of this data is an array, you may want to use the
202
                            %2$s method to push your value to the array.',
203
                            'event_espresso'
204
                        ),
205
                        $key,
206
                        $method_name,
207
                        'pushData'
208
                    )
209
                );
210
            } else {
211
                throw new InvalidArgumentException(
212
                    sprintf(
213
                        __(
214
                            'The value for %1$s already exists in the Registry::eejs object for %2$s. Overrides are not
215
                            allowed.  Consider attaching your value to a different key',
216
                            'event_espresso'
217
                        ),
218
                        $key,
219
                        $method_name
220
                    )
221
                );
222
            }
223
        }
224
        return true;
225
    }
226
227
228
229
230
    /**
231
     * Escapes backslash and umlauts existing in given string.
232
     *
233
     * '::' becomes '__'
234
     * '\'  becomes '_'
235
     *
236
     * @param string $method_name  The string to escape.
237
     * @return string
238
     */
239
    protected function methodNameToJsFriendlyString($method_name)
240
    {
241
        //all `\` from namespaces gets converted to single underscore
242
        $method_name = str_replace('\\', '_', $method_name);
243
244
        //all `::` for class::method formats gets converted to double underscore.
245
        return str_replace('::', '__', $method_name);
246
    }
247
}
248