Passed
Push — master ( 3c5336...a8246c )
by Robbie
04:44
created

ResourceLocatorField::setResourceFieldName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
namespace SilverStripe\CKANRegistry\Forms;
3
4
use InvalidArgumentException;
5
use SilverStripe\Forms\FormField;
6
use SilverStripe\ORM\DataObjectInterface;
7
8
class ResourceLocatorField extends FormField
9
{
10
    /**
11
     * The default CKAN endpoint to be used in a default isn't provided on construction
12
     * @see ResourceLocatorField::$defaultEndpoint
13
     *
14
     * @config
15
     * @var string
16
     */
17
    private static $default_endpoint = 'https://demo.ckan.org/';
18
19
    /**
20
     * The default CKAN endpoint to be used in this field. This will allow consumers of the field to only provide
21
     * package or dataset IDs and still work. If not set the configured default will instead be used.
22
     *
23
     * @var string|null
24
     */
25
    protected $defaultEndpoint;
26
27
    /**
28
     * Set a site name that can be used to refer to the CKAN endpoint. By default this will be "a CKAN website".
29
     *
30
     * @var string|null
31
     */
32
    protected $siteName = null;
33
34
    /**
35
     * The name of the subfield to save the endpoint value of this field into
36
     *
37
     * @var string
38
     */
39
    protected $endpointFieldName = 'Endpoint';
40
41
    /**
42
     * The name of the subfield to save the dataset value of this field into
43
     *
44
     * @var string
45
     */
46
    protected $datasetFieldName = 'DataSet';
47
48
    /**
49
     * The name of the subfield to save the resource value of this field into
50
     *
51
     * @var string
52
     */
53
    protected $resourceFieldName = 'Identifier';
54
55
    /**
56
     * @param string $name
57
     * @param string $title
58
     * @param string $value
59
     * @param string $defaultEndpoint
60
     */
61
    public function __construct($name, $title = null, $value = null, $defaultEndpoint = null)
62
    {
63
        parent::__construct($name, $title, $value);
64
        $this->setDefaultEndpoint($defaultEndpoint);
65
66
        // Set a default description
67
        $this->setDescription(_t(
68
            __CLASS__ . '.DESCRIPTION',
69
            'Connect to a data source from {site}. Once added and saved you can configure the appearance and add search'
70
            . ' filters.',
71
            [ 'site' => $this->getSiteName() ]
72
        ));
73
    }
74
75
    public function getSchemaDataDefaults()
76
    {
77
        return array_merge(parent::getSchemaDataDefaults(), [
78
            'hideLabels' => true,
79
            'defaultEndpoint' => $this->getDefaultEndpoint(),
80
        ]);
81
    }
82
83
    public function performReadonlyTransformation()
84
    {
85
        // Set read only and clone to maintain immutability
86
        $clone = clone $this->setReadonly(true);
87
88
        // Clear out the description that's only relevant when the field is editable.
89
        $clone->setDescription('');
90
91
        return $clone;
92
    }
93
94
95
    public function setValue($value, $data = null)
96
    {
97
        // Handle the case where this is being set as a legitimate "spec" containing endpoint, dataset and resource
98
        if (is_array($value)) {
99
            $this->value = $value;
100
            return $this;
101
        }
102
103
        // If it's still not valid we'll just run with an empty value (assume the relation isn't created)
104
        if (!$value instanceof DataObjectInterface) {
105
            $this->value = null;
106
            return $this;
107
        }
108
109
        $endpoint = $value->{$this->getEndpointFieldName()};
110
        $dataset = $value->{$this->getDatasetFieldName()};
111
        $resource = $value->{$this->getResourceFieldName()};
112
113
        // Validate we have a dataset
114
        if (!$dataset) {
115
            $this->value = null;
116
            return $this;
117
        }
118
119
        // Validate we have an endpoint (or a default to fall back upon)
120
        if (!$endpoint) {
121
            $endpoint = $this->getDefaultEndpoint();
122
            if (!$endpoint) {
123
                $this->value = null;
124
                return $this;
125
            }
126
        }
127
128
        $this->value = compact('endpoint', 'dataset', 'resource');
129
        return $this;
130
    }
131
132
    public function setSubmittedValue($value, $data = null)
133
    {
134
        return $this->setValue(json_decode($value, true));
135
    }
136
137
    public function dataValue()
138
    {
139
        // Although by default this "saves into" a child object we provide a JSON encoded value in case this method is
140
        // used.
141
        return json_encode($this->Value());
142
    }
143
144
145
    public function saveInto(DataObjectInterface $dataObject)
146
    {
147
        // Duplicate existing logic where the field is skipped given there's no name on this field.
148
        if (!$this->name) {
149
            return;
150
        }
151
152
        // Find what we're actually saving into
153
        $resource = $dataObject->{$this->name};
154
155
        if (!$resource || !$resource instanceof DataObjectInterface) {
156
            throw new InvalidArgumentException('Could not determine where to save the value of ' . __CLASS__);
157
        }
158
159
        // Pull the value that'll be null or an associative array of our specification
160
        $value = $this->Value();
161
        $resource->setCastedField($this->getEndpointFieldName(), $value ? $value['endpoint'] : null);
162
        $resource->setCastedField($this->getDatasetFieldName(), $value ? $value['dataset'] : null);
163
        $resource->setCastedField($this->getResourceFieldName(), $value ? $value['resource'] : null);
164
165
        // Now set the updated resource back on the parent
166
        $dataObject->setCastedField($this->name, $resource);
167
168
        // Ensure changes are persisted as this is not saved on page save if the ID of the resource did not change.
169
        $resource->write();
170
    }
171
172
    /**
173
     * @see ResourceLocatorField::$defaultEndpoint
174
     * @return string
175
     */
176
    public function getDefaultEndpoint()
177
    {
178
        if (!$this->defaultEndpoint) {
179
            return self::config()->get('default_endpoint');
180
        }
181
182
        return $this->defaultEndpoint;
183
    }
184
185
    /**
186
     * @see ResourceLocatorField::$defaultEndpoint
187
     * @param string $defaultEndpoint
188
     * @return $this
189
     */
190
    public function setDefaultEndpoint($defaultEndpoint)
191
    {
192
        $this->defaultEndpoint = $defaultEndpoint;
193
        return $this;
194
    }
195
196
    /**
197
     * @return null|string
198
     */
199
    public function getSiteName()
200
    {
201
        // Allow empty site names
202
        if ($this->siteName === null) {
203
            return _t(__CLASS__ . '.GENERIC_SITE_NAME', 'a CKAN website');
204
        }
205
206
        return $this->siteName;
207
    }
208
209
    /**
210
     * @param null|string $siteName
211
     * @return $this
212
     */
213
    public function setSiteName($siteName)
214
    {
215
        $this->siteName = $siteName;
216
        return $this;
217
    }
218
219
    /**
220
     * @return string
221
     */
222
    public function getEndpointFieldName()
223
    {
224
        return $this->endpointFieldName;
225
    }
226
227
    /**
228
     * @param string $endpointFieldName
229
     * @return $this
230
     */
231
    public function setEndpointFieldName($endpointFieldName)
232
    {
233
        $this->endpointFieldName = $endpointFieldName;
234
        return $this;
235
    }
236
237
    /**
238
     * @return string
239
     */
240
    public function getDatasetFieldName()
241
    {
242
        return $this->datasetFieldName;
243
    }
244
245
    /**
246
     * @param string $datasetFieldName
247
     * @return $this
248
     */
249
    public function setDatasetFieldName($datasetFieldName)
250
    {
251
        $this->datasetFieldName = $datasetFieldName;
252
        return $this;
253
    }
254
255
    /**
256
     * @return string
257
     */
258
    public function getResourceFieldName()
259
    {
260
        return $this->resourceFieldName;
261
    }
262
263
    /**
264
     * @param string $resourceFieldName
265
     * @return $this
266
     */
267
    public function setResourceFieldName($resourceFieldName)
268
    {
269
        $this->resourceFieldName = $resourceFieldName;
270
        return $this;
271
    }
272
}
273