PluginProbe
Metricool – Social media and site statistics / 2.0.2
Metricool – Social media and site statistics v2.0.2
2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
metricool / app / Features / AbstractLoader.php

AbstractLoader.php in Metricool – Social media and site statistics 2.0.2, at app/Features/AbstractLoader.php

91 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Metricool\Features;
6
7 use Metricool\Support\Helpers\Storages\RequestStorage;
8 use Metricool\Support\Helpers\Storages\EnvironmentConfig;
9
10 /**
11 * Each Feature should have a {FeatureName}Loader class that extends this
12 * abstract loader. The {@see FeatureManager} will use the loader to determine
13 * if a feature should be loaded.
14 *
15 * @internal Without loading all the feature classes, composer will prevent
16 * requiring the files entirely. Even tho the Feature namespace falls
17 * withing the psr-4 scope.
18 */
19 abstract class AbstractLoader
20 {
21 protected EnvironmentConfig $env;
22 protected RequestStorage $request;
23
24 public function __construct(EnvironmentConfig $env, RequestStorage $request)
25 {
26 $this->env = $env;
27 $this->request = $request;
28 }
29
30 /**
31 * Method should return true if the feature is enabled. This can check
32 * setting values or user capabilities for example.
33 */
34 abstract public function isEnabled(): bool;
35
36 /**
37 * Method should return true if the context of the user is in the scope of
38 * the feature to be loaded. For example: some features only need to load
39 * on our dashboard and others also in each REST API request.
40 */
41 abstract public function inScope(): bool;
42
43 /**
44 * Check if the current user is on the Dashboard page.
45 * @todo Responsibility for retrieving the dashboard "page" value should
46 * be added somewhere and it should be globally accessible.
47 */
48 protected function userIsOnDashboard(): bool
49 {
50 $pageVisitedByUser = $this->request->getString('global.page');
51 $dashboardUrl = $this->env->getString('plugin.dashboard_url');
52
53 $pluginPageQueryString = wp_parse_url($dashboardUrl, PHP_URL_QUERY);
54 parse_str($pluginPageQueryString, $parsedQuery);
55 $pluginDashboardPage = ($parsedQuery['page'] ?? '');
56
57 return $pageVisitedByUser === $pluginDashboardPage;
58 }
59
60 /**
61 * Check if the current request is a WP JSON request. This is better than
62 * the WordPress native function `wp_is_json_request()`, because that
63 * returns false when visiting /wp-json/ or ?rest_route= (for plain
64 * permalinks) endpoint. We need a true value there to activate
65 * features that register REST routes. For example
66 * {@see \Metricool\Features\Onboarding\OnboardingController}
67 *
68 * @internal Ignore the phpcs errors for this method, as they are false
69 * positives. We do not actually use the $_GET or $_SERVER variables
70 * directly, but we need to check if they are set and contain the
71 * expected values.
72 */
73 protected function requestIsRestRequest(): bool
74 {
75 $pluginHttpNamespace = $this->env->getString('http.namespace');
76 $restUrlPrefix = trailingslashit(rest_get_url_prefix());
77
78 $currentRequestUri = isset($_SERVER['REQUEST_URI'])
79 ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI']))
80 : '';
81 $isPlainPermalink = (
82 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is a REST route detection check, not form processing.
83 isset($_GET['rest_route'])
84 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is a REST route detection check, not form processing.
85 && (strpos(sanitize_text_field(wp_unslash($_GET['rest_route'])), $pluginHttpNamespace) !== false)
86 );
87
88 return (strpos($currentRequestUri, $restUrlPrefix) !== false) || $isPlainPermalink;
89 }
90 }
91