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
![]() |
|||||
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
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
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. ![]() |
|||||
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
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
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. ![]() |
|||||
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
|
|||||
214 | |||||
215 | if ($viewId !== null) { |
||||
216 | if ($reportingView === null) { |
||||
217 | $reportingView = Analytics::$plugin->getViews()->getViewById($viewId); |
||||
218 | |||||
219 | if (!$reportingView) { |
||||
0 ignored issues
–
show
|
|||||
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 | } |