Passed
Pull Request — develop (#4)
by
unknown
03:21
created

InstantAnalytics::sendPageView()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 33
rs 8.9617
c 0
b 0
f 0
cc 6
nc 4
nop 0
1
<?php
2
/**
3
 * Instant Analytics plugin for Craft CMS 3.x
4
 *
5
 * Instant Analytics brings full Google Analytics support to your Twig templates
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2017 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\instantanalytics;
12
13
use nystudio107\instantanalytics\helpers\IAnalytics;
14
use nystudio107\instantanalytics\helpers\Field as FieldHelper;
15
use nystudio107\instantanalytics\models\Settings;
16
use nystudio107\instantanalytics\services\Commerce as CommerceService;
17
use nystudio107\instantanalytics\services\IA as IAService;
18
use nystudio107\instantanalytics\variables\InstantAnalyticsVariable;
19
use nystudio107\instantanalytics\twigextensions\InstantAnalyticsTwigExtension;
20
21
use Craft;
22
use craft\base\Plugin;
23
use craft\events\PluginEvent;
24
use craft\events\RegisterUrlRulesEvent;
25
use craft\events\TemplateEvent;
26
use craft\fields\Categories;
27
use craft\fields\PlainText;
28
use craft\fields\RichText;
0 ignored issues
show
Bug introduced by
The type craft\fields\RichText was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use craft\fields\Redactor;
0 ignored issues
show
Bug introduced by
The type craft\fields\Redactor was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use craft\fields\Tags;
31
use craft\helpers\UrlHelper;
32
use craft\services\Plugins;
33
use craft\web\twig\variables\CraftVariable;
34
use craft\web\UrlManager;
35
use craft\web\View;
36
37
use craft\commerce\Plugin as Commerce;
0 ignored issues
show
Bug introduced by
The type craft\commerce\Plugin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
use craft\commerce\elements\Order;
0 ignored issues
show
Bug introduced by
The type craft\commerce\elements\Order was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
40
use nystudio107\seomatic\Seomatic;
0 ignored issues
show
Bug introduced by
The type nystudio107\seomatic\Seomatic was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
41
42
use yii\base\Event;
43
use yii\base\Exception;
44
45
/** @noinspection MissingPropertyAnnotationsInspection */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
46
47
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
48
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 4
Loading history...
49
 * @package   InstantAnalytics
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
50
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 3 spaces but found 5
Loading history...
51
 *
52
 * @property  IAService       $ia
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
53
 * @property  CommerceService $commerce
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
54
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
55
class InstantAnalytics extends Plugin
56
{
57
    // Constants
58
    // =========================================================================
59
60
    const COMMERCE_PLUGIN_HANDLE = 'commerce';
61
    const SEOMATIC_PLUGIN_HANDLE = 'seomatic';
62
63
    // Static Properties
64
    // =========================================================================
65
66
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
67
     * @var InstantAnalytics
68
     */
69
    public static $plugin;
70
71
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
72
     * @var Plugin|null
73
     */
74
    public static $commercePlugin;
75
76
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
77
     * @var Plugin|null
78
     */
79
    public static $seomaticPlugin;
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
82
     * @var string
83
     */
84
    public static $currentTemplate = '';
85
86
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
87
     * @var bool
88
     */
89
    public static $pageViewSent = false;
90
91
    // Public Methods
92
    // =========================================================================
93
94
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
95
     * @inheritdoc
96
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
97
    public function init()
98
    {
99
        parent::init();
100
        self::$plugin = $this;
101
102
        // Determine if Craft Commerce is installed & enabled
103
        self::$commercePlugin = Craft::$app->getPlugins()->getPlugin(self::COMMERCE_PLUGIN_HANDLE);
104
        // Determine if SEOmatic is installed & enabled
105
        self::$seomaticPlugin = Craft::$app->getPlugins()->getPlugin(self::SEOMATIC_PLUGIN_HANDLE);
106
        // Add in our Craft components
107
        $this->addComponents();
108
        // Install our global event handlers
109
        $this->installEventListeners();
110
111
        Craft::info(
112
            Craft::t(
113
                'instant-analytics',
114
                '{name} plugin loaded',
115
                ['name' => $this->name]
116
            ),
117
            __METHOD__
118
        );
119
    }
120
121
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
122
     * @inheritdoc
123
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
124
    public function settingsHtml()
125
    {
126
        $commerceFields = [];
127
128
        if (self::$commercePlugin) {
129
             $productTypes = Commerce::getInstance()->getProductTypes()->getAllProductTypes();
130
131
             foreach ($productTypes as $productType) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 13
Loading history...
132
                 $productFields = $this->_getPullFieldsFromLayoutId($productType->fieldLayoutId);
133
                 $commerceFields = array_merge($commerceFields, $productFields);
134
                 
135
                 if ($productType->hasVariants) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 17
Loading history...
136
                     $variantFields = $this->_getPullFieldsFromLayoutId($productType->variantFieldLayoutId);
137
                     $commerceFields = array_merge($commerceFields, $variantFields);
138
                 }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 17
Loading history...
139
             }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 13
Loading history...
140
        }
141
142
        // Rend the settings template
143
        try {
144
            return Craft::$app->getView()->renderTemplate(
145
                'instant-analytics/settings',
146
                [
147
                    'settings'       => $this->getSettings(),
148
                    'commerceFields' => $commerceFields,
149
                ]
150
            );
151
        } catch (\Twig_Error_Loader $e) {
152
            Craft::error($e->getMessage(), __METHOD__);
153
        } catch (Exception $e) {
154
            Craft::error($e->getMessage(), __METHOD__);
155
        }
156
157
        return '';
158
    }
