Completed
Push — develop ( f8c4bd...63ca71 )
by Nate
02:47
created

ObjectsField::baseQuery()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 0
cts 7
cp 0
rs 9.7666
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
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\hubspot\services;
10
11
use Craft;
12
use craft\base\ElementInterface;
13
use craft\base\FieldInterface;
14
use craft\helpers\Component as ComponentHelper;
15
use craft\helpers\StringHelper;
16
use flipbox\craft\sortable\associations\db\SortableAssociationQueryInterface;
17
use flipbox\craft\sortable\associations\records\SortableAssociationInterface;
18
use flipbox\craft\sortable\associations\services\SortableFields;
19
use flipbox\hubspot\db\ObjectAssociationQuery;
20
use flipbox\hubspot\events\RegisterResourceFieldActionsEvent;
21
use flipbox\hubspot\fields\actions\ObjectActionInterface;
22
use flipbox\hubspot\fields\actions\ObjectItemActionInterface;
23
use flipbox\hubspot\fields\Objects;
24
use flipbox\hubspot\HubSpot;
25
use flipbox\hubspot\records\ObjectAssociation;
26
use flipbox\hubspot\web\assets\resources\Resources as ObjectsFieldAsset;
27
use yii\base\Exception;
28
29
/**
30
 * @author Flipbox Factory <[email protected]>
31
 * @since 1.0.0
32
 */
