InputTrait   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 5
dl 0
loc 202
ccs 0
cts 126
cp 0
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
elementType() 0 1 ?
inputSources() 0 1 ?
A getInputHtml() 0 20 3
A inputTemplateVariables() 0 25 3
B inputToIndexSources() 0 32 7
A getInputJs() 0 37 4
A getIndexJs() 0 34 4
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-element-lists/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-element-lists/
7
 */
8
9
namespace flipbox\craft\element\lists\fields;
10
11
use Craft;
12
use craft\base\Element;
13
use craft\base\ElementInterface;
14
use craft\elements\db\ElementQuery;
15
use craft\elements\db\ElementQueryInterface;
16
use craft\helpers\ArrayHelper;
17
use flipbox\craft\element\lists\relationships\RelationshipInterface;
18
use flipbox\craft\elements\nestedIndex\web\assets\index\NestedElementIndex;
19
use flipbox\craft\ember\helpers\SiteHelper;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 2.0.0
24
 *
25
 * @property string $inputTemplate
26
 * @property string $inputJsClass
27
 * @property string $handle
28
 * @property int $id
29
 * @property string|null $viewMode
30
 * @property int|null $limit
31
 * @property string $selectionLabel
32
 */
33
trait InputTrait
34
{
35
    /**
36
     * Returns the element class associated with this field type.
37
     *
38
     * @return string The Element class name
39
     */
40
    abstract protected static function elementType(): string;
41
42
    /**
43
     * Returns an array of the source keys the field should be able to select elements from.
44
     *
45
     * @param ElementInterface|null $element
46
     * @return array|string
47
     */
48
    abstract protected function inputSources(ElementInterface $element = null);
49
50
    /**
51
     * @inheritDoc
52
     * @throws \Twig\Error\LoaderError
53
     * @throws \Twig\Error\RuntimeError
54
     * @throws \Twig\Error\SyntaxError
55
     * @throws \yii\base\InvalidConfigException
56
     */
57
    public function getInputHtml($value, ElementInterface $element = null): string
58
    {
59
        /** @var Element|null $element */
60
        if ($element !== null && $element->hasEagerLoadedElements($this->handle)) {
61
            $value = $element->getEagerLoadedElements($this->handle);
62
        }
63
64
        /** @var ElementQuery|array $value */
65
        $variables = $this->inputTemplateVariables($value, $element);
0 ignored issues
show
Documentation introduced by
$value is of type object<craft\elements\db\ElementQuery>|array, but the function expects a object<flipbox\craft\ele...tionshipInterface>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
66
67
        return Craft::$app->getView()->renderTemplate(
68
            'element-lists/_components/fieldtypes/input',
69
            array_merge(
70
                [
71
                    'inputTemplate' => $this->inputTemplate
72
                ],
73
                $variables
74
            )
75
        );
76
    }
77
78
    /**
79
     * @param RelationshipInterface|null $value
80
     * @param ElementInterface|null $element
81
     * @return array
82
     * @throws \yii\base\InvalidConfigException
83
     */
84
    protected function inputTemplateVariables($value = null, ElementInterface $element = null): array
85
    {
86
        if ($value instanceof RelationshipInterface) {
87
            $value = $value->getCollection()->pluck('id')->all();
88
        }
89
90
        if (!is_array($value)) {
91
            $value = [];
92
        }
93
94
        Craft::$app->getView()->registerAssetBundle(NestedElementIndex::class);
95
96
        return [
97
            'sources' => $this->inputToIndexSources(
98
                $this->inputSources($element)
99
            ),
100
            'element' => $element,
101
            'container' => 'nested-index-' . $this->handle,
102
            'elementType' => static::elementType(),
103
            'inputJsClass' => 'Craft.NestedElementIndexSelectInput',
104
            'inputJs' => $this->getInputJs($value, $element),
105
            'indexJsClass' => 'Craft.NestedElementIndex',
106
            'indexJs' => $this->getIndexJs($element)
107
        ];
108
    }
109
110
    /**
111
     * Converts input sources to index sources (used to filter results).
112
     *
113
     * @param $sources
114
     * @return array
115
     */
116
    protected function inputToIndexSources($sources): array
117
    {
118
        $indexSources = Craft::$app->getElementIndexes()->getSources(static::elementType());
119
120
        if ($sources === '*') {
121
            // Remove any structure sources
122
            foreach ($indexSources as &$indexSource) {
123
                ArrayHelper::remove($indexSource, 'structureEditable');
124
                ArrayHelper::remove($indexSource, 'structureId');
125
            }
126
127
            return $indexSources;
128
        }
129
130
        if (!is_array($sources)) {
131
            $sources = [$sources];
132
        }
133
134
        // Only return the selected sources
135
        foreach ($indexSources as $key => $indexSource) {
136
            if (!array_key_exists('key', $indexSource)) {
137
                unset($indexSources[$key]);
138
                continue;
139
            }
140
141
            if (!in_array($indexSource['key'], $sources)) {
142
                unset($indexSources[$key]);
143
            }
144
        }
145
146
        return $indexSources;
147
    }
148
149
    /*******************************************
150
     * JS CONFIGS
151
     *******************************************/
152
153
    /**
154
     * @param array $elementIds
155
     * @param ElementInterface $element
156
     * @return array
157
     */
158
    private function getInputJs(array $elementIds, ElementInterface $element = null): array
159
    {
160
        /** @var Element $element */
161
        $siteId = SiteHelper::ensureSiteId($element ? $element->siteId : null);
162
163
        $selectionCriteria = [
164
            'enabledForSite' => null,
165
            'siteId' => $siteId
166
        ];
167
168
        return [
169
            'elementType' => static::elementType(),
170
            'sources' => $this->inputSources($element),
171
            'criteria' => $selectionCriteria,
172
            'sourceElementId' => $element->getId() ?: null,
173
            'viewMode' => $this->viewMode,
174
            'limit' => $this->limit,
175
            'selectionLabel' => $this->selectionLabel,
176
            'storageKey' => 'nested.index.input.' . $this->handle,
177
            'elements' => $elementIds,
178
            'addAction' => 'element-lists/source/associate',
179
            'selectTargetAttribute' => 'target',
180
            'selectParams' => [
181
                'source' => $element->getId() ?: null,
182
                'field' => $this->id,
183
                'site' => $siteId,
184
            ],
185
            'modalSettings' => [
186
                'sendDisabledModalElementsAsString' => true,
187
                'indexSettings' => [
188
                    'updateElementsAction' => 'element-lists/element-indexes/get-elements',
189
                    'submitActionsAction' => 'element-lists/element-indexes/perform-action',
190
                    'loadMoreElementsAction' => 'element-lists/element-indexes/get-more-elements'
191
                ]
192
            ]
193
        ];
194
    }
195
196
    /**
197
     * @param ElementInterface $element
198
     * @return array
199
     */
200
    private function getIndexJs(ElementInterface $element = null): array
201
    {
202
203
        /** @var Element $element */
204
        $elementId = ($element !== null && $element->getId() !== null) ? $element->getId() : false;
205
206
        $siteId = SiteHelper::ensureSiteId($element ? $element->siteId : null);
207
208
        return [
209
            'source' => 'nested',
210
            'context' => 'index',
211
            'viewMode' => $this->viewMode,
212
            'showStatusMenu' => true,
213
            'showSiteMenu' => true,
214
            'hideSidebar' => true,
215
            'toolbarFixed' => false,
216
            'storageKey' => 'nested.index.' . $this->handle,
217
            'updateElementsAction' => 'element-lists/element-indexes/get-elements',
218
            'submitActionsAction' => 'element-lists/element-indexes/perform-action',
219
            'loadMoreElementsAction' => 'element-lists/element-indexes/get-more-elements',
220
            'criteria' => [
221
                'enabledForSite' => null,
222
                'siteId' => $siteId,
223
                $this->handle => [
224
                    'source' => $elementId,
225
                    'sourceSiteId' => $siteId
226
                ]
227
            ],
228
            'viewParams' => [
229
                'sourceId' => $elementId,
230
                'fieldId' => $this->id
231
            ]
232
        ];
233
    }
234
}
235