Completed
Push — master ( 4f056b...dcf641 )
by Robbie
23s queued 11s
created

ResourceLocatorField::getSaveTarget()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
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://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 = '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
        $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
        // Handle the case where this is being set as a legitimate "spec" containing endpoint, dataset and resource
89
        if (is_array($value)) {
90
            $this->value = $value;
91
            return $this;
92
        }
93
94
        // If it's still not valid we'll just run with an empty value (assume the relation isn't created)
95
        if (!$value instanceof DataObjectInterface) {
96
            $this->value = null;
97
            return $this;
98
        }
99
100
        $endpoint = $value->{$this->getEndpointFieldName()};
101
        $dataset = $value->{$this->getDatasetFieldName()};
102
        $resource = $value->{$this->getResourceFieldName()};
103
104
        // Validate we have a dataset
105
        if (!$dataset) {
106
            $this->value = null;
107
            return $this;
108
        }
109
110
        // Validate we have an endpoint (or a default to fall back upon)
111
        if (!$endpoint) {
112
            $endpoint = $this->getDefaultEndpoint();
113
            if (!$endpoint) {
114
                $this->value = null;
115
                return $this;
116
            }
117
        }
118
119
        $this->value = compact('endpoint', 'dataset', 'resource');
120
        return $this;
121
    }
122
123
    public function setSubmittedValue($value, $data = null)
124
    {
125
        return $this->setValue(json_decode($value, true));
126
    }
127
128
    public function dataValue()
129
    {
130
        // Although by default this "saves into" a child object we provide a JSON encoded value in case this method is
131
        // used.
132
        return json_encode($this->Value());
133
    }
134
135
136
    public function saveInto(DataObjectInterface $dataObject)
137
    {
138
        // Duplicate existing logic where the field is skipped given there's no name on this field.
139
        if (!$this->name) {
140
            return;
141
        }
142
143
        // Find what we're actually saving into
144
        $resource = $dataObject->{$this->name};
145
146
        if (!$resource || !$resource instanceof DataObjectInterface) {
147
            throw new InvalidArgumentException('Could not determine where to save the value of ' . __CLASS__);
148
        }
149
150
        // Pull the value that'll be null or an associative array of our specification
151
        $value = $this->Value();
152
        $resource->setCastedField($this->getEndpointFieldName(), $value ? $value['endpoint'] : null);
153
        $resource->setCastedField($this->getDatasetFieldName(), $value ? $value['dataset'] : null);
154
        $resource->setCastedField($this->getResourceFieldName(), $value ? $value['resource'] : null);
155
156
        // Now set the updated resource back on the parent
157
        $dataObject->setCastedField($this->name, $resource);
158
159
        // Ensure changes are persisted as this is not saved on page save if the ID of the resource did not change.
160
        $resource->write();
161
    }
162
163
    /**
164
     * @see ResourceLocatorField::$defaultEndpoint
165
     * @return string
166
     */
167
    public function getDefaultEndpoint()
168
    {
169
        if (!$this->defaultEndpoint) {
170
            return self::config()->get('default_endpoint');
171
        }
172
173
        return $this->defaultEndpoint;
174
    }
175
176
    /**
177
     * @see ResourceLocatorField::$defaultEndpoint
178
     * @param string $defaultEndpoint
179
     * @return $this
180
     */
181
    public function setDefaultEndpoint($defaultEndpoint)
182
    {
183
        $this->defaultEndpoint = $defaultEndpoint;
184
        return $this;
185
    }
186
187
    /**
188
     * @return null|string
189
     */
190
    public function getSiteName()
191
    {
192
        // Allow empty site names
193
        if ($this->siteName === null) {
194
            return _t(__CLASS__ . '.GENERIC_SITE_NAME', 'a CKAN website');
195
        }
196
197
        return $this->siteName;
198
    }
199
200
    /**
201
     * @param null|string $siteName
202
     * @return $this
203
     */
204
    public function setSiteName($siteName)
205
    {
206
        $this->siteName = $siteName;
207
        return $this;
208
    }
209
210
    /**
211
     * @return string
212
     */
213
    public function getEndpointFieldName()
214
    {
215
        return $this->endpointFieldName;
216
    }
217
218
    /**
219
     * @param string $endpointFieldName
220
     * @return $this
221
     */
222
    public function setEndpointFieldName($endpointFieldName)
223
    {
224
        $this->endpointFieldName = $endpointFieldName;
225
        return $this;
226
    }
227
228
    /**
229
     * @return string
230
     */
231
    public function getDatasetFieldName()
232
    {
233
        return $this->datasetFieldName;
234
    }
235
236
    /**
237
     * @param string $datasetFieldName
238
     * @return $this
239
     */
240
    public function setDatasetFieldName($datasetFieldName)
241
    {
242
        $this->datasetFieldName = $datasetFieldName;
243
        return $this;
244
    }
245
246
    /**
247
     * @return string
248
     */
249
    public function getResourceFieldName()
250
    {
251
        return $this->resourceFieldName;
252
    }
253
254
    /**
255
     * @param string $resourceFieldName
256
     * @return $this
257
     */
258
    public function setResourceFieldName($resourceFieldName)
259
    {
260
        $this->resourceFieldName = $resourceFieldName;
261
        return $this;
262
    }
263
}
264