Passed
Push — v4 ( 92005e...1f7d3f )
by Benjamin
04:15
created

SettingsController::actionDeleteView()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link      https://dukt.net/craft/analytics/
4
 * @copyright Copyright (c) 2018, Dukt
5
 * @license   https://dukt.net/craft/analytics/docs/license
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
     * @param null $plugin
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $plugin is correct as it would always require null to be passed?
Loading history...
32
     *
33
     * @return Response
34
     * @throws \craft\errors\SiteNotFoundException
35
     * @throws \yii\base\InvalidConfigException
36
     */
37
    public function actionIndex($plugin = null): Response
38
    {
39
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
40
41
        if ($isOauthProviderConfigured) {
42
            $errors = [];
43
44
            try {
45
                if (!$plugin) {
46
                    $plugin = Craft::$app->getPlugins()->getPlugin('analytics');
47
                }
48
49
                $provider = Analytics::$plugin->oauth->getOauthProvider();
50
                $token = Analytics::$plugin->oauth->getToken();
51
52
                if ($token) {
53
                    $oauthAccount = Analytics::$plugin->cache->get(['getAccount', $token]);
54
55
                    if (!$oauthAccount) {
56
                        $oauthAccount = $provider->getResourceOwner($token);
57
                        Analytics::$plugin->cache->set(['getAccount', $token], $oauthAccount);
58
                    }
59
60
                    if ($oauthAccount) {
61
                        Craft::info("Account:\r\n".print_r($oauthAccount, true), __METHOD__);
62
63
                        $settings = $plugin->getSettings();
64
                    }
65
                }
66
            } catch (Google_Service_Exception $e) {
67
                Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
68
69
                foreach ($e->getErrors() as $error) {
70
                    $errors[] = $error['message'];
71
                }
72
            } catch (IdentityProviderException $e) {
73
                $error = $e->getMessage();
74
75
                $data = $e->getResponseBody();
76
77
                if (isset($data['error_description'])) {
78
                    $error = $data['error_description'];
79
                }
80
81
                $errors[] = $error;
82
            } catch (Exception $e) {
83
                if (method_exists($e, 'getResponse')) {
84
                    Craft::info('Couldn’t get OAuth account: '.$e->getResponse(), __METHOD__);
85
                } else {
86
                    Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
87
                }
88
89
                $errors[] = $e->getMessage();
90
            }
91
        }
92
93
        $token = ($token ?? null);
94
95
        Craft::$app->getView()->registerAssetBundle(SettingsAsset::class);
96
97
        return $this->renderTemplate('analytics/settings/_index', [
98
            'isOauthProviderConfigured' => $isOauthProviderConfigured,
99
100
            'errors' => $errors ?? null,
101
            'oauthAccount' => $oauthAccount ?? null,
102
            'provider' => $provider ?? null,
103
            'settings' => $settings ?? null,
104
            'token' => $token ?? null,
105
106
            'javascriptOrigin' => Analytics::$plugin->oauth->getJavascriptOrigin(),
107
            'redirectUri' => Analytics::$plugin->oauth->getRedirectUri(),
108
            'googleIconUrl' => Craft::$app->assetManager->getPublishedUrl('@dukt/analytics/icons/google.svg', true),
109
        ]);
110
    }
111
112
    /**
113
     * OAuth Settings.
114
     *
115
     * @return Response
116
     * @throws \craft\errors\SiteNotFoundException
117
     */
118
    public function actionOauth(): Response
119
    {
120
        return $this->renderTemplate('analytics/settings/_oauth', [
121
            'javascriptOrigin' => Analytics::$plugin->oauth->getJavascriptOrigin(),
122
            'redirectUri' => Analytics::$plugin->oauth->getRedirectUri(),
123
            'googleIconUrl' => Craft::$app->assetManager->getPublishedUrl('@dukt/analytics/icons/google.svg', true),
124
            'settings' => Analytics::$plugin->getSettings(),
125
        ]);
126
    }
127
128
    /**
129
     * Saves the settings.
130
     *
131
     * @return null|Response
132
     * @throws InvalidPluginException
133
     * @throws \yii\web\BadRequestHttpException
134
     */
