Passed
Pull Request — master (#32)
by
unknown
01:56
created

ResourceLocatorField::setValue()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 33
rs 9.0777
c 0
b 0
f 0
cc 6
nc 9
nop 2
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://catalogue.data.govt.nz/';
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 = 'Resource';
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
        $this->addExtraClass('ckan-resource-locator__container');
75
    }
76
77
    public function getSchemaDataDefaults()
78
    {
79
        $schemaData = parent::getSchemaDataDefaults();
80
81
        $schemaData['defaultEndpoint'] = $this->getDefaultEndpoint();
82
83
        return $schemaData;
84
    }
85
86
    public function setValue($value, $data = null)
87
    {
88
        // $value should be the child DataObject but if it isn't we can use `getSaveTarget`
89
        if (!$value instanceof DataObjectInterface) {
90
            $value = $this->getSaveTarget($data);
91
92
            // If it's still not valid we'll just run with an empty value (assume the relation isn't created)
93
            if (!$value instanceof DataObjectInterface) {
94
                $this->value = null;
95
                return $this;
96
            }
97
        }
98
99
        $endpoint = $value->{$this->getEndpointFieldName()};
100
        $dataset = $value->{$this->getDatasetFieldName()};
101
        $resource = $value->{$this->getResourceFieldName()};
102
103
        // Validate we have a dataset
104
        if (!$dataset) {
105
            $this->value = null;
106
            return $this;
107
        }
108
109
        // Validate we have an endpoint (or a default to fall back upon)
110
        if (!$endpoint) {
111
            $endpoint = $this->getDefaultEndpoint();
112
            if (!$endpoint) {
113
                $this->value = null;
114
                return $this;
115
            }
116
        }
117
118
        $this->value = compact('endpoint', 'dataset', 'resource');
119
    }
120
121
    public function setSubmittedValue($value, $data = null)
122
    {
123
        return $this->setValue(json_decode($value, true));
124
    }
125
126
    public function dataValue()
127
    {
128
        // Although by default this "saves into" a child object we provide a JSON encoded value in case this method is
129
        // used.
130
        return json_encode($this->Value());
131
    }
132
133
134
    public function saveInto(DataObjectInterface $dataObject)
135
    {
136
        // Duplicate existing logic where the field is skipped given there's no name on this field.
137
        if (!$this->name) {
138
            return;
139
        }
140
141
        // Find what we're actually saving into
142
        $child = $this->getSaveTarget($dataObject);
143
144
        if (!$child || !$child instanceof DataObjectInterface) {
145
            throw new InvalidArgumentException('Could not determine where to save the value of ' . __CLASS__);
146
        }
147
148
        // Pull the value that'll be null or an associative array of our specification
149
        $value = $this->Value();
150
        $child->setCastedField($this->getEndpointFieldName(), $value ? $value['endpoint'] : null);
151
        $child->setCastedField($this->getDatasetFieldName(), $value ? $value['dataset'] : null);
152
        $child->setCastedField($this->getResourceFieldName(), $value ? $value['resource'] : null);
153
    }
154
155
    /**
156
     * Provide the object that this field actually saves into.
157
     * By default this is a relation access with __get. Eg. given $dataObject is a page; $page->CKANResource where
158
     * "CKANResource" is the name of this field.
159
     *
160
     * @param DataObjectInterface $dataObject
161
     * @return mixed
162
     */
163
    public function getSaveTarget(DataObjectInterface $dataObject)
164
    {
165
        $target = $dataObject->{$this->name};
166
167
        $this->extend('updateSaveTarget', $target, $dataObject);
168
169
        return $target;
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