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 / Http / Endpoints / DistributionEndpoint.php

DistributionEndpoint.php in Metricool – Social media and site statistics 2.0.2, at app/Http/Endpoints/DistributionEndpoint.php

135 lines 4.1 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\Http\Endpoints;
6
7 use Metricool\Http\Endpoints\Responses\DistributionResponse;
8 use Metricool\Http\Endpoints\Responses\Statistics\CountriesResponse;
9 use Metricool\Http\Endpoints\Responses\Statistics\RefererResponse;
10 use Metricool\Http\Metricool\DTOs\DistributionDTO;
11 use Metricool\Http\Metricool\MetricoolApi;
12 use Metricool\Interfaces\SingleEndpointInterface;
13 use Metricool\Support\Helpers\Collection;
14 use Metricool\Traits\HasAllowlistControl;
15 use Metricool\Traits\HasRestAccess;
16
17 class DistributionEndpoint implements SingleEndpointInterface
18 {
19 use HasRestAccess;
20 use HasAllowlistControl;
21
22 public const ROUTE = 'distribution';
23
24 private const METRICS_RESPONSE_MAPPER = [
25 'countries' => CountriesResponse::class,
26 'referers' => RefererResponse::class,
27 ];
28
29 public MetricoolApi $metricoolApi;
30
31 public function __construct(MetricoolApi $metricoolApi)
32 {
33 $this->metricoolApi = $metricoolApi;
34 }
35
36 /**
37 * @inheritDoc
38 */
39 public function registerRoute(): string
40 {
41 return self::ROUTE . '/(?P<metric>[^/]+)';
42 }
43
44 /**
45 * @inheritDoc
46 */
47 public function enabled(): bool
48 {
49 return $this->adminAccessAllowed();
50 }
51
52 /**
53 * @inheritDoc
54 */
55 public function registerArguments(): array
56 {
57 return [
58 'methods' => \WP_REST_Server::READABLE,
59 'callback' => [$this, 'callback'],
60 'middleware' => ['metricool:auth', 'metricool:blog_id'],
61 ];
62 }
63
64 /**
65 * Method will dynamically request the requested statistic. If the metric
66 * is filterable and filters are provided, it will apply them before
67 * retrieving the data.
68 * @example /wp-json/metricool/v1/statistics/countries?filters[start]=20250618&filters[end]=20250718&filters[country]=nl
69 */
70 public function callback(\WP_REST_Request $request): \WP_REST_Response
71 {
72 try {
73 $response = $this->buildResponse($request);
74 } catch (\Exception $e) {
75 return $this->sendHttpErrorResponse(__('Failed to load Analytics data', 'metricool'), $e->getMessage(), $e->getCode());
76 }
77
78 return $this->sendHttpResponse($response);
79 }
80
81 /**
82 * Build the specific Analytics response for the endpoint. This is mainly
83 * used in the plugin Dashboard to reflect non-realtime statistics.
84 * Building it server side prevents client-side complexity.
85 *
86 * @throws \Exception
87 */
88 private function buildResponse(\WP_REST_Request $request): array
89 {
90 $metric = ($request->get_param('metric') ?: '');
91 $requestFilters = ($request->get_param('filters') ?: []);
92
93 // Load the statistics
94 $statistics = $this->getStatisticsForMetric($metric, $requestFilters);
95
96 // Find the associated response object for the metric
97 $response = $this->createResponseObjectFromMetric($metric, $statistics);
98
99 return $response->body();
100 }
101
102 /**
103 * Loads the results from the Metricool API
104 * @return Collection|DistributionDTO[]
105 */
106 protected function getStatisticsForMetric(string $metric, array $filters): Collection
107 {
108 $statisticsModule = $this->metricoolApi->statistics();
109
110 // Load the results
111 $metricModule = $statisticsModule->$metric();
112 if (!empty($filters)) {
113 $metricModule->filter($filters);
114 }
115
116 return $metricModule->get();
117 }
118
119 /**
120 * Find the response that matches the requested metric or throw an exception.
121 * Each metric has its own specific serialisation of the results and chartData
122 * @param Collection|DistributionDTO[] $statistics
123 */
124 protected function createResponseObjectFromMetric(string $metric, Collection $statistics): DistributionResponse
125 {
126 if (!array_key_exists($metric, self::METRICS_RESPONSE_MAPPER)) {
127 throw new \InvalidArgumentException(esc_html("Metric $metric is not accepted by this endpoint"));
128 }
129
130 $response = self::METRICS_RESPONSE_MAPPER[$metric];
131
132 return new $response($statistics);
133 }
134 }
135