135
    public function actionSaveSettings()
136
    {
137
        $this->requirePostRequest();
138
139
        $pluginHandle = Craft::$app->getRequest()->getRequiredBodyParam('pluginHandle');
140
        $settings = Craft::$app->getRequest()->getBodyParam('settings');
141
142
        $plugin = Craft::$app->getPlugins()->getPlugin($pluginHandle);
0 ignored issues
show
Bug introduced by
It seems like $pluginHandle can also be of type array; however, parameter $handle of craft\services\Plugins::getPlugin() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

142
        $plugin = Craft::$app->getPlugins()->getPlugin(/** @scrutinizer ignore-type */ $pluginHandle);
Loading history...
143
144
        if (!$plugin)
145
        {
146
            throw new InvalidPluginException($pluginHandle);
0 ignored issues
show
Bug introduced by
It seems like $pluginHandle can also be of type array; however, parameter $handle of craft\errors\InvalidPluginException::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

146
            throw new InvalidPluginException(/** @scrutinizer ignore-type */ $pluginHandle);
Loading history...
147
        }
148
149
        $settings = Analytics::$plugin->getApis()->getAnalytics()->populateAccountExplorerSettings($settings);
0 ignored issues
show
Bug introduced by
It seems like $settings can also be of type string; however, parameter $settings of dukt\analytics\apis\Anal...countExplorerSettings() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

149
        $settings = Analytics::$plugin->getApis()->getAnalytics()->populateAccountExplorerSettings(/** @scrutinizer ignore-type */ $settings);
Loading history...
150
151
        if (Craft::$app->getPlugins()->savePluginSettings($plugin, $settings))
152
        {
153
            Craft::$app->getSession()->setNotice(Craft::t('analytics', 'Plugin settings saved.'));
154
155
            return $this->redirectToPostedUrl();
156
        }
157
158
        Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save plugin settings.'));
159
160
        // Send the plugin back to the template
161
        Craft::$app->getUrlManager()->setRouteParams([
162
            'plugin' => $plugin
163
        ]);
164
165
        return null;
166
    }
167
168
    /**
169
     * Returns the account explorer data.
170
     *
171
     * @return Response
172
     */
173
    public function actionGetAccountExplorerData(): Response
174
    {
175
        $accountExplorerData = Analytics::$plugin->getApis()->getAnalytics()->getAccountExplorerData();
176
177
        Analytics::$plugin->cache->set(['accountExplorerData'], $accountExplorerData);
178
179
        return $this->asJson($accountExplorerData);
180
    }
181
182
    /**
183
     * Views index.
184
     *
185
     * @return Response
186
     */
187
    public function actionViews(): Response
188
    {
189
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
190
191
        $variables['isConnected'] = 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...
192
193
        try {
194
            $token = Analytics::$plugin->oauth->getToken();
195
196
            if($isOauthProviderConfigured && $token) {
197
                $variables['isConnected'] = true;
198
                $variables['reportingViews'] = Analytics::$plugin->getViews()->getViews();
199
            }
200
        } catch (IdentityProviderException $e) {
201
            $variables['error'] = $e->getMessage();
202
203
            $data = $e->getResponseBody();
204
205
            if (isset($data['error_description'])) {
206
                $variables['error'] = $data['error_description'];
207
            }
208
        }
209
210
        return $this->renderTemplate('analytics/settings/views/_index', $variables);
211
    }
212
213
    /**
214
     * Edit a view.
215
     *
216
     * @param int|null  $viewId
217
     * @param View|null $reportingView
218
     *
219
     * @return Response
220
     * @throws NotFoundHttpException
221
     * @throws \craft\errors\SiteNotFoundException
222
     * @throws \yii\base\InvalidConfigException
223
     */
224
    public function actionEditView(int $viewId = null, View $reportingView = null): Response
