Completed
Branch Gutenberg/create-wp.data-store... (35e4b7)
by
unknown
65:58 queued 53:16
created
core/services/assets/Registry.php 2 patches
Indentation   +694 added lines, -694 removed lines patch added patch discarded remove patch
@@ -27,705 +27,705 @@
 block discarded – undo
27 27
 class Registry
28 28
 {
29 29
 
30
-    const ASSET_TYPE_CSS = 'css';
31
-    const ASSET_TYPE_JS = 'js';
32
-    const ASSET_NAMESPACE = 'core';
33
-
34
-    /**
35
-     * @var EE_Template_Config $template_config
36
-     */
37
-    protected $template_config;
38
-
39
-    /**
40
-     * @var EE_Currency_Config $currency_config
41
-     */
42
-    protected $currency_config;
43
-
44
-    /**
45
-     * This holds the jsdata data object that will be exposed on pages that enqueue the `eejs-core` script.
46
-     *
47
-     * @var array
48
-     */
49
-    protected $jsdata = array();
50
-
51
-
52
-    /**
53
-     * This keeps track of all scripts with registered data.  It is used to prevent duplicate data objects setup in the
54
-     * page source.
55
-     * @var array
56
-     */
57
-    protected $script_handles_with_data = array();
58
-
59
-
60
-    /**
61
-     * @var DomainInterface
62
-     */
63
-    protected $domain;
64
-
65
-
66
-    /**
67
-     * @var I18nRegistry
68
-     */
69
-    private $i18n_registry;
70
-
71
-
72
-
73
-    /**
74
-     * Holds the manifest data obtained from registered manifest files.
75
-     * Manifests are maps of asset chunk name to actual built asset file names.
76
-     * Shape of this array is:
77
-     *
78
-     * array(
79
-     *  'some_namespace_slug' => array(
80
-     *      'some_chunk_name' => array(
81
-     *          'js' => 'filename.js'
82
-     *          'css' => 'filename.js'
83
-     *      ),
84
-     *      'url_base' => 'https://baseurl.com/to/assets
85
-     *  )
86
-     * )
87
-     *
88
-     * @var array
89
-     */
90
-    private $manifest_data = array();
91
-
92
-
93
-    /**
94
-     * Registry constructor.
95
-     * Hooking into WP actions for script registry.
96
-     *
97
-     * @param EE_Template_Config $template_config
98
-     * @param EE_Currency_Config $currency_config
99
-     * @param I18nRegistry       $i18n_registry
100
-     * @param DomainInterface    $domain
101
-     * @throws InvalidArgumentException
102
-     * @throws InvalidFilePathException
103
-     */
104
-    public function __construct(
105
-        EE_Template_Config $template_config,
106
-        EE_Currency_Config $currency_config,
107
-        I18nRegistry $i18n_registry,
108
-        DomainInterface $domain
109
-    ) {
110
-        $this->template_config = $template_config;
111
-        $this->currency_config = $currency_config;
112
-        $this->domain = $domain;
113
-        $this->i18n_registry = $i18n_registry;
114
-        $this->registerManifestFile(
115
-            self::ASSET_NAMESPACE,
116
-            $this->domain->distributionAssetsUrl(),
117
-            $this->domain->distributionAssetsPath() . 'build-manifest.json'
118
-        );
119
-        add_action('wp_enqueue_scripts', array($this, 'scripts'), 1);
120
-        add_action('admin_enqueue_scripts', array($this, 'scripts'), 1);
121
-        add_action('wp_enqueue_scripts', array($this, 'enqueueData'), 2);
122
-        add_action('admin_enqueue_scripts', array($this, 'enqueueData'), 2);
123
-        add_action('wp_print_footer_scripts', array($this, 'enqueueData'), 1);
124
-        add_action('admin_print_footer_scripts', array($this, 'enqueueData'), 1);
125
-    }
126
-
127
-
128
-    /**
129
-     * For classes that have Registry as a dependency, this provides a handy way to register script handles for i18n
130
-     * translation handling.
131
-     *
132
-     * @return I18nRegistry
133
-     */
134
-    public function getI18nRegistry()
135
-    {
136
-        return $this->i18n_registry;
137
-    }
138
-
139
-    /**
140
-     * Callback for the WP script actions.
141
-     * Used to register globally accessible core scripts.
142
-     * Also used to add the eejs.data object to the source for any js having eejs-core as a dependency.
143
-     *
144
-     */
145
-    public function scripts()
146
-    {
147
-        global $wp_version;
148
-        wp_register_script(
149
-            'ee-manifest',
150
-            $this->getJsUrl(self::ASSET_NAMESPACE, 'manifest'),
151
-            array(),
152
-            null,
153
-            true
154
-        );
155
-        wp_register_script(
156
-            'eejs-core',
157
-            $this->getJsUrl(self::ASSET_NAMESPACE, 'eejs'),
158
-            array('ee-manifest'),
159
-            null,
160
-            true
161
-        );
162
-        wp_register_script(
163
-            'ee-vendor-react',
164
-            $this->getJsUrl(self::ASSET_NAMESPACE, 'reactVendor'),
165
-            array('eejs-core'),
166
-            null,
167
-            true
168
-        );
169
-        //only run this if WordPress 4.4.0 > is in use.
170
-        if (version_compare($wp_version, '4.4.0', '>')) {
171
-            //js.api
172
-            wp_register_script(
173
-                'eejs-api',
174
-                EE_LIBRARIES_URL . 'rest_api/assets/js/eejs-api.min.js',
175
-                array('underscore', 'eejs-core'),
176
-                EVENT_ESPRESSO_VERSION,
177
-                true
178
-            );
179
-            $this->jsdata['eejs_api_nonce'] = wp_create_nonce('wp_rest');
180
-            $this->jsdata['paths'] = array(
181
-                'rest_route' => rest_url('ee/v4.8.36/'),
182
-                'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName()
183
-            );
184
-        }
185
-        if (! is_admin()) {
186
-            $this->loadCoreCss();
187
-        }
188
-        $this->registerTranslationsForHandles(array('eejs-core'));
189
-        $this->loadCoreJs();
190
-        $this->loadJqueryValidate();
191
-        $this->loadAccountingJs();
192
-        $this->loadQtipJs();
193
-        $this->registerAdminAssets();
194
-    }
195
-
196
-
197
-
198
-    /**
199
-     * Call back for the script print in frontend and backend.
200
-     * Used to call wp_localize_scripts so that data can be added throughout the runtime until this later hook point.
201
-     *
202
-     * @since 4.9.31.rc.015
203
-     */
204
-    public function enqueueData()
205
-    {
206
-        $this->removeAlreadyRegisteredDataForScriptHandles();
207
-        wp_add_inline_script(
208
-            'eejs-core',
209
-            'var eejsdata=' . wp_json_encode(array('data' => $this->jsdata)),
210
-            'before'
211
-        );
212
-        wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings);
213
-        $this->localizeAccountingJs();
214
-        $this->addRegisteredScriptHandlesWithData('eejs-core');
215
-        $this->addRegisteredScriptHandlesWithData('espresso_core');
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     * Used to add data to eejs.data object.
222
-     * Note:  Overriding existing data is not allowed.
223
-     * Data will be accessible as a javascript object when you list `eejs-core` as a dependency for your javascript.
224
-     * If the data you add is something like this:
225
-     *  $this->addData( 'my_plugin_data', array( 'foo' => 'gar' ) );
226
-     * It will be exposed in the page source as:
227
-     *  eejs.data.my_plugin_data.foo == gar
228
-     *
229
-     * @param string       $key   Key used to access your data
230
-     * @param string|array $value Value to attach to key
231
-     * @throws InvalidArgumentException
232
-     */
233
-    public function addData($key, $value)
234
-    {
235
-        if ($this->verifyDataNotExisting($key)) {
236
-            $this->jsdata[$key] = $value;
237
-        }
238
-    }
239
-
240
-
241
-
242
-    /**
243
-     * Similar to addData except this allows for users to push values to an existing key where the values on key are
244
-     * elements in an array.
245
-     * When you use this method, the value you include will be appended to the end of an array on $key.
246
-     * So if the $key was 'test' and you added a value of 'my_data' then it would be represented in the javascript
247
-     * object like this, eejs.data.test = [ my_data,
248
-     * ]
249
-     * If there has already been a scalar value attached to the data object given key, then
250
-     * this will throw an exception.
251
-     *
252
-     * @param string       $key   Key to attach data to.
253
-     * @param string|array $value Value being registered.
254
-     * @throws InvalidArgumentException
255
-     */
256
-    public function pushData($key, $value)
257
-    {
258
-        if (isset($this->jsdata[$key])
259
-            && ! is_array($this->jsdata[$key])
260
-        ) {
261
-            throw new invalidArgumentException(
262
-                sprintf(
263
-                    __(
264
-                        'The value for %1$s is already set and it is not an array. The %2$s method can only be used to
30
+	const ASSET_TYPE_CSS = 'css';
31
+	const ASSET_TYPE_JS = 'js';
32
+	const ASSET_NAMESPACE = 'core';
33
+
34
+	/**
35
+	 * @var EE_Template_Config $template_config
36
+	 */
37
+	protected $template_config;
38
+
39
+	/**
40
+	 * @var EE_Currency_Config $currency_config
41
+	 */
42
+	protected $currency_config;
43
+
44
+	/**
45
+	 * This holds the jsdata data object that will be exposed on pages that enqueue the `eejs-core` script.
46
+	 *
47
+	 * @var array
48
+	 */
49
+	protected $jsdata = array();
50
+
51
+
52
+	/**
53
+	 * This keeps track of all scripts with registered data.  It is used to prevent duplicate data objects setup in the
54
+	 * page source.
55
+	 * @var array
56
+	 */
57
+	protected $script_handles_with_data = array();
58
+
59
+
60
+	/**
61
+	 * @var DomainInterface
62
+	 */
63
+	protected $domain;
64
+
65
+
66
+	/**
67
+	 * @var I18nRegistry
68
+	 */
69
+	private $i18n_registry;
70
+
71
+
72
+
73
+	/**
74
+	 * Holds the manifest data obtained from registered manifest files.
75
+	 * Manifests are maps of asset chunk name to actual built asset file names.
76
+	 * Shape of this array is:
77
+	 *
78
+	 * array(
79
+	 *  'some_namespace_slug' => array(
80
+	 *      'some_chunk_name' => array(
81
+	 *          'js' => 'filename.js'
82
+	 *          'css' => 'filename.js'
83
+	 *      ),
84
+	 *      'url_base' => 'https://baseurl.com/to/assets
85
+	 *  )
86
+	 * )
87
+	 *
88
+	 * @var array
89
+	 */
90
+	private $manifest_data = array();
91
+
92
+
93
+	/**
94
+	 * Registry constructor.
95
+	 * Hooking into WP actions for script registry.
96
+	 *
97
+	 * @param EE_Template_Config $template_config
98
+	 * @param EE_Currency_Config $currency_config
99
+	 * @param I18nRegistry       $i18n_registry
100
+	 * @param DomainInterface    $domain
101
+	 * @throws InvalidArgumentException
102
+	 * @throws InvalidFilePathException
103
+	 */
104
+	public function __construct(
105
+		EE_Template_Config $template_config,
106
+		EE_Currency_Config $currency_config,
107
+		I18nRegistry $i18n_registry,
108
+		DomainInterface $domain
109
+	) {
110
+		$this->template_config = $template_config;
111
+		$this->currency_config = $currency_config;
112
+		$this->domain = $domain;
113
+		$this->i18n_registry = $i18n_registry;
114
+		$this->registerManifestFile(
115
+			self::ASSET_NAMESPACE,
116
+			$this->domain->distributionAssetsUrl(),
117
+			$this->domain->distributionAssetsPath() . 'build-manifest.json'
118
+		);
119
+		add_action('wp_enqueue_scripts', array($this, 'scripts'), 1);
120
+		add_action('admin_enqueue_scripts', array($this, 'scripts'), 1);
121
+		add_action('wp_enqueue_scripts', array($this, 'enqueueData'), 2);
122
+		add_action('admin_enqueue_scripts', array($this, 'enqueueData'), 2);
123
+		add_action('wp_print_footer_scripts', array($this, 'enqueueData'), 1);
124
+		add_action('admin_print_footer_scripts', array($this, 'enqueueData'), 1);
125
+	}
126
+
127
+
128
+	/**
129
+	 * For classes that have Registry as a dependency, this provides a handy way to register script handles for i18n
130
+	 * translation handling.
131
+	 *
132
+	 * @return I18nRegistry
133
+	 */
134
+	public function getI18nRegistry()
135
+	{
136
+		return $this->i18n_registry;
137
+	}
138
+
139
+	/**
140
+	 * Callback for the WP script actions.
141
+	 * Used to register globally accessible core scripts.
142
+	 * Also used to add the eejs.data object to the source for any js having eejs-core as a dependency.
143
+	 *
144
+	 */
145
+	public function scripts()
146
+	{
147
+		global $wp_version;
148
+		wp_register_script(
149
+			'ee-manifest',
150
+			$this->getJsUrl(self::ASSET_NAMESPACE, 'manifest'),
151
+			array(),
152
+			null,
153
+			true
154
+		);
155
+		wp_register_script(
156
+			'eejs-core',
157
+			$this->getJsUrl(self::ASSET_NAMESPACE, 'eejs'),
158
+			array('ee-manifest'),
159
+			null,
160
+			true
161
+		);
162
+		wp_register_script(
163
+			'ee-vendor-react',
164
+			$this->getJsUrl(self::ASSET_NAMESPACE, 'reactVendor'),
165
+			array('eejs-core'),
166
+			null,
167
+			true
168
+		);
169
+		//only run this if WordPress 4.4.0 > is in use.
170
+		if (version_compare($wp_version, '4.4.0', '>')) {
171
+			//js.api
172
+			wp_register_script(
173
+				'eejs-api',
174
+				EE_LIBRARIES_URL . 'rest_api/assets/js/eejs-api.min.js',
175
+				array('underscore', 'eejs-core'),
176
+				EVENT_ESPRESSO_VERSION,
177
+				true
178
+			);
179
+			$this->jsdata['eejs_api_nonce'] = wp_create_nonce('wp_rest');
180
+			$this->jsdata['paths'] = array(
181
+				'rest_route' => rest_url('ee/v4.8.36/'),
182
+				'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName()
183
+			);
184
+		}
185
+		if (! is_admin()) {
186
+			$this->loadCoreCss();
187
+		}
188
+		$this->registerTranslationsForHandles(array('eejs-core'));
189
+		$this->loadCoreJs();
190
+		$this->loadJqueryValidate();
191
+		$this->loadAccountingJs();
192
+		$this->loadQtipJs();
193
+		$this->registerAdminAssets();
194
+	}
195
+
196
+
197
+
198
+	/**
199
+	 * Call back for the script print in frontend and backend.
200
+	 * Used to call wp_localize_scripts so that data can be added throughout the runtime until this later hook point.
201
+	 *
202
+	 * @since 4.9.31.rc.015
203
+	 */
204
+	public function enqueueData()
205
+	{
206
+		$this->removeAlreadyRegisteredDataForScriptHandles();
207
+		wp_add_inline_script(
208
+			'eejs-core',
209
+			'var eejsdata=' . wp_json_encode(array('data' => $this->jsdata)),
210
+			'before'
211
+		);
212
+		wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings);
213
+		$this->localizeAccountingJs();
214
+		$this->addRegisteredScriptHandlesWithData('eejs-core');
215
+		$this->addRegisteredScriptHandlesWithData('espresso_core');
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 * Used to add data to eejs.data object.
222
+	 * Note:  Overriding existing data is not allowed.
223
+	 * Data will be accessible as a javascript object when you list `eejs-core` as a dependency for your javascript.
224
+	 * If the data you add is something like this:
225
+	 *  $this->addData( 'my_plugin_data', array( 'foo' => 'gar' ) );
226
+	 * It will be exposed in the page source as:
227
+	 *  eejs.data.my_plugin_data.foo == gar
228
+	 *
229
+	 * @param string       $key   Key used to access your data
230
+	 * @param string|array $value Value to attach to key
231
+	 * @throws InvalidArgumentException
232
+	 */
233
+	public function addData($key, $value)
234
+	{
235
+		if ($this->verifyDataNotExisting($key)) {
236
+			$this->jsdata[$key] = $value;
237
+		}
238
+	}
239
+
240
+
241
+
242
+	/**
243
+	 * Similar to addData except this allows for users to push values to an existing key where the values on key are
244
+	 * elements in an array.
245
+	 * When you use this method, the value you include will be appended to the end of an array on $key.
246
+	 * So if the $key was 'test' and you added a value of 'my_data' then it would be represented in the javascript
247
+	 * object like this, eejs.data.test = [ my_data,
248
+	 * ]
249
+	 * If there has already been a scalar value attached to the data object given key, then
250
+	 * this will throw an exception.
251
+	 *
252
+	 * @param string       $key   Key to attach data to.
253
+	 * @param string|array $value Value being registered.
254
+	 * @throws InvalidArgumentException
255
+	 */
256
+	public function pushData($key, $value)
257
+	{
258
+		if (isset($this->jsdata[$key])
259
+			&& ! is_array($this->jsdata[$key])
260
+		) {
261
+			throw new invalidArgumentException(
262
+				sprintf(
263
+					__(
264
+						'The value for %1$s is already set and it is not an array. The %2$s method can only be used to
265 265
                          push values to this data element when it is an array.',
266
-                        'event_espresso'
267
-                    ),
268
-                    $key,
269
-                    __METHOD__
270
-                )
271
-            );
272
-        }
273
-        $this->jsdata[$key][] = $value;
274
-    }
275
-
276
-
277
-
278
-    /**
279
-     * Used to set content used by javascript for a template.
280
-     * Note: Overrides of existing registered templates are not allowed.
281
-     *
282
-     * @param string $template_reference
283
-     * @param string $template_content
284
-     * @throws InvalidArgumentException
285
-     */
286
-    public function addTemplate($template_reference, $template_content)
287
-    {
288
-        if (! isset($this->jsdata['templates'])) {
289
-            $this->jsdata['templates'] = array();
290
-        }
291
-        //no overrides allowed.
292
-        if (isset($this->jsdata['templates'][$template_reference])) {
293
-            throw new invalidArgumentException(
294
-                sprintf(
295
-                    __(
296
-                        'The %1$s key already exists for the templates array in the js data array.  No overrides are allowed.',
297
-                        'event_espresso'
298
-                    ),
299
-                    $template_reference
300
-                )
301
-            );
302
-        }
303
-        $this->jsdata['templates'][$template_reference] = $template_content;
304
-    }
305
-
306
-
307
-
308
-    /**
309
-     * Retrieve the template content already registered for the given reference.
310
-     *
311
-     * @param string $template_reference
312
-     * @return string
313
-     */
314
-    public function getTemplate($template_reference)
315
-    {
316
-        return isset($this->jsdata['templates'], $this->jsdata['templates'][$template_reference])
317
-            ? $this->jsdata['templates'][$template_reference]
318
-            : '';
319
-    }
320
-
321
-
322
-
323
-    /**
324
-     * Retrieve registered data.
325
-     *
326
-     * @param string $key Name of key to attach data to.
327
-     * @return mixed                If there is no for the given key, then false is returned.
328
-     */
329
-    public function getData($key)
330
-    {
331
-        return isset($this->jsdata[$key])
332
-            ? $this->jsdata[$key]
333
-            : false;
334
-    }
335
-
336
-
337
-    /**
338
-     * Get the actual asset path for asset manifests.
339
-     * If there is no asset path found for the given $chunk_name, then the $chunk_name is returned.
340
-     * @param string $namespace  The namespace associated with the manifest file hosting the map of chunk_name to actual
341
-     *                           asset file location.
342
-     * @param string $chunk_name
343
-     * @param string $asset_type
344
-     * @return string
345
-     * @since 4.9.59.p
346
-     */
347
-    public function getAssetUrl($namespace, $chunk_name, $asset_type)
348
-    {
349
-        $url = isset(
350
-            $this->manifest_data[$namespace][$chunk_name][$asset_type],
351
-            $this->manifest_data[$namespace]['url_base']
352
-        )
353
-            ? $this->manifest_data[$namespace]['url_base']
354
-              . $this->manifest_data[$namespace][$chunk_name][$asset_type]
355
-            : $chunk_name;
356
-        return apply_filters(
357
-            'FHEE__EventEspresso_core_services_assets_Registry__getAssetUrl',
358
-            $url,
359
-            $namespace,
360
-            $chunk_name,
361
-            $asset_type
362
-        );
363
-    }
364
-
365
-
366
-    /**
367
-     * Return the url to a js file for the given namespace and chunk name.
368
-     *
369
-     * @param string $namespace
370
-     * @param string $chunk_name
371
-     * @return string
372
-     */
373
-    public function getJsUrl($namespace, $chunk_name)
374
-    {
375
-        return $this->getAssetUrl($namespace, $chunk_name, self::ASSET_TYPE_JS);
376
-    }
377
-
378
-
379
-    /**
380
-     * Return the url to a css file for the given namespace and chunk name.
381
-     *
382
-     * @param string $namespace
383
-     * @param string $chunk_name
384
-     * @return string
385
-     */
386
-    public function getCssUrl($namespace, $chunk_name)
387
-    {
388
-        return $this->getAssetUrl($namespace, $chunk_name, self::ASSET_TYPE_CSS);
389
-    }
390
-
391
-
392
-    /**
393
-     * Used to register a js/css manifest file with the registered_manifest_files property.
394
-     *
395
-     * @param string $namespace     Provided to associate the manifest file with a specific namespace.
396
-     * @param string $url_base      The url base for the manifest file location.
397
-     * @param string $manifest_file The absolute path to the manifest file.
398
-     * @throws InvalidArgumentException
399
-     * @throws InvalidFilePathException
400
-     * @since 4.9.59.p
401
-     */
402
-    public function registerManifestFile($namespace, $url_base, $manifest_file)
403
-    {
404
-        if (isset($this->manifest_data[$namespace])) {
405
-            throw new InvalidArgumentException(
406
-                sprintf(
407
-                    esc_html__(
408
-                        'The namespace for this manifest file has already been registered, choose a namespace other than %s',
409
-                        'event_espresso'
410
-                    ),
411
-                    $namespace
412
-                )
413
-            );
414
-        }
415
-        if (filter_var($url_base, FILTER_VALIDATE_URL) === false) {
416
-            if (is_admin()) {
417
-                EE_Error::add_error(
418
-                    sprintf(
419
-                        esc_html__(
420
-                            'The url given for %1$s assets is invalid.  The url provided was: "%2$s". This usually happens when another plugin or theme on a site is using the "%3$s" filter or has an invalid url set for the "%4$s" constant',
421
-                            'event_espresso'
422
-                        ),
423
-                        'Event Espresso',
424
-                        $url_base,
425
-                        'plugins_url',
426
-                        'WP_PLUGIN_URL'
427
-                    ),
428
-                    __FILE__,
429
-                    __FUNCTION__,
430
-                    __LINE__
431
-                );
432
-            }
433
-            return;
434
-        }
435
-        $this->manifest_data[$namespace] = $this->decodeManifestFile($manifest_file);
436
-        if (! isset($this->manifest_data[$namespace]['url_base'])) {
437
-            $this->manifest_data[$namespace]['url_base'] = trailingslashit($url_base);
438
-        }
439
-    }
440
-
441
-
442
-
443
-    /**
444
-     * Decodes json from the provided manifest file.
445
-     *
446
-     * @since 4.9.59.p
447
-     * @param string $manifest_file Path to manifest file.
448
-     * @return array
449
-     * @throws InvalidFilePathException
450
-     */
451
-    private function decodeManifestFile($manifest_file)
452
-    {
453
-        if (! file_exists($manifest_file)) {
454
-            throw new InvalidFilePathException($manifest_file);
455
-        }
456
-        return json_decode(file_get_contents($manifest_file), true);
457
-    }
458
-
459
-
460
-
461
-    /**
462
-     * Verifies whether the given data exists already on the jsdata array.
463
-     * Overriding data is not allowed.
464
-     *
465
-     * @param string $key Index for data.
466
-     * @return bool        If valid then return true.
467
-     * @throws InvalidArgumentException if data already exists.
468
-     */
469
-    protected function verifyDataNotExisting($key)
470
-    {
471
-        if (isset($this->jsdata[$key])) {
472
-            if (is_array($this->jsdata[$key])) {
473
-                throw new InvalidArgumentException(
474
-                    sprintf(
475
-                        __(
476
-                            'The value for %1$s already exists in the Registry::eejs object.
266
+						'event_espresso'
267
+					),
268
+					$key,
269
+					__METHOD__
270
+				)
271
+			);
272
+		}
273
+		$this->jsdata[$key][] = $value;
274
+	}
275
+
276
+
277
+
278
+	/**
279
+	 * Used to set content used by javascript for a template.
280
+	 * Note: Overrides of existing registered templates are not allowed.
281
+	 *
282
+	 * @param string $template_reference
283
+	 * @param string $template_content
284
+	 * @throws InvalidArgumentException
285
+	 */
286
+	public function addTemplate($template_reference, $template_content)
287
+	{
288
+		if (! isset($this->jsdata['templates'])) {
289
+			$this->jsdata['templates'] = array();
290
+		}
291
+		//no overrides allowed.
292
+		if (isset($this->jsdata['templates'][$template_reference])) {
293
+			throw new invalidArgumentException(
294
+				sprintf(
295
+					__(
296
+						'The %1$s key already exists for the templates array in the js data array.  No overrides are allowed.',
297
+						'event_espresso'
298
+					),
299
+					$template_reference
300
+				)
301
+			);
302
+		}
303
+		$this->jsdata['templates'][$template_reference] = $template_content;
304
+	}
305
+
306
+
307
+
308
+	/**
309
+	 * Retrieve the template content already registered for the given reference.
310
+	 *
311
+	 * @param string $template_reference
312
+	 * @return string
313
+	 */
314
+	public function getTemplate($template_reference)
315
+	{
316
+		return isset($this->jsdata['templates'], $this->jsdata['templates'][$template_reference])
317
+			? $this->jsdata['templates'][$template_reference]
318
+			: '';
319
+	}
320
+
321
+
322
+
323
+	/**
324
+	 * Retrieve registered data.
325
+	 *
326
+	 * @param string $key Name of key to attach data to.
327
+	 * @return mixed                If there is no for the given key, then false is returned.
328
+	 */
329
+	public function getData($key)
330
+	{
331
+		return isset($this->jsdata[$key])
332
+			? $this->jsdata[$key]
333
+			: false;
334
+	}
335
+
336
+
337
+	/**
338
+	 * Get the actual asset path for asset manifests.
339
+	 * If there is no asset path found for the given $chunk_name, then the $chunk_name is returned.
340
+	 * @param string $namespace  The namespace associated with the manifest file hosting the map of chunk_name to actual
341
+	 *                           asset file location.
342
+	 * @param string $chunk_name
343
+	 * @param string $asset_type
344
+	 * @return string
345
+	 * @since 4.9.59.p
346
+	 */
347
+	public function getAssetUrl($namespace, $chunk_name, $asset_type)
348
+	{
349
+		$url = isset(
350
+			$this->manifest_data[$namespace][$chunk_name][$asset_type],
351
+			$this->manifest_data[$namespace]['url_base']
352
+		)
353
+			? $this->manifest_data[$namespace]['url_base']
354
+			  . $this->manifest_data[$namespace][$chunk_name][$asset_type]
355
+			: $chunk_name;
356
+		return apply_filters(
357
+			'FHEE__EventEspresso_core_services_assets_Registry__getAssetUrl',
358
+			$url,
359
+			$namespace,
360
+			$chunk_name,
361
+			$asset_type
362
+		);
363
+	}
364
+
365
+
366
+	/**
367
+	 * Return the url to a js file for the given namespace and chunk name.
368
+	 *
369
+	 * @param string $namespace
370
+	 * @param string $chunk_name
371
+	 * @return string
372
+	 */
373
+	public function getJsUrl($namespace, $chunk_name)
374
+	{
375
+		return $this->getAssetUrl($namespace, $chunk_name, self::ASSET_TYPE_JS);
376
+	}
377
+
378
+
379
+	/**
380
+	 * Return the url to a css file for the given namespace and chunk name.
381
+	 *
382
+	 * @param string $namespace
383
+	 * @param string $chunk_name
384
+	 * @return string
385
+	 */
386
+	public function getCssUrl($namespace, $chunk_name)
387
+	{
388
+		return $this->getAssetUrl($namespace, $chunk_name, self::ASSET_TYPE_CSS);
389
+	}
390
+
391
+
392
+	/**
393
+	 * Used to register a js/css manifest file with the registered_manifest_files property.
394
+	 *
395
+	 * @param string $namespace     Provided to associate the manifest file with a specific namespace.
396
+	 * @param string $url_base      The url base for the manifest file location.
397
+	 * @param string $manifest_file The absolute path to the manifest file.
398
+	 * @throws InvalidArgumentException
399
+	 * @throws InvalidFilePathException
400
+	 * @since 4.9.59.p
401
+	 */
402
+	public function registerManifestFile($namespace, $url_base, $manifest_file)
403
+	{
404
+		if (isset($this->manifest_data[$namespace])) {
405
+			throw new InvalidArgumentException(
406
+				sprintf(
407
+					esc_html__(
408
+						'The namespace for this manifest file has already been registered, choose a namespace other than %s',
409
+						'event_espresso'
410
+					),
411
+					$namespace
412
+				)
413
+			);
414
+		}
415
+		if (filter_var($url_base, FILTER_VALIDATE_URL) === false) {
416
+			if (is_admin()) {
417
+				EE_Error::add_error(
418
+					sprintf(
419
+						esc_html__(
420
+							'The url given for %1$s assets is invalid.  The url provided was: "%2$s". This usually happens when another plugin or theme on a site is using the "%3$s" filter or has an invalid url set for the "%4$s" constant',
421
+							'event_espresso'
422
+						),
423
+						'Event Espresso',
424
+						$url_base,
425
+						'plugins_url',
426
+						'WP_PLUGIN_URL'
427
+					),
428
+					__FILE__,
429
+					__FUNCTION__,
430
+					__LINE__
431
+				);
432
+			}
433
+			return;
434
+		}
435
+		$this->manifest_data[$namespace] = $this->decodeManifestFile($manifest_file);
436
+		if (! isset($this->manifest_data[$namespace]['url_base'])) {
437
+			$this->manifest_data[$namespace]['url_base'] = trailingslashit($url_base);
438
+		}
439
+	}
440
+
441
+
442
+
443
+	/**
444
+	 * Decodes json from the provided manifest file.
445
+	 *
446
+	 * @since 4.9.59.p
447
+	 * @param string $manifest_file Path to manifest file.
448
+	 * @return array
449
+	 * @throws InvalidFilePathException
450
+	 */
451
+	private function decodeManifestFile($manifest_file)
452
+	{
453
+		if (! file_exists($manifest_file)) {
454
+			throw new InvalidFilePathException($manifest_file);
455
+		}
456
+		return json_decode(file_get_contents($manifest_file), true);
457
+	}
458
+
459
+
460
+
461
+	/**
462
+	 * Verifies whether the given data exists already on the jsdata array.
463
+	 * Overriding data is not allowed.
464
+	 *
465
+	 * @param string $key Index for data.
466
+	 * @return bool        If valid then return true.
467
+	 * @throws InvalidArgumentException if data already exists.
468
+	 */
469
+	protected function verifyDataNotExisting($key)
470
+	{
471
+		if (isset($this->jsdata[$key])) {
472
+			if (is_array($this->jsdata[$key])) {
473
+				throw new InvalidArgumentException(
474
+					sprintf(
475
+						__(
476
+							'The value for %1$s already exists in the Registry::eejs object.
477 477
                             Overrides are not allowed. Since the value of this data is an array, you may want to use the
478 478
                             %2$s method to push your value to the array.',
479
-                            'event_espresso'
480
-                        ),
481
-                        $key,
482
-                        'pushData()'
483
-                    )
484
-                );
485
-            }
486
-            throw new InvalidArgumentException(
487
-                sprintf(
488
-                    __(
489
-                        'The value for %1$s already exists in the Registry::eejs object. Overrides are not
479
+							'event_espresso'
480
+						),
481
+						$key,
482
+						'pushData()'
483
+					)
484
+				);
485
+			}
486
+			throw new InvalidArgumentException(
487
+				sprintf(
488
+					__(
489
+						'The value for %1$s already exists in the Registry::eejs object. Overrides are not
490 490
                         allowed.  Consider attaching your value to a different key',
491
-                        'event_espresso'
492
-                    ),
493
-                    $key
494
-                )
495
-            );
496
-        }
497
-        return true;
498
-    }
499
-
500
-
501
-
502
-    /**
503
-     * registers core default stylesheets
504
-     */
505
-    private function loadCoreCss()
506
-    {
507
-        if ($this->template_config->enable_default_style) {
508
-            $default_stylesheet_path = is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
509
-                ? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
510
-                : EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css';
511
-            wp_register_style(
512
-                'espresso_default',
513
-                $default_stylesheet_path,
514
-                array('dashicons'),
515
-                EVENT_ESPRESSO_VERSION
516
-            );
517
-            //Load custom style sheet if available
518
-            if ($this->template_config->custom_style_sheet !== null) {
519
-                wp_register_style(
520
-                    'espresso_custom_css',
521
-                    EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
522
-                    array('espresso_default'),
523
-                    EVENT_ESPRESSO_VERSION
524
-                );
525
-            }
526
-        }
527
-    }
528
-
529
-
530
-
531
-    /**
532
-     * registers core default javascript
533
-     */
534
-    private function loadCoreJs()
535
-    {
536
-        // load core js
537
-        wp_register_script(
538
-            'espresso_core',
539
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
540
-            array('jquery'),
541
-            EVENT_ESPRESSO_VERSION,
542
-            true
543
-        );
544
-    }
545
-
546
-
547
-
548
-    /**
549
-     * registers jQuery Validate for form validation
550
-     */
551
-    private function loadJqueryValidate()
552
-    {
553
-        // register jQuery Validate and additional methods
554
-        wp_register_script(
555
-            'jquery-validate',
556
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
557
-            array('jquery'),
558
-            '1.15.0',
559
-            true
560
-        );
561
-        wp_register_script(
562
-            'jquery-validate-extra-methods',
563
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
564
-            array('jquery', 'jquery-validate'),
565
-            '1.15.0',
566
-            true
567
-        );
568
-    }
569
-
570
-
571
-
572
-    /**
573
-     * registers accounting.js for performing client-side calculations
574
-     */
575
-    private function loadAccountingJs()
576
-    {
577
-        //accounting.js library
578
-        // @link http://josscrowcroft.github.io/accounting.js/
579
-        wp_register_script(
580
-            'ee-accounting-core',
581
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
582
-            array('underscore'),
583
-            '0.3.2',
584
-            true
585
-        );
586
-        wp_register_script(
587
-            'ee-accounting',
588
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
589
-            array('ee-accounting-core'),
590
-            EVENT_ESPRESSO_VERSION,
591
-            true
592
-        );
593
-    }
594
-
595
-
596
-
597
-    /**
598
-     * registers accounting.js for performing client-side calculations
599
-     */
600
-    private function localizeAccountingJs()
601
-    {
602
-        wp_localize_script(
603
-            'ee-accounting',
604
-            'EE_ACCOUNTING_CFG',
605
-            array(
606
-                'currency' => array(
607
-                    'symbol'    => $this->currency_config->sign,
608
-                    'format'    => array(
609
-                        'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
610
-                        'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
611
-                        'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
612
-                    ),
613
-                    'decimal'   => $this->currency_config->dec_mrk,
614
-                    'thousand'  => $this->currency_config->thsnds,
615
-                    'precision' => $this->currency_config->dec_plc,
616
-                ),
617
-                'number'   => array(
618
-                    'precision' => $this->currency_config->dec_plc,
619
-                    'thousand'  => $this->currency_config->thsnds,
620
-                    'decimal'   => $this->currency_config->dec_mrk,
621
-                ),
622
-            )
623
-        );
624
-        $this->addRegisteredScriptHandlesWithData('ee-accounting');
625
-    }
626
-
627
-
628
-
629
-    /**
630
-     * registers assets for cleaning your ears
631
-     */
632
-    private function loadQtipJs()
633
-    {
634
-        // qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
635
-        // can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
636
-        if (apply_filters('FHEE_load_qtip', false)) {
637
-            EEH_Qtip_Loader::instance()->register_and_enqueue();
638
-        }
639
-    }
640
-
641
-
642
-    /**
643
-     * This is used to set registered script handles that have data.
644
-     * @param string $script_handle
645
-     */
646
-    private function addRegisteredScriptHandlesWithData($script_handle)
647
-    {
648
-        $this->script_handles_with_data[$script_handle] = $script_handle;
649
-    }
650
-
651
-
652
-    /**i
491
+						'event_espresso'
492
+					),
493
+					$key
494
+				)
495
+			);
496
+		}
497
+		return true;
498
+	}
499
+
500
+
501
+
502
+	/**
503
+	 * registers core default stylesheets
504
+	 */
505
+	private function loadCoreCss()
506
+	{
507
+		if ($this->template_config->enable_default_style) {
508
+			$default_stylesheet_path = is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
509
+				? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
510
+				: EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css';
511
+			wp_register_style(
512
+				'espresso_default',
513
+				$default_stylesheet_path,
514
+				array('dashicons'),
515
+				EVENT_ESPRESSO_VERSION
516
+			);
517
+			//Load custom style sheet if available
518
+			if ($this->template_config->custom_style_sheet !== null) {
519
+				wp_register_style(
520
+					'espresso_custom_css',
521
+					EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
522
+					array('espresso_default'),
523
+					EVENT_ESPRESSO_VERSION
524
+				);
525
+			}
526
+		}
527
+	}
528
+
529
+
530
+
531
+	/**
532
+	 * registers core default javascript
533
+	 */
534
+	private function loadCoreJs()
535
+	{
536
+		// load core js
537
+		wp_register_script(
538
+			'espresso_core',
539
+			EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
540
+			array('jquery'),
541
+			EVENT_ESPRESSO_VERSION,
542
+			true
543
+		);
544
+	}
545
+
546
+
547
+
548
+	/**
549
+	 * registers jQuery Validate for form validation
550
+	 */
551
+	private function loadJqueryValidate()
552
+	{
553
+		// register jQuery Validate and additional methods
554
+		wp_register_script(
555
+			'jquery-validate',
556
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
557
+			array('jquery'),
558
+			'1.15.0',
559
+			true
560
+		);
561
+		wp_register_script(
562
+			'jquery-validate-extra-methods',
563
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
564
+			array('jquery', 'jquery-validate'),
565
+			'1.15.0',
566
+			true
567
+		);
568
+	}
569
+
570
+
571
+
572
+	/**
573
+	 * registers accounting.js for performing client-side calculations
574
+	 */
575
+	private function loadAccountingJs()
576
+	{
577
+		//accounting.js library
578
+		// @link http://josscrowcroft.github.io/accounting.js/
579
+		wp_register_script(
580
+			'ee-accounting-core',
581
+			EE_THIRD_PARTY_URL . 'accounting/accounting.js',
582
+			array('underscore'),
583
+			'0.3.2',
584
+			true
585
+		);
586
+		wp_register_script(
587
+			'ee-accounting',
588
+			EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
589
+			array('ee-accounting-core'),
590
+			EVENT_ESPRESSO_VERSION,
591
+			true
592
+		);
593
+	}
594
+
595
+
596
+
597
+	/**
598
+	 * registers accounting.js for performing client-side calculations
599
+	 */
600
+	private function localizeAccountingJs()
601
+	{
602
+		wp_localize_script(
603
+			'ee-accounting',
604
+			'EE_ACCOUNTING_CFG',
605
+			array(
606
+				'currency' => array(
607
+					'symbol'    => $this->currency_config->sign,
608
+					'format'    => array(
609
+						'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
610
+						'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
611
+						'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
612
+					),
613
+					'decimal'   => $this->currency_config->dec_mrk,
614
+					'thousand'  => $this->currency_config->thsnds,
615
+					'precision' => $this->currency_config->dec_plc,
616
+				),
617
+				'number'   => array(
618
+					'precision' => $this->currency_config->dec_plc,
619
+					'thousand'  => $this->currency_config->thsnds,
620
+					'decimal'   => $this->currency_config->dec_mrk,
621
+				),
622
+			)
623
+		);
624
+		$this->addRegisteredScriptHandlesWithData('ee-accounting');
625
+	}
626
+
627
+
628
+
629
+	/**
630
+	 * registers assets for cleaning your ears
631
+	 */
632
+	private function loadQtipJs()
633
+	{
634
+		// qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
635
+		// can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
636
+		if (apply_filters('FHEE_load_qtip', false)) {
637
+			EEH_Qtip_Loader::instance()->register_and_enqueue();
638
+		}
639
+	}
640
+
641
+
642
+	/**
643
+	 * This is used to set registered script handles that have data.
644
+	 * @param string $script_handle
645
+	 */
646
+	private function addRegisteredScriptHandlesWithData($script_handle)
647
+	{
648
+		$this->script_handles_with_data[$script_handle] = $script_handle;
649
+	}
650
+
651
+
652
+	/**i
653 653
      * Checks WP_Scripts for all of each script handle registered internally as having data and unsets from the
654 654
      * Dependency stored in WP_Scripts if its set.
655 655
      */
656
-    private function removeAlreadyRegisteredDataForScriptHandles()
657
-    {
658
-        if (empty($this->script_handles_with_data)) {
659
-            return;
660
-        }
661
-        foreach ($this->script_handles_with_data as $script_handle) {
662
-            $this->removeAlreadyRegisteredDataForScriptHandle($script_handle);
663
-        }
664
-    }
665
-
666
-
667
-    /**
668
-     * Removes any data dependency registered in WP_Scripts if its set.
669
-     * @param string $script_handle
670
-     */
671
-    private function removeAlreadyRegisteredDataForScriptHandle($script_handle)
672
-    {
673
-        if (isset($this->script_handles_with_data[$script_handle])) {
674
-            global $wp_scripts;
675
-            $unset_handle = false;
676
-            if ($wp_scripts->get_data($script_handle, 'data')) {
677
-                unset($wp_scripts->registered[$script_handle]->extra['data']);
678
-                $unset_handle = true;
679
-            }
680
-            //deal with inline_scripts
681
-            if ($wp_scripts->get_data($script_handle, 'before')) {
682
-                unset($wp_scripts->registered[$script_handle]->extra['before']);
683
-                $unset_handle = true;
684
-            }
685
-            if ($wp_scripts->get_data($script_handle, 'after')) {
686
-                unset($wp_scripts->registered[$script_handle]->extra['after']);
687
-            }
688
-            if ($unset_handle) {
689
-                unset($this->script_handles_with_data[$script_handle]);
690
-            }
691
-        }
692
-    }
693
-
694
-
695
-    /**
696
-     * Registers assets that are used in the WordPress admin.
697
-     */
698
-    private function registerAdminAssets()
699
-    {
700
-        wp_register_script(
701
-            'ee-wp-plugins-page',
702
-            $this->getJsUrl(self::ASSET_NAMESPACE, 'wp-plugins-page'),
703
-            array(
704
-                'jquery',
705
-                'ee-vendor-react'
706
-            ),
707
-            null,
708
-            true
709
-        );
710
-        wp_register_style(
711
-            'ee-wp-plugins-page',
712
-            $this->getCssUrl(self::ASSET_NAMESPACE, 'wp-plugins-page'),
713
-            array(),
714
-            null
715
-        );
716
-        $this->registerTranslationsForHandles(array('ee-wp-plugins-page'));
717
-    }
718
-
719
-
720
-    /**
721
-     * All handles that are registered via the registry that might have translations have their translations registered
722
-     *
723
-     * @param array $handles_to_register
724
-     */
725
-    private function registerTranslationsForHandles(array $handles_to_register)
726
-    {
727
-        foreach($handles_to_register as $handle) {
728
-            $this->i18n_registry->registerScriptI18n($handle);
729
-        }
730
-    }
656
+	private function removeAlreadyRegisteredDataForScriptHandles()
657
+	{
658
+		if (empty($this->script_handles_with_data)) {
659
+			return;
660
+		}
661
+		foreach ($this->script_handles_with_data as $script_handle) {
662
+			$this->removeAlreadyRegisteredDataForScriptHandle($script_handle);
663
+		}
664
+	}
665
+
666
+
667
+	/**
668
+	 * Removes any data dependency registered in WP_Scripts if its set.
669
+	 * @param string $script_handle
670
+	 */
671
+	private function removeAlreadyRegisteredDataForScriptHandle($script_handle)
672
+	{
673
+		if (isset($this->script_handles_with_data[$script_handle])) {
674
+			global $wp_scripts;
675
+			$unset_handle = false;
676
+			if ($wp_scripts->get_data($script_handle, 'data')) {
677
+				unset($wp_scripts->registered[$script_handle]->extra['data']);
678
+				$unset_handle = true;
679
+			}
680
+			//deal with inline_scripts
681
+			if ($wp_scripts->get_data($script_handle, 'before')) {
682
+				unset($wp_scripts->registered[$script_handle]->extra['before']);
683
+				$unset_handle = true;
684
+			}
685
+			if ($wp_scripts->get_data($script_handle, 'after')) {
686
+				unset($wp_scripts->registered[$script_handle]->extra['after']);
687
+			}
688
+			if ($unset_handle) {
689
+				unset($this->script_handles_with_data[$script_handle]);
690
+			}
691
+		}
692
+	}
693
+
694
+
695
+	/**
696
+	 * Registers assets that are used in the WordPress admin.
697
+	 */
698
+	private function registerAdminAssets()
699
+	{
700
+		wp_register_script(
701
+			'ee-wp-plugins-page',
702
+			$this->getJsUrl(self::ASSET_NAMESPACE, 'wp-plugins-page'),
703
+			array(
704
+				'jquery',
705
+				'ee-vendor-react'
706
+			),
707
+			null,
708
+			true
709
+		);
710
+		wp_register_style(
711
+			'ee-wp-plugins-page',
712
+			$this->getCssUrl(self::ASSET_NAMESPACE, 'wp-plugins-page'),
713
+			array(),
714
+			null
715
+		);
716
+		$this->registerTranslationsForHandles(array('ee-wp-plugins-page'));
717
+	}
718
+
719
+
720
+	/**
721
+	 * All handles that are registered via the registry that might have translations have their translations registered
722
+	 *
723
+	 * @param array $handles_to_register
724
+	 */
725
+	private function registerTranslationsForHandles(array $handles_to_register)
726
+	{
727
+		foreach($handles_to_register as $handle) {
728
+			$this->i18n_registry->registerScriptI18n($handle);
729
+		}
730
+	}
731 731
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
         $this->registerManifestFile(
115 115
             self::ASSET_NAMESPACE,
116 116
             $this->domain->distributionAssetsUrl(),
117
-            $this->domain->distributionAssetsPath() . 'build-manifest.json'
117
+            $this->domain->distributionAssetsPath().'build-manifest.json'
118 118
         );
119 119
         add_action('wp_enqueue_scripts', array($this, 'scripts'), 1);
120 120
         add_action('admin_enqueue_scripts', array($this, 'scripts'), 1);
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
             //js.api
172 172
             wp_register_script(
173 173
                 'eejs-api',
174
-                EE_LIBRARIES_URL . 'rest_api/assets/js/eejs-api.min.js',
174
+                EE_LIBRARIES_URL.'rest_api/assets/js/eejs-api.min.js',
175 175
                 array('underscore', 'eejs-core'),
176 176
                 EVENT_ESPRESSO_VERSION,
177 177
                 true
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
                 'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName()
183 183
             );
184 184
         }
185
-        if (! is_admin()) {
185
+        if ( ! is_admin()) {
186 186
             $this->loadCoreCss();
187 187
         }
188 188
         $this->registerTranslationsForHandles(array('eejs-core'));
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
         $this->removeAlreadyRegisteredDataForScriptHandles();
207 207
         wp_add_inline_script(
208 208
             'eejs-core',
209
-            'var eejsdata=' . wp_json_encode(array('data' => $this->jsdata)),
209
+            'var eejsdata='.wp_json_encode(array('data' => $this->jsdata)),
210 210
             'before'
211 211
         );
212 212
         wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings);
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
      */
286 286
     public function addTemplate($template_reference, $template_content)
287 287
     {
288
-        if (! isset($this->jsdata['templates'])) {
288
+        if ( ! isset($this->jsdata['templates'])) {
289 289
             $this->jsdata['templates'] = array();
290 290
         }
291 291
         //no overrides allowed.
@@ -433,7 +433,7 @@  discard block
 block discarded – undo
433 433
             return;
434 434
         }
435 435
         $this->manifest_data[$namespace] = $this->decodeManifestFile($manifest_file);
436
-        if (! isset($this->manifest_data[$namespace]['url_base'])) {
436
+        if ( ! isset($this->manifest_data[$namespace]['url_base'])) {
437 437
             $this->manifest_data[$namespace]['url_base'] = trailingslashit($url_base);
438 438
         }
439 439
     }
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
      */
451 451
     private function decodeManifestFile($manifest_file)
452 452
     {
453
-        if (! file_exists($manifest_file)) {
453
+        if ( ! file_exists($manifest_file)) {
454 454
             throw new InvalidFilePathException($manifest_file);
455 455
         }
456 456
         return json_decode(file_get_contents($manifest_file), true);
@@ -505,9 +505,9 @@  discard block
 block discarded – undo
505 505
     private function loadCoreCss()
506 506
     {
507 507
         if ($this->template_config->enable_default_style) {
508
-            $default_stylesheet_path = is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
508
+            $default_stylesheet_path = is_readable(EVENT_ESPRESSO_UPLOAD_DIR.'css/style.css')
509 509
                 ? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
510
-                : EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css';
510
+                : EE_GLOBAL_ASSETS_URL.'css/espresso_default.css';
511 511
             wp_register_style(
512 512
                 'espresso_default',
513 513
                 $default_stylesheet_path,
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
             if ($this->template_config->custom_style_sheet !== null) {
519 519
                 wp_register_style(
520 520
                     'espresso_custom_css',
521
-                    EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
521
+                    EVENT_ESPRESSO_UPLOAD_URL.'css/'.$this->template_config->custom_style_sheet,
522 522
                     array('espresso_default'),
523 523
                     EVENT_ESPRESSO_VERSION
524 524
                 );
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
         // load core js
537 537
         wp_register_script(
538 538
             'espresso_core',
539
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
539
+            EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js',
540 540
             array('jquery'),
541 541
             EVENT_ESPRESSO_VERSION,
542 542
             true
@@ -553,14 +553,14 @@  discard block
 block discarded – undo
553 553
         // register jQuery Validate and additional methods
554 554
         wp_register_script(
555 555
             'jquery-validate',
556
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
556
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.validate.min.js',
557 557
             array('jquery'),
558 558
             '1.15.0',
559 559
             true
560 560
         );
561 561
         wp_register_script(
562 562
             'jquery-validate-extra-methods',
563
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
563
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.validate.additional-methods.min.js',
564 564
             array('jquery', 'jquery-validate'),
565 565
             '1.15.0',
566 566
             true
@@ -578,14 +578,14 @@  discard block
 block discarded – undo
578 578
         // @link http://josscrowcroft.github.io/accounting.js/
579 579
         wp_register_script(
580 580
             'ee-accounting-core',
581
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
581
+            EE_THIRD_PARTY_URL.'accounting/accounting.js',
582 582
             array('underscore'),
583 583
             '0.3.2',
584 584
             true
585 585
         );
586 586
         wp_register_script(
587 587
             'ee-accounting',
588
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
588
+            EE_GLOBAL_ASSETS_URL.'scripts/ee-accounting-config.js',
589 589
             array('ee-accounting-core'),
590 590
             EVENT_ESPRESSO_VERSION,
591 591
             true
@@ -724,7 +724,7 @@  discard block
 block discarded – undo
724 724
      */
725 725
     private function registerTranslationsForHandles(array $handles_to_register)
726 726
     {
727
-        foreach($handles_to_register as $handle) {
727
+        foreach ($handles_to_register as $handle) {
728 728
             $this->i18n_registry->registerScriptI18n($handle);
729 729
         }
730 730
     }
Please login to merge, or discard this patch.
modules/core_rest_api/EED_Core_Rest_Api.module.php 2 patches
Indentation   +1272 added lines, -1272 removed lines patch added patch discarded remove patch
@@ -26,1279 +26,1279 @@
 block discarded – undo
26 26
 class EED_Core_Rest_Api extends \EED_Module
27 27
 {
28 28
 
29
-    const ee_api_namespace           = Domain::API_NAMESPACE;
29
+	const ee_api_namespace           = Domain::API_NAMESPACE;
30 30
 
31
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
32
-
33
-    const saved_routes_option_names  = 'ee_core_routes';
34
-
35
-    /**
36
-     * string used in _links response bodies to make them globally unique.
37
-     *
38
-     * @see http://v2.wp-api.org/extending/linking/
39
-     */
40
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
41
-
42
-    /**
43
-     * @var CalculatedModelFields
44
-     */
45
-    protected static $_field_calculator;
46
-
47
-
48
-
49
-    /**
50
-     * @return EED_Core_Rest_Api|EED_Module
51
-     */
52
-    public static function instance()
53
-    {
54
-        self::$_field_calculator = new CalculatedModelFields();
55
-        return parent::get_instance(__CLASS__);
56
-    }
57
-
58
-
59
-
60
-    /**
61
-     *    set_hooks - for hooking into EE Core, other modules, etc
62
-     *
63
-     * @access    public
64
-     * @return    void
65
-     */
66
-    public static function set_hooks()
67
-    {
68
-        self::set_hooks_both();
69
-    }
70
-
71
-
72
-
73
-    /**
74
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
75
-     *
76
-     * @access    public
77
-     * @return    void
78
-     */
79
-    public static function set_hooks_admin()
80
-    {
81
-        self::set_hooks_both();
82
-    }
83
-
84
-
85
-
86
-    public static function set_hooks_both()
87
-    {
88
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
89
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
90
-        add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
91
-        add_filter('rest_index',
92
-            array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
93
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
94
-    }
95
-
96
-
97
-
98
-    /**
99
-     * sets up hooks which only need to be included as part of REST API requests;
100
-     * other requests like to the frontend or admin etc don't need them
101
-     *
102
-     * @throws \EE_Error
103
-     */
104
-    public static function set_hooks_rest_api()
105
-    {
106
-        //set hooks which account for changes made to the API
107
-        EED_Core_Rest_Api::_set_hooks_for_changes();
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * public wrapper of _set_hooks_for_changes.
114
-     * Loads all the hooks which make requests to old versions of the API
115
-     * appear the same as they always did
116
-     *
117
-     * @throws EE_Error
118
-     */
119
-    public static function set_hooks_for_changes()
120
-    {
121
-        self::_set_hooks_for_changes();
122
-    }
123
-
124
-
125
-
126
-    /**
127
-     * Loads all the hooks which make requests to old versions of the API
128
-     * appear the same as they always did
129
-     *
130
-     * @throws EE_Error
131
-     */
132
-    protected static function _set_hooks_for_changes()
133
-    {
134
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
135
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
136
-            //ignore the base parent class
137
-            //and legacy named classes
138
-            if ($classname_in_namespace === 'ChangesInBase'
139
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
140
-            ) {
141
-                continue;
142
-            }
143
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
144
-            if (class_exists($full_classname)) {
145
-                $instance_of_class = new $full_classname;
146
-                if ($instance_of_class instanceof ChangesInBase) {
147
-                    $instance_of_class->setHooks();
148
-                }
149
-            }
150
-        }
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
157
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
158
-     *
159
-     * @throws \EE_Error
160
-     */
161
-    public static function register_routes()
162
-    {
163
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
164
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
165
-                /**
166
-                 * @var array $data_for_multiple_endpoints numerically indexed array
167
-                 *                                         but can also contain route options like {
168
-                 * @type array    $schema                      {
169
-                 * @type callable $schema_callback
170
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
171
-                 * WP_REST_Request of course
172
-                 * }
173
-                 * }
174
-                 */
175
-                //when registering routes, register all the endpoints' data at the same time
176
-                $multiple_endpoint_args = array();
177
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
178
-                    /**
179
-                     * @var array     $data_for_single_endpoint {
180
-                     * @type callable $callback
181
-                     * @type string methods
182
-                     * @type array args
183
-                     * @type array _links
184
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
185
-                     * WP_REST_Request of course
186
-                     * }
187
-                     */
188
-                    //skip route options
189
-                    if (! is_numeric($endpoint_key)) {
190
-                        continue;
191
-                    }
192
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193
-                        throw new EE_Error(
194
-                            esc_html__(
195
-                                // @codingStandardsIgnoreStart
196
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
197
-                                // @codingStandardsIgnoreEnd
198
-                                'event_espresso')
199
-                        );
200
-                    }
201
-                    $callback = $data_for_single_endpoint['callback'];
202
-                    $single_endpoint_args = array(
203
-                        'methods' => $data_for_single_endpoint['methods'],
204
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
-                            : array(),
206
-                    );
207
-                    if (isset($data_for_single_endpoint['_links'])) {
208
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
-                    }
210
-                    if (isset($data_for_single_endpoint['callback_args'])) {
211
-                        $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
213
-                            $callback,
214
-                            $callback_args
215
-                        ) {
216
-                            array_unshift($callback_args, $request);
217
-                            return call_user_func_array(
218
-                                $callback,
219
-                                $callback_args
220
-                            );
221
-                        };
222
-                    } else {
223
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
-                    }
225
-                    $multiple_endpoint_args[] = $single_endpoint_args;
226
-                }
227
-                if (isset($data_for_multiple_endpoints['schema'])) {
228
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
229
-                    $schema_callback = $schema_route_data['schema_callback'];
230
-                    $callback_args = $schema_route_data['callback_args'];
231
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
232
-                        return call_user_func_array(
233
-                            $schema_callback,
234
-                            $callback_args
235
-                        );
236
-                    };
237
-                }
238
-                register_rest_route(
239
-                    $namespace,
240
-                    $relative_route,
241
-                    $multiple_endpoint_args
242
-                );
243
-            }
244
-        }
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     * Checks if there was a version change or something that merits invalidating the cached
251
-     * route data. If so, invalidates the cached route data so that it gets refreshed
252
-     * next time the WP API is used
253
-     */
254
-    public static function invalidate_cached_route_data_on_version_change()
255
-    {
256
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
257
-            EED_Core_Rest_Api::invalidate_cached_route_data();
258
-        }
259
-        foreach (EE_Registry::instance()->addons as $addon) {
260
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
261
-                EED_Core_Rest_Api::invalidate_cached_route_data();
262
-            }
263
-        }
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * Removes the cached route data so it will get refreshed next time the WP API is used
270
-     */
271
-    public static function invalidate_cached_route_data()
272
-    {
273
-        //delete the saved EE REST API routes
274
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
276
-        }
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * Gets the EE route data
283
-     *
284
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
285
-     * @throws \EE_Error
286
-     * @type string|array $callback
287
-     * @type string       $methods
288
-     * @type boolean      $hidden_endpoint
289
-     * }
290
-     */
291
-    public static function get_ee_route_data()
292
-    {
293
-        $ee_routes = array();
294
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
295
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
296
-                $version,
297
-                $hidden_endpoints
298
-            );
299
-        }
300
-        return $ee_routes;
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     * Gets the EE route data from the wp options if it exists already,
307
-     * otherwise re-generates it and saves it to the option
308
-     *
309
-     * @param string  $version
310
-     * @param boolean $hidden_endpoints
311
-     * @return array
312
-     * @throws \EE_Error
313
-     */
314
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315
-    {
316
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319
-        }
320
-        return $ee_routes;
321
-    }
322
-
323
-
324
-
325
-    /**
326
-     * Saves the EE REST API route data to a wp option and returns it
327
-     *
328
-     * @param string  $version
329
-     * @param boolean $hidden_endpoints
330
-     * @return mixed|null
331
-     * @throws \EE_Error
332
-     */
333
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
334
-    {
335
-        $instance = self::instance();
336
-        $routes = apply_filters(
337
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
338
-            array_replace_recursive(
339
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
340
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
341
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
342
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343
-            )
344
-        );
345
-        $option_name = self::saved_routes_option_names . $version;
346
-        if (get_option($option_name)) {
347
-            update_option($option_name, $routes, true);
348
-        } else {
349
-            add_option($option_name, $routes, null, 'no');
350
-        }
351
-        return $routes;
352
-    }
353
-
354
-
355
-
356
-    /**
357
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
358
-     * need to calculate it on every request
359
-     *
360
-     * @deprecated since version 4.9.1
361
-     * @return void
362
-     */
363
-    public static function save_ee_routes()
364
-    {
365
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
366
-            $instance = self::instance();
367
-            $routes = apply_filters(
368
-                'EED_Core_Rest_Api__save_ee_routes__routes',
369
-                array_replace_recursive(
370
-                    $instance->_register_config_routes(),
371
-                    $instance->_register_meta_routes(),
372
-                    $instance->_register_model_routes(),
373
-                    $instance->_register_rpc_routes()
374
-                )
375
-            );
376
-            update_option(self::saved_routes_option_names, $routes, true);
377
-        }
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * Gets all the route information relating to EE models
384
-     *
385
-     * @return array @see get_ee_route_data
386
-     * @deprecated since version 4.9.1
387
-     */
388
-    protected function _register_model_routes()
389
-    {
390
-        $model_routes = array();
391
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
392
-            $model_routes[EED_Core_Rest_Api::ee_api_namespace
393
-                          . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
394
-        }
395
-        return $model_routes;
396
-    }
397
-
398
-
399
-
400
-    /**
401
-     * Decides whether or not to add write endpoints for this model.
402
-     *
403
-     * Currently, this defaults to exclude all global tables and models
404
-     * which would allow inserting WP core data (we don't want to duplicate
405
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
406
-     * @param EEM_Base $model
407
-     * @return bool
408
-     */
409
-    public static function should_have_write_endpoints(EEM_Base $model)
410
-    {
411
-        if ($model->is_wp_core_model()){
412
-            return false;
413
-        }
414
-        foreach($model->get_tables() as $table){
415
-            if( $table->is_global()){
416
-                return false;
417
-            }
418
-        }
419
-        return true;
420
-    }
421
-
422
-
423
-
424
-    /**
425
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
426
-     * in this versioned namespace of EE4
427
-     * @param $version
428
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429
-     */
430
-    public static function model_names_with_plural_routes($version){
431
-        $model_version_info = new ModelVersionInfo($version);
432
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
433
-        //let's not bother having endpoints for extra metas
434
-        unset(
435
-            $models_to_register['Extra_Meta'],
436
-            $models_to_register['Extra_Join'],
437
-            $models_to_register['Post_Meta']
438
-        );
439
-        return apply_filters(
440
-            'FHEE__EED_Core_REST_API___register_model_routes',
441
-            $models_to_register
442
-        );
443
-    }
444
-
445
-
446
-
447
-    /**
448
-     * Gets the route data for EE models in the specified version
449
-     *
450
-     * @param string  $version
451
-     * @param boolean $hidden_endpoint
452
-     * @return array
453
-     * @throws EE_Error
454
-     */
455
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
456
-    {
457
-        $model_routes = array();
458
-        $model_version_info = new ModelVersionInfo($version);
459
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460
-            $model = \EE_Registry::instance()->load_model($model_name);
461
-            //if this isn't a valid model then let's skip iterate to the next item in the loop.
462
-            if (! $model instanceof EEM_Base) {
463
-                continue;
464
-            }
465
-            //yes we could just register one route for ALL models, but then they wouldn't show up in the index
466
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
467
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
468
-            $model_routes[$plural_model_route] = array(
469
-                array(
470
-                    'callback'        => array(
471
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
472
-                        'handleRequestGetAll',
473
-                    ),
474
-                    'callback_args'   => array($version, $model_name),
475
-                    'methods'         => WP_REST_Server::READABLE,
476
-                    'hidden_endpoint' => $hidden_endpoint,
477
-                    'args'            => $this->_get_read_query_params($model, $version),
478
-                    '_links'          => array(
479
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
480
-                    ),
481
-                ),
482
-                'schema' => array(
483
-                    'schema_callback' => array(
484
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
485
-                        'handleSchemaRequest',
486
-                    ),
487
-                    'callback_args'   => array($version, $model_name),
488
-                ),
489
-            );
490
-            $model_routes[$singular_model_route] = array(
491
-                array(
492
-                    'callback'        => array(
493
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
494
-                        'handleRequestGetOne',
495
-                    ),
496
-                    'callback_args'   => array($version, $model_name),
497
-                    'methods'         => WP_REST_Server::READABLE,
498
-                    'hidden_endpoint' => $hidden_endpoint,
499
-                    'args'            => $this->_get_response_selection_query_params($model, $version),
500
-                ),
501
-            );
502
-            if( apply_filters(
503
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
505
-                $model
506
-            )){
507
-                $model_routes[$plural_model_route][] = array(
508
-                    'callback'        => array(
509
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
510
-                        'handleRequestInsert',
511
-                    ),
512
-                    'callback_args'   => array($version, $model_name),
513
-                    'methods'         => WP_REST_Server::CREATABLE,
514
-                    'hidden_endpoint' => $hidden_endpoint,
515
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
516
-                );
517
-                $model_routes[$singular_model_route] = array_merge(
518
-                    $model_routes[$singular_model_route],
519
-                    array(
520
-                        array(
521
-                            'callback'        => array(
522
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
523
-                                'handleRequestUpdate',
524
-                            ),
525
-                            'callback_args'   => array($version, $model_name),
526
-                            'methods'         => WP_REST_Server::EDITABLE,
527
-                            'hidden_endpoint' => $hidden_endpoint,
528
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
529
-                        ),
530
-                        array(
531
-                            'callback'        => array(
532
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
533
-                                'handleRequestDelete',
534
-                            ),
535
-                            'callback_args'   => array($version, $model_name),
536
-                            'methods'         => WP_REST_Server::DELETABLE,
537
-                            'hidden_endpoint' => $hidden_endpoint,
538
-                            'args'            => $this->_get_delete_query_params($model, $version),
539
-                        )
540
-                    )
541
-                );
542
-            }
543
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
544
-
545
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
546
-                    $model,
547
-                    '(?P<id>[^\/]+)',
548
-                    $relation_obj
549
-                );
550
-                $endpoints = array(
551
-                    array(
552
-                        'callback'        => array(
553
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
554
-                            'handleRequestGetRelated',
555
-                        ),
556
-                        'callback_args'   => array($version, $model_name, $relation_name),
557
-                        'methods'         => WP_REST_Server::READABLE,
558
-                        'hidden_endpoint' => $hidden_endpoint,
559
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
560
-                    ),
561
-                );
562
-                $model_routes[$related_route] = $endpoints;
563
-            }
564
-        }
565
-        return $model_routes;
566
-    }
567
-
568
-
569
-
570
-    /**
571
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
572
-     * excluding the preceding slash.
573
-     * Eg you pass get_plural_route_to('Event') = 'events'
574
-     *
575
-     * @param EEM_Base $model
576
-     * @return string
577
-     */
578
-    public static function get_collection_route(EEM_Base $model)
579
-    {
580
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
587
-     * excluding the preceding slash.
588
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
589
-     *
590
-     * @param EEM_Base $model eg Event or Venue
591
-     * @param string $id
592
-     * @return string
593
-     */
594
-    public static function get_entity_route($model, $id)
595
-    {
596
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
597
-    }
598
-
599
-
600
-    /**
601
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
602
-     * excluding the preceding slash.
603
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
604
-     *
605
-     * @param EEM_Base                 $model eg Event or Venue
606
-     * @param string                 $id
607
-     * @param EE_Model_Relation_Base $relation_obj
608
-     * @return string
609
-     */
610
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
611
-    {
612
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
613
-            $relation_obj->get_other_model()->get_this_model_name(),
614
-            $relation_obj
615
-        );
616
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
617
-    }
618
-
619
-
620
-
621
-    /**
622
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
623
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
624
-     * @param string $relative_route
625
-     * @param string $version
626
-     * @return string
627
-     */
628
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
630
-    }
631
-
632
-
633
-
634
-    /**
635
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
636
-     * routes that don't conform to the traditional REST CRUD-style).
637
-     *
638
-     * @deprecated since 4.9.1
639
-     */
640
-    protected function _register_rpc_routes()
641
-    {
642
-        $routes = array();
643
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
644
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
645
-                $version,
646
-                $hidden_endpoint
647
-            );
648
-        }
649
-        return $routes;
650
-    }
651
-
652
-
653
-
654
-    /**
655
-     * @param string  $version
656
-     * @param boolean $hidden_endpoint
657
-     * @return array
658
-     */
659
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
660
-    {
661
-        $this_versions_routes = array();
662
-        //checkin endpoint
663
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
664
-            array(
665
-                'callback'        => array(
666
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
667
-                    'handleRequestToggleCheckin',
668
-                ),
669
-                'methods'         => WP_REST_Server::CREATABLE,
670
-                'hidden_endpoint' => $hidden_endpoint,
671
-                'args'            => array(
672
-                    'force' => array(
673
-                        'required'    => false,
674
-                        'default'     => false,
675
-                        'description' => __(
676
-                            // @codingStandardsIgnoreStart
677
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
678
-                            // @codingStandardsIgnoreEnd
679
-                            'event_espresso'
680
-                        ),
681
-                    ),
682
-                ),
683
-                'callback_args'   => array($version),
684
-            ),
685
-        );
686
-        return apply_filters(
687
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
688
-            $this_versions_routes,
689
-            $version,
690
-            $hidden_endpoint
691
-        );
692
-    }
693
-
694
-
695
-
696
-    /**
697
-     * Gets the query params that can be used when request one or many
698
-     *
699
-     * @param EEM_Base $model
700
-     * @param string   $version
701
-     * @return array
702
-     */
703
-    protected function _get_response_selection_query_params(\EEM_Base $model, $version)
704
-    {
705
-        return apply_filters(
706
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
707
-            array(
708
-                'include'   => array(
709
-                    'required' => false,
710
-                    'default'  => '*',
711
-                    'type'     => 'string',
712
-                ),
713
-                'calculate' => array(
714
-                    'required'          => false,
715
-                    'default'           => '',
716
-                    'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
717
-                    'type'              => 'string',
718
-                    //because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
719
-                    //freaks out. We'll just validate this argument while handling the request
720
-                    'validate_callback' => null,
721
-                    'sanitize_callback' => null,
722
-                ),
723
-            ),
724
-            $model,
725
-            $version
726
-        );
727
-    }
728
-
729
-
730
-
731
-    /**
732
-     * Gets the parameters acceptable for delete requests
733
-     *
734
-     * @param \EEM_Base $model
735
-     * @param string    $version
736
-     * @return array
737
-     */
738
-    protected function _get_delete_query_params(\EEM_Base $model, $version)
739
-    {
740
-        $params_for_delete = array(
741
-            'allow_blocking' => array(
742
-                'required' => false,
743
-                'default'  => true,
744
-                'type'     => 'boolean',
745
-            ),
746
-        );
747
-        $params_for_delete['force'] = array(
748
-            'required' => false,
749
-            'default'  => false,
750
-            'type'     => 'boolean',
751
-        );
752
-        return apply_filters(
753
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
754
-            $params_for_delete,
755
-            $model,
756
-            $version
757
-        );
758
-    }
759
-
760
-
761
-
762
-    /**
763
-     * Gets info about reading query params that are acceptable
764
-     *
765
-     * @param \EEM_Base $model eg 'Event' or 'Venue'
766
-     * @param  string   $version
767
-     * @return array    describing the args acceptable when querying this model
768
-     * @throws EE_Error
769
-     */
770
-    protected function _get_read_query_params(\EEM_Base $model, $version)
771
-    {
772
-        $default_orderby = array();
773
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
774
-            $default_orderby[$key_field->get_name()] = 'ASC';
775
-        }
776
-        return array_merge(
777
-            $this->_get_response_selection_query_params($model, $version),
778
-            array(
779
-                'where'    => array(
780
-                    'required' => false,
781
-                    'default'  => array(),
782
-                    'type'     => 'object',
783
-                    //because we accept an almost infinite list of possible where conditions, WP
784
-                    // core validation and sanitization freaks out. We'll just validate this argument
785
-                    // while handling the request
786
-                    'validate_callback' => null,
787
-                    'sanitize_callback' => null,
788
-                ),
789
-                'limit'    => array(
790
-                    'required' => false,
791
-                    'default'  => EED_Core_Rest_Api::get_default_query_limit(),
792
-                    'type'     => array(
793
-                        'array',
794
-                        'string',
795
-                        'integer',
796
-                    ),
797
-                    //because we accept a variety of types, WP core validation and sanitization
798
-                    //freaks out. We'll just validate this argument while handling the request
799
-                    'validate_callback' => null,
800
-                    'sanitize_callback' => null,
801
-                ),
802
-                'order_by' => array(
803
-                    'required' => false,
804
-                    'default'  => $default_orderby,
805
-                    'type'     => array(
806
-                        'object',
807
-                        'string',
808
-                    ),//because we accept a variety of types, WP core validation and sanitization
809
-                    //freaks out. We'll just validate this argument while handling the request
810
-                    'validate_callback' => null,
811
-                    'sanitize_callback' => null,
812
-                ),
813
-                'group_by' => array(
814
-                    'required' => false,
815
-                    'default'  => null,
816
-                    'type'     => array(
817
-                        'object',
818
-                        'string',
819
-                    ),
820
-                    //because we accept  an almost infinite list of possible groupings,
821
-                    // WP core validation and sanitization
822
-                    //freaks out. We'll just validate this argument while handling the request
823
-                    'validate_callback' => null,
824
-                    'sanitize_callback' => null,
825
-                ),
826
-                'having'   => array(
827
-                    'required' => false,
828
-                    'default'  => null,
829
-                    'type'     => 'object',
830
-                    //because we accept an almost infinite list of possible where conditions, WP
831
-                    // core validation and sanitization freaks out. We'll just validate this argument
832
-                    // while handling the request
833
-                    'validate_callback' => null,
834
-                    'sanitize_callback' => null,
835
-                ),
836
-                'caps'     => array(
837
-                    'required' => false,
838
-                    'default'  => EEM_Base::caps_read,
839
-                    'type'     => 'string',
840
-                    'enum'     => array(
841
-                        EEM_Base::caps_read,
842
-                        EEM_Base::caps_read_admin,
843
-                        EEM_Base::caps_edit,
844
-                        EEM_Base::caps_delete
845
-                    )
846
-                ),
847
-            )
848
-        );
849
-    }
850
-
851
-
852
-
853
-    /**
854
-     * Gets parameter information for a model regarding writing data
855
-     *
856
-     * @param string           $model_name
857
-     * @param ModelVersionInfo $model_version_info
858
-     * @param boolean          $create                                       whether this is for request to create (in which case we need
859
-     *                                                                       all required params) or just to update (in which case we don't need those on every request)
860
-     * @return array
861
-     */
862
-    protected function _get_write_params(
863
-        $model_name,
864
-        ModelVersionInfo $model_version_info,
865
-        $create = false
866
-    ) {
867
-        $model = EE_Registry::instance()->load_model($model_name);
868
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
869
-        $args_info = array();
870
-        foreach ($fields as $field_name => $field_obj) {
871
-            if ($field_obj->is_auto_increment()) {
872
-                //totally ignore auto increment IDs
873
-                continue;
874
-            }
875
-            $arg_info = $field_obj->getSchema();
876
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
877
-            $arg_info['required'] = $required;
878
-            //remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
879
-            unset($arg_info['readonly']);
880
-            $schema_properties = $field_obj->getSchemaProperties();
881
-            if (
882
-                isset($schema_properties['raw'])
883
-                && $field_obj->getSchemaType() === 'object'
884
-            ) {
885
-                //if there's a "raw" form of this argument, use those properties instead
886
-                $arg_info = array_replace(
887
-                    $arg_info,
888
-                    $schema_properties['raw']
889
-                );
890
-            }
891
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
892
-                $field_obj,
893
-                $field_obj->get_default_value(),
894
-                $model_version_info->requestedVersion()
895
-            );
896
-            //we do our own validation and sanitization within the controller
897
-            if(function_exists('rest_validate_value_from_schema')){
898
-                $sanitize_callback = array(
899
-                    'EED_Core_Rest_Api',
900
-                    'default_sanitize_callback',
901
-                );
902
-            } else {
903
-                $sanitize_callback = null;
904
-            }
905
-            $arg_info['sanitize_callback'] = $sanitize_callback;
906
-            $args_info[$field_name] = $arg_info;
907
-            if ($field_obj instanceof EE_Datetime_Field) {
908
-                $gmt_arg_info = $arg_info;
909
-                $gmt_arg_info['description'] = sprintf(
910
-                    esc_html__(
911
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
912
-                        'event_espresso'
913
-                    ),
914
-                    $field_obj->get_nicename(),
915
-                    $field_name
916
-                );
917
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
918
-            }
919
-        }
920
-        return $args_info;
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * Replacement for WP API's 'rest_parse_request_arg'.
927
-     * If the value is blank but not required, don't bother validating it.
928
-     * Also, it uses our email validation instead of WP API's default.
929
-     *
930
-     * @param                 $value
931
-     * @param WP_REST_Request $request
932
-     * @param                 $param
933
-     * @return bool|true|WP_Error
934
-     * @throws InvalidArgumentException
935
-     * @throws InvalidInterfaceException
936
-     * @throws InvalidDataTypeException
937
-     */
938
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
939
-    {
940
-        $attributes = $request->get_attributes();
941
-        if (! isset($attributes['args'][$param])
942
-            || ! is_array($attributes['args'][$param])) {
943
-            $validation_result = true;
944
-        } else {
945
-            $args = $attributes['args'][$param];
946
-            if ((
947
-                    $value === ''
948
-                    || $value === null
949
-                )
950
-                && (! isset($args['required'])
951
-                    || $args['required'] === false
952
-                )
953
-            ) {
954
-                //not required and not provided? that's cool
955
-                $validation_result = true;
956
-            } elseif (isset($args['format'])
957
-                && $args['format'] === 'email'
958
-            ) {
959
-                $validation_result = true;
960
-                if (! self::_validate_email($value)) {
961
-                    $validation_result = new WP_Error(
962
-                        'rest_invalid_param',
963
-                        esc_html__(
964
-                            'The email address is not valid or does not exist.',
965
-                            'event_espresso'
966
-                        )
967
-                    );
968
-                }
969
-            } else {
970
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
971
-            }
972
-        }
973
-        if (is_wp_error($validation_result)) {
974
-            return $validation_result;
975
-        }
976
-        return rest_sanitize_request_arg($value, $request, $param);
977
-    }
978
-
979
-
980
-
981
-    /**
982
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
983
-     *
984
-     * @param $email
985
-     * @return bool
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidInterfaceException
988
-     * @throws InvalidDataTypeException
989
-     */
990
-    protected static function _validate_email($email){
991
-        try {
992
-            EmailAddressFactory::create($email);
993
-            return true;
994
-        } catch (EmailValidationException $e) {
995
-            return false;
996
-        }
997
-    }
998
-
999
-
1000
-
1001
-    /**
1002
-     * Gets routes for the config
1003
-     *
1004
-     * @return array @see _register_model_routes
1005
-     * @deprecated since version 4.9.1
1006
-     */
1007
-    protected function _register_config_routes()
1008
-    {
1009
-        $config_routes = array();
1010
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1012
-                $version,
1013
-                $hidden_endpoint
1014
-            );
1015
-        }
1016
-        return $config_routes;
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * Gets routes for the config for the specified version
1023
-     *
1024
-     * @param string  $version
1025
-     * @param boolean $hidden_endpoint
1026
-     * @return array
1027
-     */
1028
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1029
-    {
1030
-        return array(
1031
-            'config'    => array(
1032
-                array(
1033
-                    'callback'        => array(
1034
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1035
-                        'handleRequest',
1036
-                    ),
1037
-                    'methods'         => WP_REST_Server::READABLE,
1038
-                    'hidden_endpoint' => $hidden_endpoint,
1039
-                    'callback_args'   => array($version),
1040
-                ),
1041
-            ),
1042
-            'site_info' => array(
1043
-                array(
1044
-                    'callback'        => array(
1045
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1046
-                        'handleRequestSiteInfo',
1047
-                    ),
1048
-                    'methods'         => WP_REST_Server::READABLE,
1049
-                    'hidden_endpoint' => $hidden_endpoint,
1050
-                    'callback_args'   => array($version),
1051
-                ),
1052
-            ),
1053
-        );
1054
-    }
1055
-
1056
-
1057
-
1058
-    /**
1059
-     * Gets the meta info routes
1060
-     *
1061
-     * @return array @see _register_model_routes
1062
-     * @deprecated since version 4.9.1
1063
-     */
1064
-    protected function _register_meta_routes()
1065
-    {
1066
-        $meta_routes = array();
1067
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1069
-                $version,
1070
-                $hidden_endpoint
1071
-            );
1072
-        }
1073
-        return $meta_routes;
1074
-    }
1075
-
1076
-
1077
-
1078
-    /**
1079
-     * @param string  $version
1080
-     * @param boolean $hidden_endpoint
1081
-     * @return array
1082
-     */
1083
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1084
-    {
1085
-        return array(
1086
-            'resources' => array(
1087
-                array(
1088
-                    'callback'        => array(
1089
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1090
-                        'handleRequestModelsMeta',
1091
-                    ),
1092
-                    'methods'         => WP_REST_Server::READABLE,
1093
-                    'hidden_endpoint' => $hidden_endpoint,
1094
-                    'callback_args'   => array($version),
1095
-                ),
1096
-            ),
1097
-        );
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * Tries to hide old 4.6 endpoints from the
1104
-     *
1105
-     * @param array $route_data
1106
-     * @return array
1107
-     * @throws \EE_Error
1108
-     */
1109
-    public static function hide_old_endpoints($route_data)
1110
-    {
1111
-        //allow API clients to override which endpoints get hidden, in case
1112
-        //they want to discover particular endpoints
1113
-        //also, we don't have access to the request so we have to just grab it from the superglobal
1114
-        $force_show_ee_namespace = ltrim(
1115
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1116
-            '/'
1117
-        );
1118
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1119
-            foreach ($relative_urls as $resource_name => $endpoints) {
1120
-                foreach ($endpoints as $key => $endpoint) {
1121
-                    //skip schema and other route options
1122
-                    if (! is_numeric($key)) {
1123
-                        continue;
1124
-                    }
1125
-                    //by default, hide "hidden_endpoint"s, unless the request indicates
1126
-                    //to $force_show_ee_namespace, in which case only show that one
1127
-                    //namespace's endpoints (and hide all others)
1128
-                    if (
1129
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131
-                    ) {
1132
-                        $full_route = '/' . ltrim($namespace, '/');
1133
-                        $full_route .= '/' . ltrim($resource_name, '/');
1134
-                        unset($route_data[$full_route]);
1135
-                    }
1136
-                }
1137
-            }
1138
-        }
1139
-        return $route_data;
1140
-    }
1141
-
1142
-
1143
-
1144
-    /**
1145
-     * Returns an array describing which versions of core support serving requests for.
1146
-     * Keys are core versions' major and minor version, and values are the
1147
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1148
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1149
-     * the answers table entirely, in which case it would be very difficult for
1150
-     * it to serve 4.6-style responses.
1151
-     * Versions of core that are missing from this array are unknowns.
1152
-     * previous ver
1153
-     *
1154
-     * @return array
1155
-     */
1156
-    public static function version_compatibilities()
1157
-    {
1158
-        return apply_filters(
1159
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1160
-            array(
1161
-                '4.8.29' => '4.8.29',
1162
-                '4.8.33' => '4.8.29',
1163
-                '4.8.34' => '4.8.29',
1164
-                '4.8.36' => '4.8.29',
1165
-            )
1166
-        );
1167
-    }
1168
-
1169
-
1170
-
1171
-    /**
1172
-     * Gets the latest API version served. Eg if there
1173
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1174
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1175
-     *
1176
-     * @return string
1177
-     */
1178
-    public static function latest_rest_api_version()
1179
-    {
1180
-        $versions_served = \EED_Core_Rest_Api::versions_served();
1181
-        $versions_served_keys = array_keys($versions_served);
1182
-        return end($versions_served_keys);
1183
-    }
1184
-
1185
-
1186
-
1187
-    /**
1188
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1189
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1190
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1191
-     * We also indicate whether or not this version should be put in the index or not
1192
-     *
1193
-     * @return array keys are API version numbers (just major and minor numbers), and values
1194
-     * are whether or not they should be hidden
1195
-     */
1196
-    public static function versions_served()
1197
-    {
1198
-        $versions_served = array();
1199
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1200
-        $lowest_compatible_version = end($possibly_served_versions);
1201
-        reset($possibly_served_versions);
1202
-        $versions_served_historically = array_keys($possibly_served_versions);
1203
-        $latest_version = end($versions_served_historically);
1204
-        reset($versions_served_historically);
1205
-        //for each version of core we have ever served:
1206
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1207
-            //if it's not above the current core version, and it's compatible with the current version of core
1208
-            if ($key_versioned_endpoint === $latest_version) {
1209
-                //don't hide the latest version in the index
1210
-                $versions_served[$key_versioned_endpoint] = false;
1211
-            } elseif (
1212
-                $key_versioned_endpoint >= $lowest_compatible_version
1213
-                && $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1214
-            ) {
1215
-                //include, but hide, previous versions which are still supported
1216
-                $versions_served[$key_versioned_endpoint] = true;
1217
-            } elseif (apply_filters(
1218
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1219
-                false,
1220
-                $possibly_served_versions
1221
-            )) {
1222
-                //if a version is no longer supported, don't include it in index or list of versions served
1223
-                $versions_served[$key_versioned_endpoint] = true;
1224
-            }
1225
-        }
1226
-        return $versions_served;
1227
-    }
1228
-
1229
-
1230
-
1231
-    /**
1232
-     * Gets the major and minor version of EE core's version string
1233
-     *
1234
-     * @return string
1235
-     */
1236
-    public static function core_version()
1237
-    {
1238
-        return apply_filters(
1239
-            'FHEE__EED_Core_REST_API__core_version',
1240
-            implode(
1241
-                '.',
1242
-                array_slice(
1243
-                    explode(
1244
-                        '.',
1245
-                        espresso_version()
1246
-                    ),
1247
-                0,
1248
-                3
1249
-                )
1250
-            )
1251
-        );
1252
-    }
1253
-
1254
-
1255
-
1256
-    /**
1257
-     * Gets the default limit that should be used when querying for resources
1258
-     *
1259
-     * @return int
1260
-     */
1261
-    public static function get_default_query_limit()
1262
-    {
1263
-        //we actually don't use a const because we want folks to always use
1264
-        //this method, not the const directly
1265
-        return apply_filters(
1266
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1267
-            50
1268
-        );
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     *
1274
-     * @param string $version api version string (i.e. '4.8.36')
1275
-     * @return array
1276
-     */
1277
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1278
-    {
1279
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1280
-        $model_names = self::model_names_with_plural_routes($version);
1281
-        $collection_routes = array();
1282
-        foreach ($model_names as $model_name => $model_class_name) {
1283
-            $collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1284
-                                                          . EEH_Inflector::pluralize_and_lower($model_name);
1285
-
1286
-        }
1287
-        return $collection_routes;
1288
-    }
1289
-
1290
-
1291
-
1292
-    /**
1293
-     *    run - initial module setup
1294
-     *
1295
-     * @access    public
1296
-     * @param  WP $WP
1297
-     * @return    void
1298
-     */
1299
-    public function run($WP)
1300
-    {
1301
-    }
31
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
32
+
33
+	const saved_routes_option_names  = 'ee_core_routes';
34
+
35
+	/**
36
+	 * string used in _links response bodies to make them globally unique.
37
+	 *
38
+	 * @see http://v2.wp-api.org/extending/linking/
39
+	 */
40
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
41
+
42
+	/**
43
+	 * @var CalculatedModelFields
44
+	 */
45
+	protected static $_field_calculator;
46
+
47
+
48
+
49
+	/**
50
+	 * @return EED_Core_Rest_Api|EED_Module
51
+	 */
52
+	public static function instance()
53
+	{
54
+		self::$_field_calculator = new CalculatedModelFields();
55
+		return parent::get_instance(__CLASS__);
56
+	}
57
+
58
+
59
+
60
+	/**
61
+	 *    set_hooks - for hooking into EE Core, other modules, etc
62
+	 *
63
+	 * @access    public
64
+	 * @return    void
65
+	 */
66
+	public static function set_hooks()
67
+	{
68
+		self::set_hooks_both();
69
+	}
70
+
71
+
72
+
73
+	/**
74
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
75
+	 *
76
+	 * @access    public
77
+	 * @return    void
78
+	 */
79
+	public static function set_hooks_admin()
80
+	{
81
+		self::set_hooks_both();
82
+	}
83
+
84
+
85
+
86
+	public static function set_hooks_both()
87
+	{
88
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
89
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
90
+		add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
91
+		add_filter('rest_index',
92
+			array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
93
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
94
+	}
95
+
96
+
97
+
98
+	/**
99
+	 * sets up hooks which only need to be included as part of REST API requests;
100
+	 * other requests like to the frontend or admin etc don't need them
101
+	 *
102
+	 * @throws \EE_Error
103
+	 */
104
+	public static function set_hooks_rest_api()
105
+	{
106
+		//set hooks which account for changes made to the API
107
+		EED_Core_Rest_Api::_set_hooks_for_changes();
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * public wrapper of _set_hooks_for_changes.
114
+	 * Loads all the hooks which make requests to old versions of the API
115
+	 * appear the same as they always did
116
+	 *
117
+	 * @throws EE_Error
118
+	 */
119
+	public static function set_hooks_for_changes()
120
+	{
121
+		self::_set_hooks_for_changes();
122
+	}
123
+
124
+
125
+
126
+	/**
127
+	 * Loads all the hooks which make requests to old versions of the API
128
+	 * appear the same as they always did
129
+	 *
130
+	 * @throws EE_Error
131
+	 */
132
+	protected static function _set_hooks_for_changes()
133
+	{
134
+		$folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
135
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
136
+			//ignore the base parent class
137
+			//and legacy named classes
138
+			if ($classname_in_namespace === 'ChangesInBase'
139
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
140
+			) {
141
+				continue;
142
+			}
143
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
144
+			if (class_exists($full_classname)) {
145
+				$instance_of_class = new $full_classname;
146
+				if ($instance_of_class instanceof ChangesInBase) {
147
+					$instance_of_class->setHooks();
148
+				}
149
+			}
150
+		}
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
157
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
158
+	 *
159
+	 * @throws \EE_Error
160
+	 */
161
+	public static function register_routes()
162
+	{
163
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
164
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
165
+				/**
166
+				 * @var array $data_for_multiple_endpoints numerically indexed array
167
+				 *                                         but can also contain route options like {
168
+				 * @type array    $schema                      {
169
+				 * @type callable $schema_callback
170
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
171
+				 * WP_REST_Request of course
172
+				 * }
173
+				 * }
174
+				 */
175
+				//when registering routes, register all the endpoints' data at the same time
176
+				$multiple_endpoint_args = array();
177
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
178
+					/**
179
+					 * @var array     $data_for_single_endpoint {
180
+					 * @type callable $callback
181
+					 * @type string methods
182
+					 * @type array args
183
+					 * @type array _links
184
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
185
+					 * WP_REST_Request of course
186
+					 * }
187
+					 */
188
+					//skip route options
189
+					if (! is_numeric($endpoint_key)) {
190
+						continue;
191
+					}
192
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193
+						throw new EE_Error(
194
+							esc_html__(
195
+								// @codingStandardsIgnoreStart
196
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
197
+								// @codingStandardsIgnoreEnd
198
+								'event_espresso')
199
+						);
200
+					}
201
+					$callback = $data_for_single_endpoint['callback'];
202
+					$single_endpoint_args = array(
203
+						'methods' => $data_for_single_endpoint['methods'],
204
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
+							: array(),
206
+					);
207
+					if (isset($data_for_single_endpoint['_links'])) {
208
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
+					}
210
+					if (isset($data_for_single_endpoint['callback_args'])) {
211
+						$callback_args = $data_for_single_endpoint['callback_args'];
212
+						$single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
213
+							$callback,
214
+							$callback_args
215
+						) {
216
+							array_unshift($callback_args, $request);
217
+							return call_user_func_array(
218
+								$callback,
219
+								$callback_args
220
+							);
221
+						};
222
+					} else {
223
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
+					}
225
+					$multiple_endpoint_args[] = $single_endpoint_args;
226
+				}
227
+				if (isset($data_for_multiple_endpoints['schema'])) {
228
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
229
+					$schema_callback = $schema_route_data['schema_callback'];
230
+					$callback_args = $schema_route_data['callback_args'];
231
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
232
+						return call_user_func_array(
233
+							$schema_callback,
234
+							$callback_args
235
+						);
236
+					};
237
+				}
238
+				register_rest_route(
239
+					$namespace,
240
+					$relative_route,
241
+					$multiple_endpoint_args
242
+				);
243
+			}
244
+		}
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 * Checks if there was a version change or something that merits invalidating the cached
251
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
252
+	 * next time the WP API is used
253
+	 */
254
+	public static function invalidate_cached_route_data_on_version_change()
255
+	{
256
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
257
+			EED_Core_Rest_Api::invalidate_cached_route_data();
258
+		}
259
+		foreach (EE_Registry::instance()->addons as $addon) {
260
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
261
+				EED_Core_Rest_Api::invalidate_cached_route_data();
262
+			}
263
+		}
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
270
+	 */
271
+	public static function invalidate_cached_route_data()
272
+	{
273
+		//delete the saved EE REST API routes
274
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
276
+		}
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * Gets the EE route data
283
+	 *
284
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
285
+	 * @throws \EE_Error
286
+	 * @type string|array $callback
287
+	 * @type string       $methods
288
+	 * @type boolean      $hidden_endpoint
289
+	 * }
290
+	 */
291
+	public static function get_ee_route_data()
292
+	{
293
+		$ee_routes = array();
294
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
295
+			$ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
296
+				$version,
297
+				$hidden_endpoints
298
+			);
299
+		}
300
+		return $ee_routes;
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 * Gets the EE route data from the wp options if it exists already,
307
+	 * otherwise re-generates it and saves it to the option
308
+	 *
309
+	 * @param string  $version
310
+	 * @param boolean $hidden_endpoints
311
+	 * @return array
312
+	 * @throws \EE_Error
313
+	 */
314
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315
+	{
316
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
+		if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319
+		}
320
+		return $ee_routes;
321
+	}
322
+
323
+
324
+
325
+	/**
326
+	 * Saves the EE REST API route data to a wp option and returns it
327
+	 *
328
+	 * @param string  $version
329
+	 * @param boolean $hidden_endpoints
330
+	 * @return mixed|null
331
+	 * @throws \EE_Error
332
+	 */
333
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
334
+	{
335
+		$instance = self::instance();
336
+		$routes = apply_filters(
337
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
338
+			array_replace_recursive(
339
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
340
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
341
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
342
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343
+			)
344
+		);
345
+		$option_name = self::saved_routes_option_names . $version;
346
+		if (get_option($option_name)) {
347
+			update_option($option_name, $routes, true);
348
+		} else {
349
+			add_option($option_name, $routes, null, 'no');
350
+		}
351
+		return $routes;
352
+	}
353
+
354
+
355
+
356
+	/**
357
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
358
+	 * need to calculate it on every request
359
+	 *
360
+	 * @deprecated since version 4.9.1
361
+	 * @return void
362
+	 */
363
+	public static function save_ee_routes()
364
+	{
365
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
366
+			$instance = self::instance();
367
+			$routes = apply_filters(
368
+				'EED_Core_Rest_Api__save_ee_routes__routes',
369
+				array_replace_recursive(
370
+					$instance->_register_config_routes(),
371
+					$instance->_register_meta_routes(),
372
+					$instance->_register_model_routes(),
373
+					$instance->_register_rpc_routes()
374
+				)
375
+			);
376
+			update_option(self::saved_routes_option_names, $routes, true);
377
+		}
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Gets all the route information relating to EE models
384
+	 *
385
+	 * @return array @see get_ee_route_data
386
+	 * @deprecated since version 4.9.1
387
+	 */
388
+	protected function _register_model_routes()
389
+	{
390
+		$model_routes = array();
391
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
392
+			$model_routes[EED_Core_Rest_Api::ee_api_namespace
393
+						  . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
394
+		}
395
+		return $model_routes;
396
+	}
397
+
398
+
399
+
400
+	/**
401
+	 * Decides whether or not to add write endpoints for this model.
402
+	 *
403
+	 * Currently, this defaults to exclude all global tables and models
404
+	 * which would allow inserting WP core data (we don't want to duplicate
405
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
406
+	 * @param EEM_Base $model
407
+	 * @return bool
408
+	 */
409
+	public static function should_have_write_endpoints(EEM_Base $model)
410
+	{
411
+		if ($model->is_wp_core_model()){
412
+			return false;
413
+		}
414
+		foreach($model->get_tables() as $table){
415
+			if( $table->is_global()){
416
+				return false;
417
+			}
418
+		}
419
+		return true;
420
+	}
421
+
422
+
423
+
424
+	/**
425
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
426
+	 * in this versioned namespace of EE4
427
+	 * @param $version
428
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429
+	 */
430
+	public static function model_names_with_plural_routes($version){
431
+		$model_version_info = new ModelVersionInfo($version);
432
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
433
+		//let's not bother having endpoints for extra metas
434
+		unset(
435
+			$models_to_register['Extra_Meta'],
436
+			$models_to_register['Extra_Join'],
437
+			$models_to_register['Post_Meta']
438
+		);
439
+		return apply_filters(
440
+			'FHEE__EED_Core_REST_API___register_model_routes',
441
+			$models_to_register
442
+		);
443
+	}
444
+
445
+
446
+
447
+	/**
448
+	 * Gets the route data for EE models in the specified version
449
+	 *
450
+	 * @param string  $version
451
+	 * @param boolean $hidden_endpoint
452
+	 * @return array
453
+	 * @throws EE_Error
454
+	 */
455
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
456
+	{
457
+		$model_routes = array();
458
+		$model_version_info = new ModelVersionInfo($version);
459
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460
+			$model = \EE_Registry::instance()->load_model($model_name);
461
+			//if this isn't a valid model then let's skip iterate to the next item in the loop.
462
+			if (! $model instanceof EEM_Base) {
463
+				continue;
464
+			}
465
+			//yes we could just register one route for ALL models, but then they wouldn't show up in the index
466
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
467
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
468
+			$model_routes[$plural_model_route] = array(
469
+				array(
470
+					'callback'        => array(
471
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
472
+						'handleRequestGetAll',
473
+					),
474
+					'callback_args'   => array($version, $model_name),
475
+					'methods'         => WP_REST_Server::READABLE,
476
+					'hidden_endpoint' => $hidden_endpoint,
477
+					'args'            => $this->_get_read_query_params($model, $version),
478
+					'_links'          => array(
479
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
480
+					),
481
+				),
482
+				'schema' => array(
483
+					'schema_callback' => array(
484
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
485
+						'handleSchemaRequest',
486
+					),
487
+					'callback_args'   => array($version, $model_name),
488
+				),
489
+			);
490
+			$model_routes[$singular_model_route] = array(
491
+				array(
492
+					'callback'        => array(
493
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
494
+						'handleRequestGetOne',
495
+					),
496
+					'callback_args'   => array($version, $model_name),
497
+					'methods'         => WP_REST_Server::READABLE,
498
+					'hidden_endpoint' => $hidden_endpoint,
499
+					'args'            => $this->_get_response_selection_query_params($model, $version),
500
+				),
501
+			);
502
+			if( apply_filters(
503
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
505
+				$model
506
+			)){
507
+				$model_routes[$plural_model_route][] = array(
508
+					'callback'        => array(
509
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
510
+						'handleRequestInsert',
511
+					),
512
+					'callback_args'   => array($version, $model_name),
513
+					'methods'         => WP_REST_Server::CREATABLE,
514
+					'hidden_endpoint' => $hidden_endpoint,
515
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
516
+				);
517
+				$model_routes[$singular_model_route] = array_merge(
518
+					$model_routes[$singular_model_route],
519
+					array(
520
+						array(
521
+							'callback'        => array(
522
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
523
+								'handleRequestUpdate',
524
+							),
525
+							'callback_args'   => array($version, $model_name),
526
+							'methods'         => WP_REST_Server::EDITABLE,
527
+							'hidden_endpoint' => $hidden_endpoint,
528
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
529
+						),
530
+						array(
531
+							'callback'        => array(
532
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
533
+								'handleRequestDelete',
534
+							),
535
+							'callback_args'   => array($version, $model_name),
536
+							'methods'         => WP_REST_Server::DELETABLE,
537
+							'hidden_endpoint' => $hidden_endpoint,
538
+							'args'            => $this->_get_delete_query_params($model, $version),
539
+						)
540
+					)
541
+				);
542
+			}
543
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
544
+
545
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
546
+					$model,
547
+					'(?P<id>[^\/]+)',
548
+					$relation_obj
549
+				);
550
+				$endpoints = array(
551
+					array(
552
+						'callback'        => array(
553
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
554
+							'handleRequestGetRelated',
555
+						),
556
+						'callback_args'   => array($version, $model_name, $relation_name),
557
+						'methods'         => WP_REST_Server::READABLE,
558
+						'hidden_endpoint' => $hidden_endpoint,
559
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
560
+					),
561
+				);
562
+				$model_routes[$related_route] = $endpoints;
563
+			}
564
+		}
565
+		return $model_routes;
566
+	}
567
+
568
+
569
+
570
+	/**
571
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
572
+	 * excluding the preceding slash.
573
+	 * Eg you pass get_plural_route_to('Event') = 'events'
574
+	 *
575
+	 * @param EEM_Base $model
576
+	 * @return string
577
+	 */
578
+	public static function get_collection_route(EEM_Base $model)
579
+	{
580
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
587
+	 * excluding the preceding slash.
588
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
589
+	 *
590
+	 * @param EEM_Base $model eg Event or Venue
591
+	 * @param string $id
592
+	 * @return string
593
+	 */
594
+	public static function get_entity_route($model, $id)
595
+	{
596
+		return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
597
+	}
598
+
599
+
600
+	/**
601
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
602
+	 * excluding the preceding slash.
603
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
604
+	 *
605
+	 * @param EEM_Base                 $model eg Event or Venue
606
+	 * @param string                 $id
607
+	 * @param EE_Model_Relation_Base $relation_obj
608
+	 * @return string
609
+	 */
610
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
611
+	{
612
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
613
+			$relation_obj->get_other_model()->get_this_model_name(),
614
+			$relation_obj
615
+		);
616
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
617
+	}
618
+
619
+
620
+
621
+	/**
622
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
623
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
624
+	 * @param string $relative_route
625
+	 * @param string $version
626
+	 * @return string
627
+	 */
628
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
630
+	}
631
+
632
+
633
+
634
+	/**
635
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
636
+	 * routes that don't conform to the traditional REST CRUD-style).
637
+	 *
638
+	 * @deprecated since 4.9.1
639
+	 */
640
+	protected function _register_rpc_routes()
641
+	{
642
+		$routes = array();
643
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
644
+			$routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
645
+				$version,
646
+				$hidden_endpoint
647
+			);
648
+		}
649
+		return $routes;
650
+	}
651
+
652
+
653
+
654
+	/**
655
+	 * @param string  $version
656
+	 * @param boolean $hidden_endpoint
657
+	 * @return array
658
+	 */
659
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
660
+	{
661
+		$this_versions_routes = array();
662
+		//checkin endpoint
663
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
664
+			array(
665
+				'callback'        => array(
666
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
667
+					'handleRequestToggleCheckin',
668
+				),
669
+				'methods'         => WP_REST_Server::CREATABLE,
670
+				'hidden_endpoint' => $hidden_endpoint,
671
+				'args'            => array(
672
+					'force' => array(
673
+						'required'    => false,
674
+						'default'     => false,
675
+						'description' => __(
676
+							// @codingStandardsIgnoreStart
677
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
678
+							// @codingStandardsIgnoreEnd
679
+							'event_espresso'
680
+						),
681
+					),
682
+				),
683
+				'callback_args'   => array($version),
684
+			),
685
+		);
686
+		return apply_filters(
687
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
688
+			$this_versions_routes,
689
+			$version,
690
+			$hidden_endpoint
691
+		);
692
+	}
693
+
694
+
695
+
696
+	/**
697
+	 * Gets the query params that can be used when request one or many
698
+	 *
699
+	 * @param EEM_Base $model
700
+	 * @param string   $version
701
+	 * @return array
702
+	 */
703
+	protected function _get_response_selection_query_params(\EEM_Base $model, $version)
704
+	{
705
+		return apply_filters(
706
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
707
+			array(
708
+				'include'   => array(
709
+					'required' => false,
710
+					'default'  => '*',
711
+					'type'     => 'string',
712
+				),
713
+				'calculate' => array(
714
+					'required'          => false,
715
+					'default'           => '',
716
+					'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
717
+					'type'              => 'string',
718
+					//because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
719
+					//freaks out. We'll just validate this argument while handling the request
720
+					'validate_callback' => null,
721
+					'sanitize_callback' => null,
722
+				),
723
+			),
724
+			$model,
725
+			$version
726
+		);
727
+	}
728
+
729
+
730
+
731
+	/**
732
+	 * Gets the parameters acceptable for delete requests
733
+	 *
734
+	 * @param \EEM_Base $model
735
+	 * @param string    $version
736
+	 * @return array
737
+	 */
738
+	protected function _get_delete_query_params(\EEM_Base $model, $version)
739
+	{
740
+		$params_for_delete = array(
741
+			'allow_blocking' => array(
742
+				'required' => false,
743
+				'default'  => true,
744
+				'type'     => 'boolean',
745
+			),
746
+		);
747
+		$params_for_delete['force'] = array(
748
+			'required' => false,
749
+			'default'  => false,
750
+			'type'     => 'boolean',
751
+		);
752
+		return apply_filters(
753
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
754
+			$params_for_delete,
755
+			$model,
756
+			$version
757
+		);
758
+	}
759
+
760
+
761
+
762
+	/**
763
+	 * Gets info about reading query params that are acceptable
764
+	 *
765
+	 * @param \EEM_Base $model eg 'Event' or 'Venue'
766
+	 * @param  string   $version
767
+	 * @return array    describing the args acceptable when querying this model
768
+	 * @throws EE_Error
769
+	 */
770
+	protected function _get_read_query_params(\EEM_Base $model, $version)
771
+	{
772
+		$default_orderby = array();
773
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
774
+			$default_orderby[$key_field->get_name()] = 'ASC';
775
+		}
776
+		return array_merge(
777
+			$this->_get_response_selection_query_params($model, $version),
778
+			array(
779
+				'where'    => array(
780
+					'required' => false,
781
+					'default'  => array(),
782
+					'type'     => 'object',
783
+					//because we accept an almost infinite list of possible where conditions, WP
784
+					// core validation and sanitization freaks out. We'll just validate this argument
785
+					// while handling the request
786
+					'validate_callback' => null,
787
+					'sanitize_callback' => null,
788
+				),
789
+				'limit'    => array(
790
+					'required' => false,
791
+					'default'  => EED_Core_Rest_Api::get_default_query_limit(),
792
+					'type'     => array(
793
+						'array',
794
+						'string',
795
+						'integer',
796
+					),
797
+					//because we accept a variety of types, WP core validation and sanitization
798
+					//freaks out. We'll just validate this argument while handling the request
799
+					'validate_callback' => null,
800
+					'sanitize_callback' => null,
801
+				),
802
+				'order_by' => array(
803
+					'required' => false,
804
+					'default'  => $default_orderby,
805
+					'type'     => array(
806
+						'object',
807
+						'string',
808
+					),//because we accept a variety of types, WP core validation and sanitization
809
+					//freaks out. We'll just validate this argument while handling the request
810
+					'validate_callback' => null,
811
+					'sanitize_callback' => null,
812
+				),
813
+				'group_by' => array(
814
+					'required' => false,
815
+					'default'  => null,
816
+					'type'     => array(
817
+						'object',
818
+						'string',
819
+					),
820
+					//because we accept  an almost infinite list of possible groupings,
821
+					// WP core validation and sanitization
822
+					//freaks out. We'll just validate this argument while handling the request
823
+					'validate_callback' => null,
824
+					'sanitize_callback' => null,
825
+				),
826
+				'having'   => array(
827
+					'required' => false,
828
+					'default'  => null,
829
+					'type'     => 'object',
830
+					//because we accept an almost infinite list of possible where conditions, WP
831
+					// core validation and sanitization freaks out. We'll just validate this argument
832
+					// while handling the request
833
+					'validate_callback' => null,
834
+					'sanitize_callback' => null,
835
+				),
836
+				'caps'     => array(
837
+					'required' => false,
838
+					'default'  => EEM_Base::caps_read,
839
+					'type'     => 'string',
840
+					'enum'     => array(
841
+						EEM_Base::caps_read,
842
+						EEM_Base::caps_read_admin,
843
+						EEM_Base::caps_edit,
844
+						EEM_Base::caps_delete
845
+					)
846
+				),
847
+			)
848
+		);
849
+	}
850
+
851
+
852
+
853
+	/**
854
+	 * Gets parameter information for a model regarding writing data
855
+	 *
856
+	 * @param string           $model_name
857
+	 * @param ModelVersionInfo $model_version_info
858
+	 * @param boolean          $create                                       whether this is for request to create (in which case we need
859
+	 *                                                                       all required params) or just to update (in which case we don't need those on every request)
860
+	 * @return array
861
+	 */
862
+	protected function _get_write_params(
863
+		$model_name,
864
+		ModelVersionInfo $model_version_info,
865
+		$create = false
866
+	) {
867
+		$model = EE_Registry::instance()->load_model($model_name);
868
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
869
+		$args_info = array();
870
+		foreach ($fields as $field_name => $field_obj) {
871
+			if ($field_obj->is_auto_increment()) {
872
+				//totally ignore auto increment IDs
873
+				continue;
874
+			}
875
+			$arg_info = $field_obj->getSchema();
876
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
877
+			$arg_info['required'] = $required;
878
+			//remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
879
+			unset($arg_info['readonly']);
880
+			$schema_properties = $field_obj->getSchemaProperties();
881
+			if (
882
+				isset($schema_properties['raw'])
883
+				&& $field_obj->getSchemaType() === 'object'
884
+			) {
885
+				//if there's a "raw" form of this argument, use those properties instead
886
+				$arg_info = array_replace(
887
+					$arg_info,
888
+					$schema_properties['raw']
889
+				);
890
+			}
891
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
892
+				$field_obj,
893
+				$field_obj->get_default_value(),
894
+				$model_version_info->requestedVersion()
895
+			);
896
+			//we do our own validation and sanitization within the controller
897
+			if(function_exists('rest_validate_value_from_schema')){
898
+				$sanitize_callback = array(
899
+					'EED_Core_Rest_Api',
900
+					'default_sanitize_callback',
901
+				);
902
+			} else {
903
+				$sanitize_callback = null;
904
+			}
905
+			$arg_info['sanitize_callback'] = $sanitize_callback;
906
+			$args_info[$field_name] = $arg_info;
907
+			if ($field_obj instanceof EE_Datetime_Field) {
908
+				$gmt_arg_info = $arg_info;
909
+				$gmt_arg_info['description'] = sprintf(
910
+					esc_html__(
911
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
912
+						'event_espresso'
913
+					),
914
+					$field_obj->get_nicename(),
915
+					$field_name
916
+				);
917
+				$args_info[$field_name . '_gmt'] = $gmt_arg_info;
918
+			}
919
+		}
920
+		return $args_info;
921
+	}
922
+
923
+
924
+
925
+	/**
926
+	 * Replacement for WP API's 'rest_parse_request_arg'.
927
+	 * If the value is blank but not required, don't bother validating it.
928
+	 * Also, it uses our email validation instead of WP API's default.
929
+	 *
930
+	 * @param                 $value
931
+	 * @param WP_REST_Request $request
932
+	 * @param                 $param
933
+	 * @return bool|true|WP_Error
934
+	 * @throws InvalidArgumentException
935
+	 * @throws InvalidInterfaceException
936
+	 * @throws InvalidDataTypeException
937
+	 */
938
+	public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
939
+	{
940
+		$attributes = $request->get_attributes();
941
+		if (! isset($attributes['args'][$param])
942
+			|| ! is_array($attributes['args'][$param])) {
943
+			$validation_result = true;
944
+		} else {
945
+			$args = $attributes['args'][$param];
946
+			if ((
947
+					$value === ''
948
+					|| $value === null
949
+				)
950
+				&& (! isset($args['required'])
951
+					|| $args['required'] === false
952
+				)
953
+			) {
954
+				//not required and not provided? that's cool
955
+				$validation_result = true;
956
+			} elseif (isset($args['format'])
957
+				&& $args['format'] === 'email'
958
+			) {
959
+				$validation_result = true;
960
+				if (! self::_validate_email($value)) {
961
+					$validation_result = new WP_Error(
962
+						'rest_invalid_param',
963
+						esc_html__(
964
+							'The email address is not valid or does not exist.',
965
+							'event_espresso'
966
+						)
967
+					);
968
+				}
969
+			} else {
970
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
971
+			}
972
+		}
973
+		if (is_wp_error($validation_result)) {
974
+			return $validation_result;
975
+		}
976
+		return rest_sanitize_request_arg($value, $request, $param);
977
+	}
978
+
979
+
980
+
981
+	/**
982
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
983
+	 *
984
+	 * @param $email
985
+	 * @return bool
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidInterfaceException
988
+	 * @throws InvalidDataTypeException
989
+	 */
990
+	protected static function _validate_email($email){
991
+		try {
992
+			EmailAddressFactory::create($email);
993
+			return true;
994
+		} catch (EmailValidationException $e) {
995
+			return false;
996
+		}
997
+	}
998
+
999
+
1000
+
1001
+	/**
1002
+	 * Gets routes for the config
1003
+	 *
1004
+	 * @return array @see _register_model_routes
1005
+	 * @deprecated since version 4.9.1
1006
+	 */
1007
+	protected function _register_config_routes()
1008
+	{
1009
+		$config_routes = array();
1010
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
+			$config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1012
+				$version,
1013
+				$hidden_endpoint
1014
+			);
1015
+		}
1016
+		return $config_routes;
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * Gets routes for the config for the specified version
1023
+	 *
1024
+	 * @param string  $version
1025
+	 * @param boolean $hidden_endpoint
1026
+	 * @return array
1027
+	 */
1028
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1029
+	{
1030
+		return array(
1031
+			'config'    => array(
1032
+				array(
1033
+					'callback'        => array(
1034
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1035
+						'handleRequest',
1036
+					),
1037
+					'methods'         => WP_REST_Server::READABLE,
1038
+					'hidden_endpoint' => $hidden_endpoint,
1039
+					'callback_args'   => array($version),
1040
+				),
1041
+			),
1042
+			'site_info' => array(
1043
+				array(
1044
+					'callback'        => array(
1045
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1046
+						'handleRequestSiteInfo',
1047
+					),
1048
+					'methods'         => WP_REST_Server::READABLE,
1049
+					'hidden_endpoint' => $hidden_endpoint,
1050
+					'callback_args'   => array($version),
1051
+				),
1052
+			),
1053
+		);
1054
+	}
1055
+
1056
+
1057
+
1058
+	/**
1059
+	 * Gets the meta info routes
1060
+	 *
1061
+	 * @return array @see _register_model_routes
1062
+	 * @deprecated since version 4.9.1
1063
+	 */
1064
+	protected function _register_meta_routes()
1065
+	{
1066
+		$meta_routes = array();
1067
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
+			$meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1069
+				$version,
1070
+				$hidden_endpoint
1071
+			);
1072
+		}
1073
+		return $meta_routes;
1074
+	}
1075
+
1076
+
1077
+
1078
+	/**
1079
+	 * @param string  $version
1080
+	 * @param boolean $hidden_endpoint
1081
+	 * @return array
1082
+	 */
1083
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1084
+	{
1085
+		return array(
1086
+			'resources' => array(
1087
+				array(
1088
+					'callback'        => array(
1089
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1090
+						'handleRequestModelsMeta',
1091
+					),
1092
+					'methods'         => WP_REST_Server::READABLE,
1093
+					'hidden_endpoint' => $hidden_endpoint,
1094
+					'callback_args'   => array($version),
1095
+				),
1096
+			),
1097
+		);
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * Tries to hide old 4.6 endpoints from the
1104
+	 *
1105
+	 * @param array $route_data
1106
+	 * @return array
1107
+	 * @throws \EE_Error
1108
+	 */
1109
+	public static function hide_old_endpoints($route_data)
1110
+	{
1111
+		//allow API clients to override which endpoints get hidden, in case
1112
+		//they want to discover particular endpoints
1113
+		//also, we don't have access to the request so we have to just grab it from the superglobal
1114
+		$force_show_ee_namespace = ltrim(
1115
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1116
+			'/'
1117
+		);
1118
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1119
+			foreach ($relative_urls as $resource_name => $endpoints) {
1120
+				foreach ($endpoints as $key => $endpoint) {
1121
+					//skip schema and other route options
1122
+					if (! is_numeric($key)) {
1123
+						continue;
1124
+					}
1125
+					//by default, hide "hidden_endpoint"s, unless the request indicates
1126
+					//to $force_show_ee_namespace, in which case only show that one
1127
+					//namespace's endpoints (and hide all others)
1128
+					if (
1129
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131
+					) {
1132
+						$full_route = '/' . ltrim($namespace, '/');
1133
+						$full_route .= '/' . ltrim($resource_name, '/');
1134
+						unset($route_data[$full_route]);
1135
+					}
1136
+				}
1137
+			}
1138
+		}
1139
+		return $route_data;
1140
+	}
1141
+
1142
+
1143
+
1144
+	/**
1145
+	 * Returns an array describing which versions of core support serving requests for.
1146
+	 * Keys are core versions' major and minor version, and values are the
1147
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1148
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1149
+	 * the answers table entirely, in which case it would be very difficult for
1150
+	 * it to serve 4.6-style responses.
1151
+	 * Versions of core that are missing from this array are unknowns.
1152
+	 * previous ver
1153
+	 *
1154
+	 * @return array
1155
+	 */
1156
+	public static function version_compatibilities()
1157
+	{
1158
+		return apply_filters(
1159
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1160
+			array(
1161
+				'4.8.29' => '4.8.29',
1162
+				'4.8.33' => '4.8.29',
1163
+				'4.8.34' => '4.8.29',
1164
+				'4.8.36' => '4.8.29',
1165
+			)
1166
+		);
1167
+	}
1168
+
1169
+
1170
+
1171
+	/**
1172
+	 * Gets the latest API version served. Eg if there
1173
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1174
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1175
+	 *
1176
+	 * @return string
1177
+	 */
1178
+	public static function latest_rest_api_version()
1179
+	{
1180
+		$versions_served = \EED_Core_Rest_Api::versions_served();
1181
+		$versions_served_keys = array_keys($versions_served);
1182
+		return end($versions_served_keys);
1183
+	}
1184
+
1185
+
1186
+
1187
+	/**
1188
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1189
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1190
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1191
+	 * We also indicate whether or not this version should be put in the index or not
1192
+	 *
1193
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1194
+	 * are whether or not they should be hidden
1195
+	 */
1196
+	public static function versions_served()
1197
+	{
1198
+		$versions_served = array();
1199
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1200
+		$lowest_compatible_version = end($possibly_served_versions);
1201
+		reset($possibly_served_versions);
1202
+		$versions_served_historically = array_keys($possibly_served_versions);
1203
+		$latest_version = end($versions_served_historically);
1204
+		reset($versions_served_historically);
1205
+		//for each version of core we have ever served:
1206
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1207
+			//if it's not above the current core version, and it's compatible with the current version of core
1208
+			if ($key_versioned_endpoint === $latest_version) {
1209
+				//don't hide the latest version in the index
1210
+				$versions_served[$key_versioned_endpoint] = false;
1211
+			} elseif (
1212
+				$key_versioned_endpoint >= $lowest_compatible_version
1213
+				&& $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1214
+			) {
1215
+				//include, but hide, previous versions which are still supported
1216
+				$versions_served[$key_versioned_endpoint] = true;
1217
+			} elseif (apply_filters(
1218
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1219
+				false,
1220
+				$possibly_served_versions
1221
+			)) {
1222
+				//if a version is no longer supported, don't include it in index or list of versions served
1223
+				$versions_served[$key_versioned_endpoint] = true;
1224
+			}
1225
+		}
1226
+		return $versions_served;
1227
+	}
1228
+
1229
+
1230
+
1231
+	/**
1232
+	 * Gets the major and minor version of EE core's version string
1233
+	 *
1234
+	 * @return string
1235
+	 */
1236
+	public static function core_version()
1237
+	{
1238
+		return apply_filters(
1239
+			'FHEE__EED_Core_REST_API__core_version',
1240
+			implode(
1241
+				'.',
1242
+				array_slice(
1243
+					explode(
1244
+						'.',
1245
+						espresso_version()
1246
+					),
1247
+				0,
1248
+				3
1249
+				)
1250
+			)
1251
+		);
1252
+	}
1253
+
1254
+
1255
+
1256
+	/**
1257
+	 * Gets the default limit that should be used when querying for resources
1258
+	 *
1259
+	 * @return int
1260
+	 */
1261
+	public static function get_default_query_limit()
1262
+	{
1263
+		//we actually don't use a const because we want folks to always use
1264
+		//this method, not the const directly
1265
+		return apply_filters(
1266
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1267
+			50
1268
+		);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 *
1274
+	 * @param string $version api version string (i.e. '4.8.36')
1275
+	 * @return array
1276
+	 */
1277
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1278
+	{
1279
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1280
+		$model_names = self::model_names_with_plural_routes($version);
1281
+		$collection_routes = array();
1282
+		foreach ($model_names as $model_name => $model_class_name) {
1283
+			$collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1284
+														  . EEH_Inflector::pluralize_and_lower($model_name);
1285
+
1286
+		}
1287
+		return $collection_routes;
1288
+	}
1289
+
1290
+
1291
+
1292
+	/**
1293
+	 *    run - initial module setup
1294
+	 *
1295
+	 * @access    public
1296
+	 * @param  WP $WP
1297
+	 * @return    void
1298
+	 */
1299
+	public function run($WP)
1300
+	{
1301
+	}
1302 1302
 }
