PluginProbe
Metricool – Social media and site statistics / 2.1.1
Metricool – Social media and site statistics v2.1.1
2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
← All changes | app/Features/Onboarding/OnboardingService.php +104 -0 2.0.0 → 2.1.1 View file →
@@ -1,0 +1,104 @@
1 +<?php
2 +
3 +namespace Metricool\Features\Onboarding;
4 +
5 +use Metricool\Http\Metricool\Exceptions\ApiException;
6 +use Metricool\Features\Onboarding\Exceptions\BrandAccessDeniedException;
7 +use Metricool\Http\Metricool\MetricoolApi;
8 +use Metricool\Services\DashboardService;
9 +use Metricool\Services\MetricoolAccountService;
10 +use Metricool\Services\TrackingScriptService;
11 +
12 +class OnboardingService
13 +{
14 + private MetricoolApi $api;
15 + private TrackingScriptService $tracking;
16 + private DashboardService $dashboard;
17 + private MetricoolAccountService $account;
18 +
19 + public function __construct(MetricoolApi $api, TrackingScriptService $tracking, DashboardService $dashboard, MetricoolAccountService $account)
20 + {
21 + $this->api = $api;
22 + $this->tracking = $tracking;
23 + $this->dashboard = $dashboard;
24 + $this->account = $account;
25 + }
26 +
27 + /**
28 + * Attempt to finish the onboarding process. When the necessary information is provided or retrieved,
29 + * set the onboarding as completed.
30 + *
31 + * @throws BrandAccessDeniedException
32 + * @throws ApiException
33 + */
34 + public function finalizeOnboarding(?string $blogId = null): bool
35 + {
36 + if ($blogId !== null) {
37 + // When a blogId is provided, try to connect to the brand
38 + $this->connectBrand($blogId);
39 + }
40 +
41 + // If the blogId is not set, the onboarding is not completed
42 + if ($this->api->hasBlogId() === false) {
43 + return false;
44 + }
45 +
46 + // Update the metricool user data from the API
47 + $this->account->fetch();
48 +
49 + // When all the necessary information is retrieved, set the onboarding as completed
50 + return $this->dashboard->setOnboardingCompleted();
51 + }
52 +
53 + /**
54 + * A brand is connected when it's retrieved from the API and the tracking hash is activated. The blogId is stored for future API calls.
55 + *
56 + * @throws BrandAccessDeniedException
57 + * @throws ApiException
58 + */
59 + private function connectBrand(string $blogId): void
60 + {
61 + try {
62 + $brand = $this->api->brands()->get($blogId);
63 + } catch (ApiException $e) {
64 + if ($e->getCode() === 403) {
65 + throw new BrandAccessDeniedException();
66 + }
67 + throw $e;
68 + }
69 +
70 + if (!$this->brandCanBeConnected($brand)) {
71 + throw new BrandAccessDeniedException();
72 + }
73 +
74 + $this->activateTrackingHash($brand);
75 + $this->api->storeBlogId($blogId);
76 + }
77 +
78 + /**
79 + * A brand can only be connected by its owner or by a user whose brand
80 + * role includes the editBrand permission. This is the same capability
81 + * the Metricool API validates when linking a site to a brand.
82 + */
83 + private function brandCanBeConnected(array $brand): bool
84 + {
85 + if (isset($brand['ownerUserId']) && (string) $brand['ownerUserId'] === $this->api->getUserId()) {
86 + return true;
87 + }
88 +
89 + return isset($brand['brandRole']['actions']['editBrand']) && $brand['brandRole']['actions']['editBrand'] === true;
90 + }
91 +
92 + /**
93 + * Activate the tracking hash for the given brand and store it in the database
94 + */
95 + private function activateTrackingHash(array $brand): void
96 + {
97 + $trackingId = isset($brand['hash']) ? (string) $brand['hash'] : null;
98 +
99 + if ($trackingId !== null) {
100 + $this->tracking->storeTrackingHash($trackingId)
101 + ->activateTrackingWidget();
102 + }
103 + }
104 +}