225
    {
226
        $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...
227
228
        if ($viewId !== null) {
229
            if ($reportingView === null) {
230
                $reportingView = Analytics::$plugin->getViews()->getViewById($viewId);
231
232
                if (!$reportingView) {
233
                    throw new NotFoundHttpException('View not found');
234
                }
235
            }
236
237
            $variables['title'] = $reportingView->name;
238
            $variables['reportingView'] = $reportingView;
239
        } else {
240
            if ($reportingView === null) {
241
                $reportingView = new View();
242
                $variables['isNewView'] = true;
243
            }
244
            $variables['title'] = Craft::t('analytics', 'Create a new view');
245
        }
246
247
        $variables['reportingView'] = $reportingView;
248
249
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
250
251
        if($isOauthProviderConfigured) {
252
            $errors = [];
253
254
            try {
255
                $plugin = Craft::$app->getPlugins()->getPlugin('analytics');
256
257
                $provider = Analytics::$plugin->oauth->getOauthProvider();
258
                $token = Analytics::$plugin->oauth->getToken();
259
260
                if ($token) {
261
                    $oauthAccount = Analytics::$plugin->cache->get(['getAccount', $token]);
262
263
                    if (!$oauthAccount) {
264
                        $oauthAccount = $provider->getResourceOwner($token);
265
                        Analytics::$plugin->cache->set(['getAccount', $token], $oauthAccount);
266
                    }
267
268
                    if ($oauthAccount) {
269
                        Craft::info("Account:\r\n".print_r($oauthAccount, true), __METHOD__);
270
271
                        $settings = $plugin->getSettings();
272
273
274
                        // Account explorer options
275
276
                        $accountExplorerData = Analytics::$plugin->cache->get(['accountExplorerData']);
277
278
                        $accountOptions = $this->getAccountOptions($accountExplorerData, $reportingView);
279
                        $propertyOptions = $this->getPropertyOptions($accountExplorerData, $reportingView);
280
                        $viewOptions = $this->getViewOptions($accountExplorerData, $reportingView);
281
282
                        $accountExplorerOptions = [
283
                            'accounts' => $accountOptions,
284
                            'properties' => $propertyOptions,
285
                            'views' => $viewOptions,
286
                        ];
287
288
                        $accountId = $settings->accountId;
289
                        $webPropertyId = $settings->webPropertyId;
290
                        $googleAnalyticsviewId = $settings->profileId;
291
                    }
292
                }
293
            } catch (\Google_Service_Exception $e) {
294
                Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
295
296
                foreach ($e->getErrors() as $error) {
297
                    array_push($errors, $error['message']);
298
                }
299
            } catch (\Exception $e) {
300
                if (method_exists($e, 'getResponse')) {
301
                    Craft::info('Couldn’t get OAuth account: '.$e->getResponse(), __METHOD__);
302
                } else {
303
                    Craft::info('Couldn’t get OAuth account: '.$e->getMessage(), __METHOD__);
304
                }
305
306
                array_push($errors, $e->getMessage());
307
            }
308
        }
309
310
        $token = ($token ?? null);
311
312
        Craft::$app->getView()->registerAssetBundle(SettingsAsset::class);
313
314
        $variables['isOauthProviderConfigured'] = $isOauthProviderConfigured;
315
        $variables['accountExplorerData'] = ($accountExplorerData ?? null);
316
        $variables['accountExplorerOptions'] = ($accountExplorerOptions ?? null);
317
        $variables['accountId'] = ($accountId ?? null);
318
        $variables['errors'] = ($errors ?? null);
319
        $variables['oauthAccount'] = ($oauthAccount ?? null);
320
        $variables['provider'] = ($provider ?? null);
321
        $variables['settings'] = ($settings ?? null);
322
        $variables['token'] = ($token ?? null);
323
        $variables['viewId'] = ($googleAnalyticsviewId ?? null);
324
        $variables['webPropertyId'] = ($webPropertyId ?? null);
325
326
        $variables['javascriptOrigin'] = Analytics::$plugin->oauth->getJavascriptOrigin();
327
        $variables['redirectUri'] = Analytics::$plugin->oauth->getRedirectUri();
328
        $variables['googleIconUrl'] = Craft::$app->assetManager->getPublishedUrl('@dukt/analytics/icons/google.svg', true);
329
330
        return $this->renderTemplate('analytics/settings/views/_edit', $variables);
331
    }
