Completed
Push — develop ( 9a2d03...4f224f )
by Nate
09:22
created

Visitor::syncImmediately()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 2
nc 2
nop 1
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
    protected function findTokenValue()
33
    {
34
        return $_COOKIE[self::COOKIE_NAME] ?? null;
35
    }
36
37
    /**
38
     * @param bool $toQueue
39
     * @param string|null $connection
40
     * @return mixed|null
41
     */
42
    public function findContact(bool $toQueue = true, string $connection = null)
43
    {
44
        if (null === ($token = $this->findTokenValue())) {
45
            HubSpot::info("Visitor token was not found.");
46
            return null;
47
        }
48
49
        $record = VisitorRecord::findOrCreate($token, $connection);
50
        if ($record->status !== VisitorRecord::STATUS_SUCCESSFUL) {
51
            // If new, save now so we can reference later
52
            if ($record->getIsNewRecord()) {
53
                $record->save();
54
            }
55
56
            if ($record->status === VisitorRecord::STATUS_PENDING) {
57
                $this->syncVisitor($record, $toQueue);
58
            }
59
60
            // It's possible the sync operation was run immediately
61
            if ($record->status !== VisitorRecord::STATUS_SUCCESSFUL) {
62
                HubSpot::info(sprintf(
63
                    "Visitor record status is '%s' and is not 'completed'; nothing to return.",
64
                    $record->status
65
                ));
66
                return null;
67
            }
68
        }
69
70
        return Json::decodeIfJson(
71
            $record->contact
72
        );
73
    }
74
75
    /**
76
     * @param VisitorRecord $record
77
     * @param bool $toQueue
78
     */
79
    public function syncVisitor(VisitorRecord $record, bool $toQueue = true)
80
    {
81
        if ($record->inQueue()) {
82
            HubSpot::warning("Queue Job already exists; ignoring.");
83
            return;
84
        }
85
86
        $toQueue === true ? $this->syncViaQueue($record) : $this->syncImmediately($record);
87
    }
88
89
    /**
90
     * @param VisitorRecord $record
91
     */
92
    protected function syncViaQueue(VisitorRecord $record)
93
    {
94
        Craft::$app->getQueue()->push(
95
            new SaveVisitor([
96
                'token' => $record->token,
97
                'connection' => $record->connection
98
            ])
99
        );
100
101
        HubSpot::info("Added Queue Job to sync Visitor from HubSpot");
102
        return;
103
    }
104
105
    /**
106
     * @param VisitorRecord $record
107
     */
108
    protected function syncImmediately(VisitorRecord $record)
109
    {
110
        try {
111
            $this->syncFromHubSpot($record);
112
        } catch (\Exception $e) {
113
            HubSpot::error(
114
                sprintf(
115
                    "Exception caught while trying to sync visitor. Exception: [%s].",
116
                    (string)Json::encode([
117
                        'Trace' => $e->getTraceAsString(),
118
                        'File' => $e->getFile(),
119
                        'Line' => $e->getLine(),
120
                        'Code' => $e->getCode(),
121
                        'Message' => $e->getMessage()
122
                    ])
123
                ),
124
                __METHOD__
125
            );
126
        }
127
    }
128
129
    /**
130
     * @param VisitorRecord $record
131
     * @throws \Exception
132
     */
133
    public function syncFromHubSpot(VisitorRecord $record)
134
    {
135
        // Only process 'pending'
136
        if ($record->status !== VisitorRecord::STATUS_PENDING) {
137
            return;
138
        }
139
140
        $result = (new ContactCriteria())
141
            ->setId($record->token)
142
            ->setConnection($record->connection)
143
            ->read();
144
145
        // Contact doesn't exist.  A known response
146
        if ($result->getStatusCode() === 404) {
147
            $record->status = VisitorRecord::STATUS_NOT_FOUND;
148
            $record->save();
149
            return;
150
        }
151
152
        // Not sure what happened.
153
        if ($result->getStatusCode() !== 200) {
154
            $record->status = VisitorRecord::STATUS_ERROR;
155
            $record->save();
156
157
            throw new Exception(sprintf(
158
                "Failed to save visitor '%s' due to the following errors: %s:",
159
                $record->token,
160
                $result->getBody()->getContents()
161
            ));
162
        }
163
164
        $event = new PrepVisitorDataFromHubSpotEvent([
165
            'contact' => Json::decodeIfJson(
166
                $result->getBody()->getContents()
167
            )
168
        ]);
169
170
        $record->trigger($event::EVENT_NAME, $event);
171
172
        $record->contact = $event->contact;
173
        $record->status = VisitorRecord::STATUS_SUCCESSFUL;
174
175
        $record->save();
176
    }
177
}
178