33
class ObjectsField extends SortableFields
34
{
35
    /**
36
     * @inheritdoc
37
     */
38
    const SOURCE_ATTRIBUTE = ObjectAssociation::SOURCE_ATTRIBUTE;
39
40
    /**
41
     * @inheritdoc
42
     */
43
    const TARGET_ATTRIBUTE = ObjectAssociation::TARGET_ATTRIBUTE;
44
45
    /**
46
     * HubSpot Object Association fields, indexed by their Id.
47
     *
48
     * @var Objects[]
49
     */
50
    private $fields = [];
51
52
    /**
53
     * @inheritdoc
54
     */
55
    protected static function tableAlias(): string
56
    {
57
        return ObjectAssociation::tableAlias();
58
    }
59
60
    /**
61
     * @param int $id
62
     * @return Objects|null
63
     */
64
    public function findById(int $id)
65
    {
66
        if (!array_key_exists($id, $this->fields)) {
67
            $field = Craft::$app->getFields()->getFieldById($id);
68
            if (!$field instanceof Objects) {
69
                $field = null;
70
            }
71
72
            $this->fields[$id] = $field;
73
        }
74
75
        return $this->fields[$id];
76
    }
77
78
    /**
79
     * @inheritdoc
80
     * @return ObjectAssociationQuery
81
     * @throws Exception
82
     */
83
    protected function getQuery(
84
        FieldInterface $field,
85
        ElementInterface $element = null
86
    ): SortableAssociationQueryInterface {
87
        $query = $this->baseQuery($field, $element);
88
89
        /** @var Objects $field */
90
91
        if ($field->max !== null) {
92
            $query->limit($field->max);
93
        }
94
95
        return $query;
96
    }
97
98
    /**
99
     * @param FieldInterface $field
100
     * @param ElementInterface|null $element
101
     * @return ObjectAssociationQuery
102
     * @throws Exception
103
     */
104
    private function baseQuery(
105
        FieldInterface $field,
106
        ElementInterface $element = null
107
    ): ObjectAssociationQuery {
108
        /** @var Objects $field */
109
        $this->ensureField($field);
110
111
        $query = HubSpot::getInstance()->getObjectAssociations()->getQuery()
112
            ->field($field->id)
113
            ->site($this->targetSiteId($element));
114
115
        $query->{ObjectAssociation::SOURCE_ATTRIBUTE} = $element === null ? null : $element->getId();
116
117
        return $query;
118
    }
119
120
    /*******************************************
121
     * NORMALIZE VALUE
122
     *******************************************/
123
124
    /**
125
     * @inheritdoc
126
     * @throws Exception
127
     */
128
    protected function normalizeQueryInputValue(
129
        FieldInterface $field,
130
        $value,
131
        int &$sortOrder,
132
        ElementInterface $element = null
133
    ): SortableAssociationInterface {
134
        if (is_array($value)) {
135
            $value = StringHelper::toString($value);
136
        }
137
138
        $query = $this->baseQuery($field, $element)
139
            ->sortOrder($sortOrder++);
140
141
        $query->{ObjectAssociation::TARGET_ATTRIBUTE} = $value;
142
143
        return $query;
144
    }
145
146
    /**
147
     * @param FieldInterface $field
148
     * @throws Exception
149
     */
150
    private function ensureField(FieldInterface $field)
151
    {
152
        if (!$field instanceof Objects) {
153
            throw new Exception(sprintf(
154
                "The field must be an instance of '%s', '%s' given.",
155
                (string)Objects::class,
156
                (string)get_class($field)
157
            ));
158
        }
159
    }
160
161
162
    /**
163
     * @param Objects $field
164
     * @param ObjectAssociationQuery $query
165
     * @param ElementInterface|null $element
166
     * @param bool $static
167
     * @return null|string
168
     * @throws Exception
169
     * @throws \Twig_Error_Loader
170
     */
171
    public function getInputHtml(
172
        Objects $field,
173
        ObjectAssociationQuery $query,
174
        ElementInterface $element = null,
175
        bool $static = false
176
    ) {
177
        Craft::$app->getView()->registerAssetBundle(ObjectsFieldAsset::class);
178
179
        return Craft::$app->getView()->renderTemplate(
180
            'hubspot/_components/fieldtypes/Objects/input',
181
            [
182
                'field' => $field,
183
                'element' => $element,
184
                'value' => $query,
185
                'actions' => $this->getActionHtml($field, $element),
186
                'itemActions' => $this->getItemActionHtml($field, $element),
187
                'static' => $static
188
            ]
189
        );
190
    }
191
192
    /**
193
     * @param Objects $field
194
     * @return null|string
195
     * @throws Exception
196
     * @throws \Twig_Error_Loader
197
     */
198
    public function getSettingsHtml(
199
        Objects $field
200
    ) {
201
        return Craft::$app->getView()->renderTemplate(
202
            'hubspot/_components/fieldtypes/Objects/settings',
203
            [
204
                'field' => $field
205
            ]
206
        );
207
    }
208
209
210
    /*******************************************
211
     * ACTIONS
212
     *******************************************/
213
    /**
214
     * @param Objects $field
215
     * @param ElementInterface|null $element
216
     * @return ObjectActionInterface[]
217
     * @throws \craft\errors\MissingComponentException
218
     * @throws \yii\base\InvalidConfigException
219
     */
220
    public function getActions(Objects $field, ElementInterface $element = null): array
221
    {
222
        $actions = [];
223
224
        $event = new RegisterResourceFieldActionsEvent([
225
            'actions' => $actions,
226
            'element' => $element
227
        ]);
228
229
        $field->trigger(
230
            $field::EVENT_REGISTER_ACTIONS,
231
            $event
232
        );
233
234
        return $this->resolveActions($event->actions, ObjectActionInterface::class);
235
    }
236
237
    /**
238
     * @param Objects $field
239
     * @param ElementInterface|null $element
240
     * @return ObjectItemActionInterface[]
241
     * @throws \craft\errors\MissingComponentException
242
     * @throws \yii\base\InvalidConfigException
243
     */
244
    public function getItemActions(Objects $field, ElementInterface $element = null): array
245
    {
246
        $event = new RegisterResourceFieldActionsEvent([
247
            'actions' => [],
248
            'element' => $element
249
        ]);
250
251
        $field->trigger(
252
            $field::EVENT_REGISTER_ITEM_ACTIONS,
253
            $event
254
        );
255
256
        return $this->resolveActions($event->actions, ObjectItemActionInterface::class);
257
    }
258
259
    /**
260
     * @param array $actions
261
     * @param string $instance
262
     * @return array
263
     * @throws \craft\errors\MissingComponentException
264
     * @throws \yii\base\InvalidConfigException
265
     */
266
    protected function resolveActions(array $actions, string $instance)
267
    {
268
        foreach ($actions as $i => $action) {
269
            // $action could be a string or config array
270
            if (!$action instanceof $instance) {
271
                $actions[$i] = $action = ComponentHelper::createComponent($action, $instance);
272
273
                if ($actions[$i] === null) {
274
                    unset($actions[$i]);
275
                }
276
            }
277
        }
278
279
        return array_values($actions);
280
    }
281
282
    /**
283
     * @param Objects $field
284
     * @param ElementInterface|null $element
285
     * @return array
286
     * @throws \craft\errors\MissingComponentException
287
     * @throws \yii\base\InvalidConfigException
288
     */
289
    protected function getActionHtml(Objects $field, ElementInterface $element = null): array
290
    {
291
        $actionData = [];
292
293
        foreach ($this->getActions($field, $element) as $action) {
294
            $actionData[] = [
295
                'type' => get_class($action),
296
                'destructive' => $action->isDestructive(),
297
                'params' => [],
298
                'name' => $action->getTriggerLabel(),
299
                'trigger' => $action->getTriggerHtml(),
300
                'confirm' => $action->getConfirmationMessage(),
301
            ];
302
        }
303
304
        return $actionData;
305
    }
306
307
    /**
308
     * @param Objects $field
309
     * @param ElementInterface|null $element
310
     * @return array
311
     * @throws \craft\errors\MissingComponentException
312
     * @throws \yii\base\InvalidConfigException
313
     */
314
    protected function getItemActionHtml(Objects $field, ElementInterface $element = null): array
315
    {
316
        $actionData = [];
317
318
        foreach ($this->getItemActions($field, $element) as $action) {
319
            $actionData[] = [
320
                'type' => get_class($action),
321
                'destructive' => $action->isDestructive(),
322
                'params' => [],
323
                'name' => $action->getTriggerLabel(),
324
                'trigger' => $action->getTriggerHtml(),
325
                'confirm' => $action->getConfirmationMessage(),
326
            ];
327
        }
328
329
        return $actionData;
330
    }
331
}
332