Visitor::syncFromHubSpot()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 0
cts 33
cp 0
rs 9.216
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 20
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/hubspot/license
6
 * @link       https://www.flipboxfactory.com/software/hubspot/
7
 */
8
9
namespace flipbox\craft\hubspot\services;
10
11
use Craft;
12
use craft\helpers\Json;
13
use flipbox\craft\hubspot\criteria\ContactCriteria;
14
use flipbox\craft\hubspot\events\PrepVisitorDataFromHubSpotEvent;
15
use flipbox\craft\hubspot\HubSpot;
16
use flipbox\craft\hubspot\queue\SaveVisitor;
17
use flipbox\craft\hubspot\records\Visitor as VisitorRecord;
18
use yii\base\Component;
19
use yii\base\Exception;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.1.0
24
 */
25
class Visitor extends Component
26
{
27
    const COOKIE_NAME = 'hubspotutk';
28
29
    /**
30
     * @return string|null
31
     */
32
    public function findTokenValue()
33
    {
34
        return $_COOKIE[self::COOKIE_NAME] ?? null;
35
    }
36
37
    /**
38
     * @param string|null $connection
39
     * @return VisitorRecord|null
40
     */
41
    public function findRecord(string $connection = null)
42
    {
43
        if (null === ($token = $this->findTokenValue())) {
44
            HubSpot::info("Visitor token was not found.");
45
            return null;
46
        }
47
48
        return VisitorRecord::findOrCreate($token, $connection);
49
    }
50
51
    /**
52
     * @param bool $toQueue
53
     * @param string|null $connection
54
     * @return mixed|null
55
     */
56
    public function findContact(bool $toQueue = true, string $connection = null)
57
    {
58
        if (null === ($record = $this->findRecord($connection))) {
59
            return null;
60
        }
61
62
        if ($record->status !== VisitorRecord::STATUS_SUCCESSFUL) {
63
            // If new, save now so we can reference later
64
            if ($record->getIsNewRecord()) {
65
                $record->save();
66
            }
67
68
            if ($record->status === VisitorRecord::STATUS_PENDING) {
69
                $this->syncVisitor($record, $toQueue);
70
            }
71
72
            // It's possible the sync operation was run immediately
73
            if ($record->status !== VisitorRecord::STATUS_SUCCESSFUL) {
74
                HubSpot::info(sprintf(
75
                    "Visitor record status is '%s' and is not 'completed'; nothing to return.",
76
                    $record->status
77
                ));
78
                return null;
79
            }
80
        }
81
82
        return Json::decodeIfJson(
83
            $record->contact
84
        );
85
    }
86
    
87
    /**
88
     * @param VisitorRecord $record
89
     * @param bool $toQueue
90
     */
91
    public function syncVisitor(VisitorRecord $record, bool $toQueue = true)
92
    {
93
        if ($toQueue === true && $record->inQueue()) {
94
            HubSpot::warning("Queue Job already exists; ignoring.");
95
            return;
96
        }
97
98
        $toQueue === true ? $this->syncViaQueue($record) : $this->syncImmediately($record);
99
    }
100
101
    /**
102
     * @param VisitorRecord $record
103
     */
104
    protected function syncViaQueue(VisitorRecord $record)
105
    {
106
        Craft::$app->getQueue()->push(
107
            new SaveVisitor([
108
                'token' => $record->token,
109
                'connection' => $record->connection
110
            ])
111
        );
112
113
        HubSpot::info("Added Queue Job to sync Visitor from HubSpot");
114
    }
115
116
    /**
117
     * @param VisitorRecord $record
118
     */
119
    protected function syncImmediately(VisitorRecord $record)
120
    {
121
        try {
122
            $this->syncFromHubSpot($record);
123
        } catch (\Exception $e) {
124
            HubSpot::error(
125
                sprintf(
126
                    "Exception caught while trying to sync visitor. Exception: [%s].",
127
                    (string)Json::encode([
128
                        'Trace' => $e->getTraceAsString(),
129
                        'File' => $e->getFile(),
130
                        'Line' => $e->getLine(),
131
                        'Code' => $e->getCode(),
132
                        'Message' => $e->getMessage()
133
                    ])
134
                ),
135
                __METHOD__
136
            );
137
        }
138
    }
139
140
    /**
141
     * @param VisitorRecord $record
142
     * @throws \Exception
143
     */
144
    public function syncFromHubSpot(VisitorRecord $record)
145
    {
146
        // Only process 'pending'
147
        if ($record->status !== VisitorRecord::STATUS_PENDING) {
148
            return;
149
        }
150
151
        $result = (new ContactCriteria())
152
            ->setId($record->token)
153
            ->setConnection($record->connection)
154
            ->read();
155
156
        // Contact doesn't exist.  A known response
157
        if ($result->getStatusCode() === 404) {
158
            $record->status = VisitorRecord::STATUS_NOT_FOUND;
159
            $record->save();
160
            return;
161
        }
162
163
        // Not sure what happened.
164
        if ($result->getStatusCode() !== 200) {
165
            $record->status = VisitorRecord::STATUS_ERROR;
166
            $record->save();
167
168
            throw new Exception(sprintf(
169
                "Failed to save visitor '%s' due to the following errors: %s:",
170
                $record->token,
171
                $result->getBody()->getContents()
172
            ));
173
        }
174
175
        $event = new PrepVisitorDataFromHubSpotEvent([
176
            'contact' => Json::decodeIfJson(
177
                $result->getBody()->getContents()
178
            )
179
        ]);
180
181
        $record->trigger($event::EVENT_NAME, $event);
182
183
        $record->contact = $event->contact;
184
        $record->status = VisitorRecord::STATUS_SUCCESSFUL;
185
186
        $record->save();
187
    }
188
}
189