332
333
    /**
334
     * Saves a view.
335
     *
336
     * @return null|Response
337
     * @throws \dukt\analytics\errors\InvalidViewException
338
     * @throws \yii\web\BadRequestHttpException
339
     */
340
    public function actionSaveView()
341
    {
342
        $this->requirePostRequest();
343
344
        $reportingView = new View();
345
346
        // Set the simple stuff
347
        $request = Craft::$app->getRequest();
348
        $reportingView->id = $request->getBodyParam('viewId');
349
        $reportingView->name = $request->getBodyParam('name');
0 ignored issues
show
Documentation Bug introduced by
It seems like $request->getBodyParam('name') can also be of type array. However, the property $name is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
350
351
        $accountExplorer = $request->getBodyParam('accountExplorer');
352
353
        $reportingView->gaAccountId = $accountExplorer['account'];
354
        $reportingView->gaPropertyId = $accountExplorer['property'];
355
        $reportingView->gaViewId = $accountExplorer['view'];
356
357
358
        $accountExplorerData = Analytics::$plugin->getApis()->getAnalytics()->getAccountExplorerData();
359
360
        foreach($accountExplorerData['accounts'] as $dataAccount) {
361
            if($dataAccount['id'] == $reportingView->gaAccountId) {
362
                $reportingView->gaAccountName = $dataAccount['name'];
363
            }
364
        }
365
366
        foreach($accountExplorerData['properties'] as $dataProperty) {
367
            if($dataProperty['id'] == $reportingView->gaPropertyId) {
368
                $reportingView->gaPropertyName = $dataProperty['name'];
369
            }
370
        }
371
        foreach($accountExplorerData['views'] as $dataView) {
372
            if($dataView['id'] == $reportingView->gaViewId) {
373
                $reportingView->gaViewName = $dataView['name'];
374
                $reportingView->gaViewCurrency = $dataView['currency'];
375
            }
376
        }
377
378
        // Save it
379
        if (!Analytics::$plugin->getViews()->saveView($reportingView)) {
380
            Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save the view.'));
381
382
            // Send the view back to the template
383
            Craft::$app->getUrlManager()->setRouteParams([
384
                'reportingView' => $reportingView
385
            ]);
386
387
            return null;
388
        }
389
390
        Craft::$app->getSession()->setNotice(Craft::t('analytics', 'View saved.'));
391
392
        return $this->redirectToPostedUrl($reportingView);
393
    }
394
395
    /**
396
     * Deletes a view.
397
     *
398
     * @return Response
399
     * @throws \Throwable
400
     * @throws \yii\db\StaleObjectException
401
     * @throws \yii\web\BadRequestHttpException
402
     */
403
    public function actionDeleteView(): Response
404
    {
405
        $this->requirePostRequest();
406
        $this->requireAcceptsJson();
407
408
        $request = Craft::$app->getRequest();
409
        $viewId = $request->getRequiredBodyParam('id');
410
411
        Analytics::$plugin->getViews()->deleteViewById($viewId);
412
413
        return $this->asJson(['success' => true]);
414
    }
415
416
    /**
417
     * Sites index.
418
     *
419
     * @return Response
420
     */
421
    public function actionSites(): Response
422
    {
423
        $isOauthProviderConfigured = Analytics::$plugin->getAnalytics()->isOauthProviderConfigured();
424
425
        $variables['isConnected'] = 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...
426
427
        try {
428
            $token = Analytics::$plugin->oauth->getToken();
429
430
            if ($isOauthProviderConfigured && $token) {
431
                $variables['isConnected'] = true;
432
                $variables['sites'] = Craft::$app->getSites()->getAllSites();
433
                $variables['siteViews'] = Analytics::$plugin->getViews()->getSiteViews();
434
            }
435
        } catch (IdentityProviderException $e) {
436
            $variables['error'] = $e->getMessage();
437
438
            $data = $e->getResponseBody();
439
440
            if (isset($data['error_description'])) {
441
                $variables['error'] = $data['error_description'];
442
            }
443
        }
444
445
        return $this->renderTemplate('analytics/settings/sites/_index', $variables);
446
    }
