SettingsController::actionSaveSite()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 12
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 25
rs 9.8666
1
<?php
2
/**
3
 * @link      https://dukt.net/analytics/
4
 * @copyright Copyright (c) 2022, Dukt
5
 * @license   https://github.com/dukt/analytics/blob/master/LICENSE.md
6
 */
7
8
namespace dukt\analytics\controllers;
9
10
use Craft;
11
use craft\errors\InvalidPluginException;
12
use craft\web\Controller;
13
use dukt\analytics\models\SiteView;
14
use dukt\analytics\models\View;
15
use dukt\analytics\web\assets\settings\SettingsAsset;
16
use dukt\analytics\Plugin as Analytics;
17
use Exception;
18
use Google_Service_Exception;
19
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
20
use yii\web\NotFoundHttpException;
21
use yii\web\Response;
22
23
class SettingsController extends Controller
24
{
25
    // Public Methods
26
    // =========================================================================
27
28
    /**
29
     * Index.
30
     *
31
     * @return Response
32
     * @throws \yii\base\InvalidConfigException
33
     */
34
    public function actionIndex(): Response
35
    {
36
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
37
38
        if ($isOauthProviderConfigured) {
39
            $errors = [];
40
41
            try {
42
                $provider = Analytics::$plugin->oauth->getOauthProvider();
43
                $token = Analytics::$plugin->oauth->getToken();
44
45
                if ($token) {
46
                    $oauthAccount = Analytics::$plugin->cache->get(['getAccount', $token]);
47
48
                    if (!$oauthAccount) {
49
                        $oauthAccount = $provider->getResourceOwner($token);
50
                        Analytics::$plugin->cache->set(['getAccount', $token], $oauthAccount);
51
                    }
52
53
                    if ($oauthAccount) {
54
                        Craft::info("Account:\r\n".print_r($oauthAccount, true), __METHOD__);
0 ignored issues
show
Bug introduced by
Are you sure print_r($oauthAccount, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

54
                        Craft::info("Account:\r\n"./** @scrutinizer ignore-type */ print_r($oauthAccount, true), __METHOD__);
Loading history...
55
56
                        $plugin = Craft::$app->getPlugins()->getPlugin('analytics');
57
                        $settings = $plugin->getSettings();
58
                    }
59
                }
60
            } catch (Google_Service_Exception $e) {
61
                Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
62
63
                foreach ($e->getErrors() as $error) {
64
                    $errors[] = $error['message'];
65
                }
66
            } catch (IdentityProviderException $e) {
67
                $error = $e->getMessage();
68
                $data = $e->getResponseBody();
69
70
                if (isset($data['error_description'])) {
71
                    $error = $data['error_description'];
72
                }
73
74
                $errors[] = $error;
75
            } catch (Exception $e) {
76
                if (method_exists($e, 'getResponse')) {
77
                    Craft::info('Couldn’t get OAuth account: '.$e->getResponse(), __METHOD__);
78
                } else {
79
                    Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
80
                }
81
82
                $errors[] = $e->getMessage();
83
            }
84
        }
85
86
        Craft::$app->getView()->registerAssetBundle(SettingsAsset::class);
87
88
        return $this->renderTemplate('analytics/settings/_index', [
89
            'isOauthProviderConfigured' => $isOauthProviderConfigured,
90
            'errors' => $errors ?? null,
91
            'oauthAccount' => $oauthAccount ?? null,
92
            'settings' => $settings ?? null,
93
            'info' => Analytics::getInstance()->getInfo(),
94
            'googleIconUrl' => Craft::$app->assetManager->getPublishedUrl('@dukt/analytics/icons/google.svg', true),
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
            'googleIconUrl' => Craft::$app->assetManager->/** @scrutinizer ignore-call */ getPublishedUrl('@dukt/analytics/icons/google.svg', true),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
95
        ]);
96
    }
97
98
    /**
99
     * OAuth Settings.
100
     *
101
     * @return Response
102
     * @throws \craft\errors\SiteNotFoundException
103
     */
104
    public function actionOauth(): Response
105
    {
106
        return $this->renderTemplate('analytics/settings/_oauth', [
107
            'javascriptOrigin' => Analytics::$plugin->oauth->getJavascriptOrigin(),
108
            'redirectUri' => Analytics::$plugin->oauth->getRedirectUri(),
109
            'googleIconUrl' => Craft::$app->assetManager->getPublishedUrl('@dukt/analytics/icons/google.svg', true),
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
            'googleIconUrl' => Craft::$app->assetManager->/** @scrutinizer ignore-call */ getPublishedUrl('@dukt/analytics/icons/google.svg', true),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
110
            'settings' => Analytics::$plugin->getSettings(),
111
        ]);
112
    }
113
114
    /**
115
     * Saves the settings.
116
     *
117
     * @return null|Response
118
     * @throws InvalidPluginException
119
     * @throws \yii\base\InvalidConfigException
120
     * @throws \yii\web\BadRequestHttpException
121
     */
122
    public function actionSaveSettings()
123
    {
124
        $this->requirePostRequest();
125
126
        $pluginHandle = Craft::$app->getRequest()->getRequiredBodyParam('pluginHandle');
127
        $settings = Craft::$app->getRequest()->getBodyParam('settings');
128
        $plugin = Craft::$app->getPlugins()->getPlugin($pluginHandle);
129
130
        if (!$plugin) {
131
            throw new InvalidPluginException($pluginHandle);
132
        }
133
134
        $settings = Analytics::$plugin->getApis()->getAnalytics()->populateAccountExplorerSettings($settings);
135
136
        if (Craft::$app->getPlugins()->savePluginSettings($plugin, $settings)) {
137
            Craft::$app->getSession()->setNotice(Craft::t('analytics', 'Plugin settings saved.'));
138
139
            return $this->redirectToPostedUrl();
140
        }
141
142
        Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save plugin settings.'));
143
144
        // Send the plugin back to the template
145
        Craft::$app->getUrlManager()->setRouteParams([
146
            'plugin' => $plugin
147
        ]);
148
149
        return null;
150
    }
151
152
    /**
153
     * Returns the account explorer data.
154
     *
155
     * @return Response
156
     * @throws \yii\base\InvalidConfigException
157
     */
158
    public function actionGetAccountExplorerData(): Response
159
    {
160
        $accountExplorerData = Analytics::$plugin->getApis()->getAnalytics()->getAccountExplorerData();
161
162
        Analytics::$plugin->cache->set(['accountExplorerData'], $accountExplorerData);
163
164
        return $this->asJson($accountExplorerData);
165
    }
166
167
    /**
168
     * Views index.
169
     *
170
     * @return Response
171
     * @throws \yii\base\InvalidConfigException
172
     */
173
    public function actionViews(): Response
174
    {
175
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
176
177
        $variables = [
178
            'isConnected' => false
179
        ];
180
181
        try {
182
            $token = Analytics::$plugin->oauth->getToken();
183
184
            if ($isOauthProviderConfigured && $token) {
185
                $variables['isConnected'] = true;
186
                $variables['reportingViews'] = Analytics::$plugin->getViews()->getViews();
187
            }
188
        } catch (IdentityProviderException $e) {
189
            $variables['error'] = $e->getMessage();
190
191
            $data = $e->getResponseBody();
192
193
            if (isset($data['error_description'])) {
194
                $variables['error'] = $data['error_description'];
195
            }
196
        }
197
198
        return $this->renderTemplate('analytics/settings/views/_index', $variables);
199
    }
200
201
    /**
202
     * Edit a view.
203
     *
204
     * @param int|null  $viewId
205
     * @param View|null $reportingView
206
     *
207
     * @return Response
208
     * @throws NotFoundHttpException
209
     * @throws \yii\base\InvalidConfigException
210
     */
211
    public function actionEditView(int $viewId = null, View $reportingView = null): Response
212
    {
213
        $variables['isNewView'] = false;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$variables was never initialized. Although not strictly required by PHP, it is generally a good practice to add $variables = array(); before regardless.
Loading history...
214
215
        if ($viewId !== null) {
216
            if ($reportingView === null) {
217
                $reportingView = Analytics::$plugin->getViews()->getViewById($viewId);
218
219
                if (!$reportingView) {
0 ignored issues
show
introduced by
$reportingView is of type dukt\analytics\models\View, thus it always evaluated to true.
Loading history...
220
                    throw new NotFoundHttpException('View not found');
221
                }
222
            }
223
224
            $variables['title'] = $reportingView->name;
225
            $variables['reportingView'] = $reportingView;
226
        } else {
227
            if ($reportingView === null) {
228
                $reportingView = new View();
229
                $variables['isNewView'] = true;
230
            }
231
            $variables['title'] = Craft::t('analytics', 'Create a new view');
232
        }
233
234
        $variables['reportingView'] = $reportingView;
235
        $variables['accountExplorerOptions'] = $this->getAccountExplorerOptions($reportingView);
236
237
        Craft::$app->getView()->registerAssetBundle(SettingsAsset::class);
238
239
        return $this->renderTemplate('analytics/settings/views/_edit', $variables);
240
    }
241
242
    /**
243
     * Saves a view.
244
     *
245
     * @return null|Response
246
     * @throws \dukt\analytics\errors\InvalidViewException
247
     * @throws \yii\base\InvalidConfigException
248
     * @throws \yii\web\BadRequestHttpException
249
     */
250
    public function actionSaveView()
251
    {
252
        $this->requirePostRequest();
253
254
        $request = Craft::$app->getRequest();
255
        $accountExplorer = $request->getBodyParam('accountExplorer');
256
257
        $reportingView = new View();
258
        $reportingView->id = $request->getBodyParam('viewId');
259
        $reportingView->name = $request->getBodyParam('name');
260
        $reportingView->gaAccountId = $accountExplorer['account'];
261
        $reportingView->gaPropertyId = $accountExplorer['property'];
262
        $reportingView->gaViewId = $accountExplorer['view'];
263
264
        $accountExplorerData = Analytics::$plugin->getApis()->getAnalytics()->getAccountExplorerData();
265
266
        foreach ($accountExplorerData['accounts'] as $dataAccount) {
267
            if ($dataAccount->id == $reportingView->gaAccountId) {
268
                $reportingView->gaAccountName = $dataAccount->name;
269
            }
270
        }
271
272
        foreach ($accountExplorerData['properties'] as $dataProperty) {
273
            if ($dataProperty->id == $reportingView->gaPropertyId) {
274
                $reportingView->gaPropertyName = $dataProperty->name;
275
            }
276
        }
277
        foreach ($accountExplorerData['views'] as $dataView) {
278
            if ($dataView->id == $reportingView->gaViewId) {
279
                $reportingView->gaViewName = $dataView->name;
280
                $reportingView->gaViewCurrency = $dataView->currency;
281
            }
282
        }
283
284
        // Save it
285
        if (!Analytics::$plugin->getViews()->saveView($reportingView)) {
286
            Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save the view.'));
287
288
            // Send the view back to the template
289
            Craft::$app->getUrlManager()->setRouteParams([
290
                'reportingView' => $reportingView
291
            ]);
292
293
            return null;
294
        }
295
296
        Craft::$app->getSession()->setNotice(Craft::t('analytics', 'View saved.'));
297
298
        return $this->redirectToPostedUrl($reportingView);
299
    }
300
301
    /**
302
     * Deletes a view.
303
     *
304
     * @return Response
305
     * @throws \Throwable
306
     * @throws \yii\db\StaleObjectException
307
     * @throws \yii\web\BadRequestHttpException
308
     */
309
    public function actionDeleteView(): Response
310
    {
311
        $this->requirePostRequest();
312
        $this->requireAcceptsJson();
313
314
        $request = Craft::$app->getRequest();
315
        $viewId = $request->getRequiredBodyParam('id');
316
317
        Analytics::$plugin->getViews()->deleteViewById($viewId);
318
319
        return $this->asJson(['success' => true]);
320
    }
321
322
    /**
323
     * Sites index.
324
     *
325
     * @return Response
326
     * @throws \yii\base\InvalidConfigException
327
     */
328
    public function actionSites(): Response
329
    {
330
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
331
332
        $variables = [
333
            'isConnected' => false
334
        ];
335
336
        try {
337
            $token = Analytics::$plugin->oauth->getToken();
338
339
            if ($isOauthProviderConfigured && $token) {
340
                $variables['isConnected'] = true;
341
                $variables['sites'] = Craft::$app->getSites()->getAllSites();
342
                $variables['siteViews'] = Analytics::$plugin->getViews()->getSiteViews();
343
            }
344
        } catch (IdentityProviderException $e) {
345
            $variables['error'] = $e->getMessage();
346
347
            $data = $e->getResponseBody();
348
349
            if (isset($data['error_description'])) {
350
                $variables['error'] = $data['error_description'];
351
            }
352
        }
353
354
        return $this->renderTemplate('analytics/settings/sites/_index', $variables);
355
    }
356
357
    /**
358
     * Edit a site.
359
     *
360
     * @param $siteId
361
     *
362
     * @return Response
363
     * @throws \yii\base\InvalidConfigException
364
     */
365
    public function actionEditSite($siteId): Response
366
    {
367
        $site = Craft::$app->getSites()->getSiteById($siteId);
368
        $siteView = Analytics::$plugin->getViews()->getSiteViewBySiteId($siteId);
369
        $reportingViews = Analytics::$plugin->getViews()->getViews();
370
371
        return $this->renderTemplate('analytics/settings/sites/_edit', [
372
            'site' => $site,
373
            'siteView' => $siteView,
374
            'reportingViews' => $reportingViews,
375
        ]);
376
    }
377
378
    /**
379
     * Saves a site.
380
     *
381
     * @return null|Response
382
     * @throws \yii\base\InvalidConfigException
383
     * @throws \yii\db\Exception
384
     * @throws \yii\web\BadRequestHttpException
385
     */
386
    public function actionSaveSite()
387
    {
388
        $this->requirePostRequest();
389
390
        $request = Craft::$app->getRequest();
391
392
        $siteView = new SiteView();
393
        $siteView->siteId = $request->getBodyParam('siteId');
394
        $siteView->viewId = $request->getBodyParam('viewId');
395
396
        // Save it
397
        if (!Analytics::$plugin->getViews()->saveSiteView($siteView)) {
398
            Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save the site view.'));
399
400
            // Send the view back to the template
401
            Craft::$app->getUrlManager()->setRouteParams([
402
                'siteView' => $siteView
403
            ]);
404
405
            return null;
406
        }
407
408
        Craft::$app->getSession()->setNotice(Craft::t('analytics', 'Site view saved.'));
409
410
        return $this->redirectToPostedUrl($siteView);
411
    }
412
413
    // Private Methods
414
    // =========================================================================
415
416
    /**
417
     * @param View $reportingView
418
     *
419
     * @return array
420
     */
421
    private function getAccountExplorerOptions(View $reportingView): array
422
    {
423
        $accountExplorerData = Analytics::$plugin->cache->get(['accountExplorerData']);
424
425
        return [
426
            'accounts' => $this->getAccountOptions($accountExplorerData, $reportingView),
427
            'properties' => $this->getPropertyOptions($accountExplorerData, $reportingView),
428
            'views' => $this->getViewOptions($accountExplorerData, $reportingView),
429
        ];
430
    }
431
432
    /**
433
     * @param      $accountExplorerData
434
     * @param View $reportingView
435
     *
436
     * @return array
437
     */
438
    private function getAccountOptions($accountExplorerData, View $reportingView): array
439
    {
440
        $accountOptions = [];
441
442
        if (isset($accountExplorerData['accounts'])) {
443
            foreach ($accountExplorerData['accounts'] as $account) {
444
                $accountOptions[] = ['label' => $account->name, 'value' => $account->id];
445
            }
446
        } else {
447
            $accountOptions[] = ['label' => $reportingView->gaAccountName, 'value' => $reportingView->gaAccountId];
448
        }
449
450
        return $accountOptions;
451
    }
452
453
    /**
454
     * @param      $accountExplorerData
455
     * @param View $reportingView
456
     *
457
     * @return array
458
     */
459
    private function getPropertyOptions($accountExplorerData, View $reportingView): array
460
    {
461
        $propertyOptions = [];
462
463
        if (isset($accountExplorerData['properties'])) {
464
            foreach ($accountExplorerData['properties'] as $webProperty) {
465
                $propertyOptions[] = ['label' => $webProperty->name, 'value' => $webProperty->id];
466
            }
467
        } else {
468
            $propertyOptions[] = ['label' => $reportingView->gaPropertyName, 'value' => $reportingView->gaPropertyId];
469
        }
470
471
        return $propertyOptions;
472
    }
473
474
    /**
475
     * @param      $accountExplorerData
476
     * @param View $reportingView
477
     *
478
     * @return array
479
     */
480
    private function getViewOptions($accountExplorerData, View $reportingView): array
481
    {
482
        $viewOptions = [];
483
484
        if (isset($accountExplorerData['views'])) {
485
            foreach ($accountExplorerData['views'] as $dataView) {
486
                $viewOptions[] = ['label' => $dataView->name, 'value' => $dataView->id];
487
            }
488
        } else {
489
            $viewOptions[] = ['label' => $reportingView->gaViewName, 'value' => $reportingView->gaViewId];
490
        }
491
492
        return $viewOptions;
493
    }
494
}