Link::getInputHtml()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
c 0
b 0
f 0
ccs 0
cts 11
cp 0
rs 9.4285
cc 1
eloc 6
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/link/license
6
 * @link       https://www.flipboxfactory.com/software/link/
7
 */
8
9
namespace flipbox\link\fields;
10
11
use Craft;
12
use craft\base\ElementInterface;
13
use craft\base\Field;
14
use craft\helpers\ArrayHelper;
15
use craft\helpers\Db;
16
use craft\helpers\Json;
17
use flipbox\link\Link as LinkPlugin;
18
use flipbox\link\types\TypeInterface;
19
use flipbox\link\web\assets\settings\Settings;
20
use yii\db\Schema;
21
22
/**
23
 * @author Flipbox Factory <[email protected]>
24
 * @since 1.0.0
25
 */
26
class Link extends Field
27
{
28
29
    /**
30
     * Type objects that have been configured via the admin
31
     *
32
     * @var TypeInterface[]
33
     */
34
    protected $types = [];
35
36
    /**
37
     * Raw configurations that have been configured via the admin
38
     *
39
     * @var array
40
     */
41
    protected $typeConfigs = [];
42
43
    /**
44
     * @return TypeInterface[]
45
     */
46
    public function getTypes()
47
    {
48
        // Make sure all un-resolved configs are resolved
49
        $this->resolveConfigs();
50
51
        return $this->types;
52
    }
53
54
    /**
55
     * @param array $types
56
     * @return $this
57
     */
58
    public function setTypes(array $types)
59
    {
60
        foreach ($types as $identifier => $type) {
61
            $identifier = is_array($type) ? ArrayHelper::getValue($type, 'identifier', $identifier) : $identifier;
62
            $this->typeConfigs[$identifier] = $type;
63
        }
64
        return $this;
65
    }
66
67
    /**
68
     * @param string $identifier
69
     * @return TypeInterface
70
     */
71
    public function getType(string $identifier)
72
    {
73
        // Is it already an object?
74
        if (!array_key_exists($identifier, $this->types)) {
75
            // Can we create it?
76
            if (!$type = $this->createFromConfig($identifier)) {
77
                return null;
78
            }
79
80
            $this->types[$identifier] = $type;
81
        }
82
83
        return clone $this->types[$identifier];
84
    }
85
86
    /**
87
     * Create objects from all (remaining) configurations
88
     *
89
     * @return $this
90
     */
91
    private function resolveConfigs()
92
    {
93
        foreach ($this->typeConfigs as $identifier => $config) {
94
            $this->resolveConfig($identifier, $config);
95
        }
96
        $this->typeConfigs = [];
97
    }
98
99
    /**
100
     * @param string $identifier
101
     * @param array $config
102
     * @return null|object
103
     */
104
    private function resolveConfig(string $identifier, array $config)
105
    {
106
        // cCreate new
107
        if (!$type = LinkPlugin::getInstance()->getType()->create($config)) {
108
            return null;
109
        }
110
111
        $type->setIdentifier($identifier);
112
113
        // Cache it
114
        $this->types[$identifier] = $type;
115
116
        return $type;
117
    }
118
119
    /**
120
     * @param string $identifier
121
     * @return null|object
122
     */
123
    private function createFromConfig(string $identifier)
124
    {
125
        if (!$config = ArrayHelper::remove($this->typeConfigs, $identifier)) {
126
            return null;
127
        }
128
129
        return $this->resolveConfig($identifier, $config);
130
    }
131
132
    /**
133
     * @inheritdoc
134
     */
135
    public static function displayName(): string
136
    {
137
        return Craft::t('link', 'Link');
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143
    public function getContentColumnType(): string
144
    {
145
        return Schema::TYPE_TEXT;
146
    }
147
148
    /**
149
     * @inheritdoc
150
     */
151
    public function getSettingsHtml()
152
    {
153
154
        $view = Craft::$app->getView();
155
156
        $view->registerAssetBundle(Settings::class);
157
        
158
        return $view->renderTemplate(
159
            'link/_components/fieldtypes/Link/settings',
160
            [
161
                'field' => $this,
162
                'types' => LinkPlugin::getInstance()->getType()->findAll(),
163
                'namespace' => $view->getNamespace()
164
            ]
165
        );
166
    }
167
168
    /**
169
     * @inheritdoc
170
     */
171
    public function getInputHtml($value, ElementInterface $element = null): string
172
    {
173
        return Craft::$app->getView()->renderTemplate(
174
            'link/_components/fieldtypes/Link/input',
175
            [
176
                'field' => $this,
177
                'value' => $value,
178
                'element' => $element
179
            ]
180
        );
181
    }
182
183
    /**
184
     * @inheritdoc
185
     */
186
    public function serializeValue($value, ElementInterface $element = null)
187
    {
188
        if ($value === null) {
189
            return $value;
190
        }
191
192
        if ($value instanceof TypeInterface) {
193
            $value = array_merge(
194
                [
195
                    'identifier' => $value->getIdentifier(),
196
                ],
197
                $value->getProperties()
198
            );
199
        }
200
201
        return Db::prepareValueForDb($value);
202
    }
203
204
    /**
205
     * @inheritdoc
206
     */
207
    public function getSettings(): array
208
    {
209
        $settings = parent::getSettings();
210
211
        // Merge the type settings
212
        foreach ($this->getTypes() as $identifier => $type) {
213
            $settings['types'][$identifier] = array_merge(
214
                ['class' => get_class($type)],
215
                $type->getSettings()
216
            );
217
        }
218
219
        return $settings;
220
    }
221
222
    /**
223
     * @param mixed $value
224
     * @param ElementInterface|null $element
225
     * @return array|mixed|null|object
226
     */
227
    public function normalizeValue($value, ElementInterface $element = null)
228
    {
229
        if (is_string($value) && !empty($value)) {
230
            $value = Json::decodeIfJson($value);
231
        }
232
233
        if ($value instanceof TypeInterface) {
234
            return $value;
235
        }
236
237
        if (!is_array($value)) {
238
            return null;
239
        }
240
241
        // Get the type by identifier
242
        if ($identifier = ArrayHelper::remove($value, 'identifier')) {
243
            $type = $this->getType($identifier);
244
        } else {
245
            if ($class = ArrayHelper::remove($value, 'class')) {
246
                $type = LinkPlugin::getInstance()->getType()->create($class);
247
            }
248
        }
249
250
        if (empty($type) || !$type instanceof TypeInterface) {
251
            return null;
252
        }
253
254
        // When saving via the admin, there may be multiple 'types' configured
255
        if ($types = ArrayHelper::remove($value, 'types')) {
256
            $value = array_merge(
257
                ArrayHelper::remove($types, $identifier, []),
258
                $value
259
            );
260
        }
261
262
        LinkPlugin::getInstance()->getType()->populate(
263
            $type,
264
            $value
265
        );
266
267
        return $type;
268
    }
269
}
270