159
160
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $context should have a doc-comment as per coding-style.
Loading history...
161
     * Handle the `{% hook isSendPageView %}`
162
     *
163
     * @param array &$context
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter &$context does not match actual variable name $context
Loading history...
164
     *
165
     * @return string|null
166
     */
167
    public function iaSendPageView(/** @noinspection PhpUnusedParameterInspection */ array &$context)
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
168
    {
169
        $this->sendPageView();
170
171
        return '';
172
    }
173
174
    // Protected Methods
175
    // =========================================================================
176
177
    /**
178
     * Add in our Craft components
179
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
180
    protected function addComponents()
181
    {
182
        $view = Craft::$app->getView();
183
        // Add in our Twig extensions
184
        $view->registerTwigExtension(new InstantAnalyticsTwigExtension());
185
        // Install our template hook
186
        $view->hook('iaSendPageView', [$this, 'iaSendPageView']);
187
        // Register our variables
188
        Event::on(
189
            CraftVariable::class,
190
            CraftVariable::EVENT_INIT,
191
            function (Event $event) {
192
                /** @var CraftVariable $variable */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
193
                $variable = $event->sender;
194
                $variable->set('instantAnalytics', InstantAnalyticsVariable::class);
195
            }
196
        );
197
    }
198
199
    /**
200
     * Install our event listeners
201
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
202
    protected function installEventListeners()
203
    {
204
        // Handler: Plugins::EVENT_AFTER_INSTALL_PLUGIN
205
        Event::on(
206
            Plugins::class,
207
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
208
            function (PluginEvent $event) {
209
                if ($event->plugin === $this) {
210
                    $request = Craft::$app->getRequest();
211
                    if ($request->isCpRequest) {
212
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('instant-analytics/welcome'))->send();
213
                    }
214
                }
215
            }
216
        );
217
        $request = Craft::$app->getRequest();
218
        // Install only for non-console site requests
219
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
220
            $this->installSiteEventListeners();
221
        }
222
        // Install only for non-console AdminCP requests
223
        if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
224
            $this->installCpEventListeners();
225
        }
226
    }
227
228
    /**
229
     * Install site event listeners for site requests only
230
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
231
    protected function installSiteEventListeners()
232
    {
233
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
234
        Event::on(
235
            UrlManager::class,
236
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
237
            function (RegisterUrlRulesEvent $event) {
238
                Craft::debug(
239
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
240
                    __METHOD__
241
                );
242
                // Register our AdminCP routes
243
                $event->rules = array_merge(
244
                    $event->rules,
245
                    $this->customFrontendRoutes()
246
                );
247
            }
248
        );
249
        // Remember the name of the currently rendering template
250
        Event::on(
251
            View::class,
252
            View::EVENT_BEFORE_RENDER_PAGE_TEMPLATE,
253
            function (TemplateEvent $event) {
254
                self::$currentTemplate = $event->template;
255
            }
256
        );
257
        // Remember the name of the currently rendering template
258
        Event::on(
259
            View::class,
260
            View::EVENT_AFTER_RENDER_PAGE_TEMPLATE,
261
            function (TemplateEvent $event) {
262
                $settings = InstantAnalytics::$plugin->getSettings();
263
                if ($settings->autoSendPageView) {
264
                    $this->sendPageView();
265
                }
266
            }
267
        );
268
        // Commerce-specific hooks
269
        if (self::$commercePlugin) {
270
271
            Event::on(Order::class, Order::EVENT_AFTER_COMPLETE_ORDER, function(Event $e) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
272
                $order = $e->sender;
273
                $settings = InstantAnalytics::$plugin->getSettings();
274
275
                if ($settings->autoSendPurchaseComplete) {
276
                    $this->commerce->orderComplete($order);
277
                }
278
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
279
280
            Event::on(Order::class, Order::EVENT_AFTER_ADD_LINE_ITEM, function(Event $e) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
281
                $lineItem = $e->lineItem;
282
283
                $settings = InstantAnalytics::$plugin->getSettings();
284
                
285
                if ($settings->autoSendAddToCart) {
286
                    $this->commerce->addToCart($lineItem->order, $lineItem);
287
                }
288
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
289
290
            Event::on(Order::class, Order::EVENT_AFTER_REMOVE_LINE_ITEM, function(Event $e) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
291
                $lineItem = $e->lineItem;
292
293
                $settings = InstantAnalytics::$plugin->getSettings();
294
                
295
                if ($settings->autoSendRemoveFromCart) {
296
                    $this->commerce->removeFromCart($lineItem->order, $lineItem);
297
                }
298
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
299
        }
300
    }
301
302
    /**
303
     * Install site event listeners for AdminCP requests only
304
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
305
    protected function installCpEventListeners()
306
    {
307
    }
308
309
    /**
310
     * Return the custom frontend routes
311
     *
312
     * @return array
313
     */