447
448
    /**
449
     * Edit a site.
450
     *
451
     * @param $siteId
452
     *
453
     * @return Response
454
     */
455
    public function actionEditSite($siteId): Response
456
    {
457
        $site = Craft::$app->getSites()->getSiteById($siteId);
458
        $siteView = Analytics::$plugin->getViews()->getSiteViewBySiteId($siteId);
459
        $reportingViews = Analytics::$plugin->getViews()->getViews();
460
461
        return $this->renderTemplate('analytics/settings/sites/_edit', [
462
            'site' => $site,
463
            'siteView' => $siteView,
464
            'reportingViews' => $reportingViews,
465
        ]);
466
    }
467
468
    /**
469
     * Saves a site.
470
     *
471
     * @return null|Response
472
     * @throws \yii\db\Exception
473
     * @throws \yii\web\BadRequestHttpException
474
     */
475
    public function actionSaveSite()
476
    {
477
        $this->requirePostRequest();
478
479
        $siteView = new SiteView();
480
481
        // Set the simple stuff
482
        $request = Craft::$app->getRequest();
483
        $siteView->siteId = $request->getBodyParam('siteId');
484
        $siteView->viewId = $request->getBodyParam('viewId');
485
486
        // Save it
487
        if (!Analytics::$plugin->getViews()->saveSiteView($siteView)) {
488
            Craft::$app->getSession()->setError(Craft::t('analytics', 'Couldn’t save the site view.'));
489
490
            // Send the view back to the template
491
            Craft::$app->getUrlManager()->setRouteParams([
492
                'siteView' => $siteView
493
            ]);
494
495
            return null;
496
        }
497
498
        Craft::$app->getSession()->setNotice(Craft::t('analytics', 'Site view saved.'));
499
500
        return $this->redirectToPostedUrl($siteView);
501
    }
502
503
    /**
504
     * @param      $accountExplorerData
505
     * @param View $reportingView
506
     *
507
     * @return array
508
     */
509
    private function getAccountOptions($accountExplorerData, View $reportingView): array
510
    {
511
        $accountOptions = [];
512
513
        if (isset($accountExplorerData['accounts'])) {
514
            foreach ($accountExplorerData['accounts'] as $account) {
515
                $accountOptions[] = ['label' => $account['name'], 'value' => $account['id']];
516
            }
517
        } else {
518
            $accountOptions[] = ['label' => $reportingView->gaAccountName, 'value' => $reportingView->gaAccountId];
519
        }
520
521
        return $accountOptions;
522
    }
523
524
    /**
525
     * @param      $accountExplorerData
526
     * @param View $reportingView
527
     *
528
     * @return array
529
     */
530
    private function getPropertyOptions($accountExplorerData, View $reportingView): array
531
    {
532
        $propertyOptions = [];
533
534
        if (isset($accountExplorerData['properties'])) {
535
            foreach ($accountExplorerData['properties'] as $webProperty) {
536
                $propertyOptions[] = ['label' => $webProperty['name'], 'value' => $webProperty['id']];
537
            }
538
        } else {
539
            $propertyOptions[] = ['label' => $reportingView->gaPropertyName, 'value' => $reportingView->gaPropertyId];
540
        }
541
542
        return $propertyOptions;
543
    }
544
545
    /**
546
     * @param      $accountExplorerData
547
     * @param View $reportingView
548
     *
549
     * @return array
550
     */
551
    private function getViewOptions($accountExplorerData, View $reportingView): array
552
    {
553
        $viewOptions = [];
554
555
        if (isset($accountExplorerData['views'])) {
556
            foreach ($accountExplorerData['views'] as $dataView) {
557
                $viewOptions[] = ['label' => $dataView['name'], 'value' => $dataView['id']];
558
            }
559
        } else {
560
            $viewOptions[] = ['label' => $reportingView->gaViewName, 'value' => $reportingView->gaViewId];
561
        }
562
563
        return $viewOptions;
564
    }
565
}