1303 1303
 
1304 1304
 // End of file EED_Core_Rest_Api.module.php
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
      */
132 132
     protected static function _set_hooks_for_changes()
133 133
     {
134
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
134
+        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES.'rest_api'.DS.'changes'), false);
135 135
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
136 136
             //ignore the base parent class
137 137
             //and legacy named classes
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
             ) {
141 141
                 continue;
142 142
             }
143
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
144 144
             if (class_exists($full_classname)) {
145 145
                 $instance_of_class = new $full_classname;
146 146
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -186,10 +186,10 @@  discard block
 block discarded – undo
186 186
                      * }
187 187
                      */
188 188
                     //skip route options
189
-                    if (! is_numeric($endpoint_key)) {
189
+                    if ( ! is_numeric($endpoint_key)) {
190 190
                         continue;
191 191
                     }
192
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193 193
                         throw new EE_Error(
194 194
                             esc_html__(
195 195
                                 // @codingStandardsIgnoreStart
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
                     }
210 210
                     if (isset($data_for_single_endpoint['callback_args'])) {
211 211
                         $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
212
+                        $single_endpoint_args['callback'] = function(\WP_REST_Request $request) use (
213 213
                             $callback,
214 214
                             $callback_args
215 215
                         ) {
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
229 229
                     $schema_callback = $schema_route_data['schema_callback'];
230 230
                     $callback_args = $schema_route_data['callback_args'];
231
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
231
+                    $multiple_endpoint_args['schema'] = function() use ($schema_callback, $callback_args) {
232 232
                         return call_user_func_array(
233 233
                             $schema_callback,
234 234
                             $callback_args
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
     {
273 273
         //delete the saved EE REST API routes
274 274
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
275
+            delete_option(EED_Core_Rest_Api::saved_routes_option_names.$version);
276 276
         }
277 277
     }
278 278
 
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
     {
293 293
         $ee_routes = array();
294 294
         foreach (self::versions_served() as $version => $hidden_endpoints) {
295
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
295
+            $ee_routes[self::ee_api_namespace.$version] = self::_get_ee_route_data_for_version(
296 296
                 $version,
297 297
                 $hidden_endpoints
298 298
             );
@@ -313,8 +313,8 @@  discard block
 block discarded – undo
313 313
      */
314 314
     protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315 315
     {
316
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
316
+        $ee_routes = get_option(self::saved_routes_option_names.$version, null);
317
+        if ( ! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318 318
             $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319 319
         }
320 320
         return $ee_routes;
@@ -342,7 +342,7 @@  discard block
 block discarded – undo
342 342
                 $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343 343
             )
344 344
         );
345
-        $option_name = self::saved_routes_option_names . $version;
345
+        $option_name = self::saved_routes_option_names.$version;
346 346
         if (get_option($option_name)) {
347 347
             update_option($option_name, $routes, true);
348 348
         } else {
@@ -408,11 +408,11 @@  discard block
 block discarded – undo
408 408
      */
409 409
     public static function should_have_write_endpoints(EEM_Base $model)
410 410
     {
411
-        if ($model->is_wp_core_model()){
411
+        if ($model->is_wp_core_model()) {
412 412
             return false;
413 413
         }
414
-        foreach($model->get_tables() as $table){
415
-            if( $table->is_global()){
414
+        foreach ($model->get_tables() as $table) {
415
+            if ($table->is_global()) {
416 416
                 return false;
417 417
             }
418 418
         }
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
      * @param $version
428 428
      * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429 429
      */
430
-    public static function model_names_with_plural_routes($version){
430
+    public static function model_names_with_plural_routes($version) {
431 431
         $model_version_info = new ModelVersionInfo($version);
432 432
         $models_to_register = $model_version_info->modelsForRequestedVersion();
433 433
         //let's not bother having endpoints for extra metas
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460 460
             $model = \EE_Registry::instance()->load_model($model_name);
461 461
             //if this isn't a valid model then let's skip iterate to the next item in the loop.
462
-            if (! $model instanceof EEM_Base) {
462
+            if ( ! $model instanceof EEM_Base) {
463 463
                 continue;
464 464
             }
465 465
             //yes we could just register one route for ALL models, but then they wouldn't show up in the index
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
                     'hidden_endpoint' => $hidden_endpoint,
477 477
                     'args'            => $this->_get_read_query_params($model, $version),
478 478
                     '_links'          => array(
479
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
479
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
480 480
                     ),
481 481
                 ),
482 482
                 'schema' => array(
@@ -499,11 +499,11 @@  discard block
 block discarded – undo
499 499
                     'args'            => $this->_get_response_selection_query_params($model, $version),
500 500
                 ),
501 501
             );
502
-            if( apply_filters(
502
+            if (apply_filters(
503 503
                 'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504 504
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
505 505
                 $model
506
-            )){
506
+            )) {
507 507
                 $model_routes[$plural_model_route][] = array(
508 508
                     'callback'        => array(
509 509
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
@@ -593,7 +593,7 @@  discard block
 block discarded – undo
593 593
      */
594 594
     public static function get_entity_route($model, $id)
595 595
     {
596
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
596
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
597 597
     }
598 598
 
599 599
 
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
             $relation_obj->get_other_model()->get_this_model_name(),
614 614
             $relation_obj
615 615
         );
616
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
616
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
617 617
     }
618 618
 
619 619
 
@@ -625,8 +625,8 @@  discard block
 block discarded – undo
625 625
      * @param string $version
626 626
      * @return string
627 627
      */
628
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
628
+    public static function get_versioned_route_to($relative_route, $version = '4.8.36') {
629
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
630 630
     }
631 631
 
632 632
 
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
     {
642 642
         $routes = array();
643 643
         foreach (self::versions_served() as $version => $hidden_endpoint) {
644
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
644
+            $routes[self::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
645 645
                 $version,
646 646
                 $hidden_endpoint
647 647
             );
@@ -805,7 +805,7 @@  discard block
 block discarded – undo
805 805
                     'type'     => array(
806 806
                         'object',
807 807
                         'string',
808
-                    ),//because we accept a variety of types, WP core validation and sanitization
808
+                    ), //because we accept a variety of types, WP core validation and sanitization
809 809
                     //freaks out. We'll just validate this argument while handling the request
810 810
                     'validate_callback' => null,
811 811
                     'sanitize_callback' => null,
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
                 $model_version_info->requestedVersion()
895 895
             );
896 896
             //we do our own validation and sanitization within the controller
897
-            if(function_exists('rest_validate_value_from_schema')){
897
+            if (function_exists('rest_validate_value_from_schema')) {
898 898
                 $sanitize_callback = array(
899 899
                     'EED_Core_Rest_Api',
900 900
                     'default_sanitize_callback',
@@ -914,7 +914,7 @@  discard block
 block discarded – undo
914 914
                     $field_obj->get_nicename(),
915 915
                     $field_name
916 916
                 );
917
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
917
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
918 918
             }
919 919
         }
920 920
         return $args_info;
@@ -935,10 +935,10 @@  discard block
 block discarded – undo
935 935
      * @throws InvalidInterfaceException
936 936
      * @throws InvalidDataTypeException
937 937
      */
938
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
938
+    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
939 939
     {
940 940
         $attributes = $request->get_attributes();
941
-        if (! isset($attributes['args'][$param])
941
+        if ( ! isset($attributes['args'][$param])
942 942
             || ! is_array($attributes['args'][$param])) {
943 943
             $validation_result = true;
944 944
         } else {
@@ -947,7 +947,7 @@  discard block
 block discarded – undo
947 947
                     $value === ''
948 948
                     || $value === null
949 949
                 )
950
-                && (! isset($args['required'])
950
+                && ( ! isset($args['required'])
951 951
                     || $args['required'] === false
952 952
                 )
953 953
             ) {
@@ -957,7 +957,7 @@  discard block
 block discarded – undo
957 957
                 && $args['format'] === 'email'
958 958
             ) {
959 959
                 $validation_result = true;
960
-                if (! self::_validate_email($value)) {
960
+                if ( ! self::_validate_email($value)) {
961 961
                     $validation_result = new WP_Error(
962 962
                         'rest_invalid_param',
963 963
                         esc_html__(
@@ -987,7 +987,7 @@  discard block
 block discarded – undo
987 987
      * @throws InvalidInterfaceException
988 988
      * @throws InvalidDataTypeException
989 989
      */
990
-    protected static function _validate_email($email){
990
+    protected static function _validate_email($email) {
991 991
         try {
992 992
             EmailAddressFactory::create($email);
993 993
             return true;
@@ -1008,7 +1008,7 @@  discard block
 block discarded – undo
1008 1008
     {
1009 1009
         $config_routes = array();
1010 1010
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1011
+            $config_routes[self::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1012 1012
                 $version,
1013 1013
                 $hidden_endpoint
1014 1014
             );
@@ -1065,7 +1065,7 @@  discard block
 block discarded – undo
1065 1065
     {
1066 1066
         $meta_routes = array();
1067 1067
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1068
+            $meta_routes[self::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1069 1069
                 $version,
1070 1070
                 $hidden_endpoint
1071 1071
             );
@@ -1119,7 +1119,7 @@  discard block
 block discarded – undo
1119 1119
             foreach ($relative_urls as $resource_name => $endpoints) {
1120 1120
                 foreach ($endpoints as $key => $endpoint) {
1121 1121
                     //skip schema and other route options
1122
-                    if (! is_numeric($key)) {
1122
+                    if ( ! is_numeric($key)) {
1123 1123
                         continue;
1124 1124
                     }
1125 1125
                     //by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1129,8 +1129,8 @@  discard block
 block discarded – undo
1129 1129
                         ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130 1130
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131 1131
                     ) {
1132
-                        $full_route = '/' . ltrim($namespace, '/');
1133
-                        $full_route .= '/' . ltrim($resource_name, '/');
1132
+                        $full_route = '/'.ltrim($namespace, '/');
1133
+                        $full_route .= '/'.ltrim($resource_name, '/');
1134 1134
                         unset($route_data[$full_route]);
1135 1135
                     }
1136 1136
                 }
@@ -1280,7 +1280,7 @@  discard block
 block discarded – undo
1280 1280
         $model_names = self::model_names_with_plural_routes($version);
1281 1281
         $collection_routes = array();
1282 1282
         foreach ($model_names as $model_name => $model_class_name) {
1283
-            $collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1283
+            $collection_routes[strtolower($model_name)] = '/'.self::ee_api_namespace.$version.'/'
1284 1284
                                                           . EEH_Inflector::pluralize_and_lower($model_name);
1285 1285
 
1286 1286
         }
Please login to merge, or discard this patch.