314
    protected function customFrontendRoutes(): array
315
    {
316
        return [
317
            'instantanalytics/pageViewTrack/<filename:[-\w\.*]+>?' =>
318
                'instant-analytics/track/track-page-view-url',
319
            'instantanalytics/eventTrack/<filename:[-\w\.*]+>?' =>
320
                'instant-analytics/track/track-event-url',
321
        // Make webpack async bundle loading work out of published AssetBundles
322
            '/cpresources/instant-analytics/<resourceType:{handle}>/<fileName>' => 'instant-analytics/manifest/resource',
323
        ];
324
    }
325
326
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
327
     * @inheritdoc
328
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
329
    protected function createSettingsModel()
330
    {
331
        return new Settings();
332
    }
333
334
    // Private Methods
335
    // =========================================================================
336
337
    /**
338
     * Send a page view with the pre-loaded IAnalytics object
339
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
340
    private function sendPageView()
0 ignored issues
show
Coding Style introduced by
Private method name "InstantAnalytics::sendPageView" must be prefixed with an underscore
Loading history...
341
    {
342
        $request = Craft::$app->getRequest();
343
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest() && !self::$pageViewSent) {
344
            self::$pageViewSent = true;
345
            /** @var IAnalytics $analytics */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
346
            $analytics = InstantAnalytics::$plugin->ia->getGlobals(self::$currentTemplate);
347
            // Bail if we have no analytics object
348
            if ($analytics === null) {
349
                return;
350
            }
351
            // If SEOmatic is installed, set the page title from it
352
            $this->setTitleFromSeomatic($analytics);
353
            // Send the page view
354
            if ($analytics) {
0 ignored issues
show
introduced by
$analytics is of type nystudio107\instantanalytics\helpers\IAnalytics, thus it always evaluated to true.
Loading history...
355
                $response = $analytics->sendPageview();
356
                Craft::info(
357
                    Craft::t(
358
                        'instant-analytics',
359
                        'pageView sent, response:: {response}',
360
                        [
361
                            'response' => print_r($response, true),
362
                        ]
363
                    ),
364
                    __METHOD__
365
                );
366
            } else {
367
                Craft::error(
368
                    Craft::t(
369
                        'instant-analytics',
370
                        'Analytics not sent because googleAnalyticsTracking is not set'
371
                    ),
372
                    __METHOD__
373
                );
374
            }
375
        }
376
    }
377
378
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $analytics should have a doc-comment as per coding-style.
Loading history...
379
     * If SEOmatic is installed, set the page title from it
380
     *
381
     * @param $analytics
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
382
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
383
    private function setTitleFromSeomatic(IAnalytics $analytics)
0 ignored issues
show
Coding Style introduced by
Private method name "InstantAnalytics::setTitleFromSeomatic" must be prefixed with an underscore
Loading history...
384
    {
385
        if (self::$seomaticPlugin && Seomatic::$settings->renderEnabled) {
386
            $titleTag = Seomatic::$plugin->title->get('title');
387
            if ($titleTag) {
388
                $titleArray = $titleTag->renderAttributes();
389
                if (!empty($titleArray['title'])) {
390
                    $analytics->setDocumentTitle($titleArray['title']);
391
                }
392
            }
393
        }
394
    }
395
396
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $layoutId should have a doc-comment as per coding-style.
Loading history...
397
     * @return array
398
     */
399
    private function _getPullFieldsFromLayoutId($layoutId)
400
    {
401
        $result = ['' => "none"];
402
        $fieldLayout = Craft::$app->getFields()->getLayoutById($layoutId);
403
        $fieldLayoutFields = $fieldLayout->getFields();
404
        
405
        foreach ($fieldLayoutFields as $field) {            
406
            switch (get_class($field)) {
407
                case PlainText::class:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
408
                case RichText::class:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
409
                case Redactor::class:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
410
                case Categories::class:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
411
                    $result[$field->handle] = $field->name;
412
                    break;
413
                case Tags::class:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
414
                    break;
415
            }
416
        }
417
418
        return $result;
419
    }
420
}
421