Test Failed
Branch master (3c461d)
by Mohamed
103:57
created

GridField::setOwner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Moo\HasOneSelector\Form;
4
5
use Exception;
6
use Moo\HasOneSelector\ORM\DataList;
7
use SilverStripe\Control\Controller;
8
use SilverStripe\Forms\FormField;
9
use SilverStripe\Forms\GridField\GridField as SSGridField;
10
use SilverStripe\Forms\GridField\GridField_ActionMenu;
11
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
12
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
13
use SilverStripe\Forms\GridField\GridFieldButtonRow;
14
use SilverStripe\Forms\GridField\GridFieldConfig;
15
use SilverStripe\Forms\GridField\GridFieldDataColumns;
16
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
17
use SilverStripe\Forms\GridField\GridFieldDetailForm;
18
use SilverStripe\Forms\GridField\GridFieldEditButton;
19
use SilverStripe\ORM\DataObject;
20
use SilverStripe\ORM\SS_List;
21
use SilverStripe\View\Requirements;
22
23
/**
24
 * Class GridField instance of grid field
25
 */
26
class GridField extends SSGridField
27
{
28
    /**
29
     * Name of the list data class
30
     *
31
     * @var string
32
     */
33
    protected $dataClass;
34
35
    /**
36
     * Instance of data object that contains the has one relation
37
     *
38
     * @var DataObject
39
     */
40
    protected $owner;
41
42
    /**
43
     * Text to display when no record selected
44
     *
45
     * @var string
46
     */
47
    protected $emptyString = 'No item selected';
48
49
    /**
50
     * Instance of form field that holds the value
51
     *
52
     * @var FormField
53
     */
54
    protected $valueField;
55
56
    /**
57
     * HasOneSelector GridField constructor.
58
     * @param string     $name
59
     * @param string     $title
60
     * @param DataObject $owner
61
     * @param string     $dataClass
62
     */
63
    public function __construct($name, $title, DataObject $owner, $dataClass = DataObject::class)
64
    {
65
        // Include styles
66
        Requirements::css('moo/hasoneselector:client/styles/hasoneselector.css');
67
68
        // Initiate grid field configuration based on relation editor
69
        $config = new GridFieldConfig();
70
        $config->addComponent(new GridFieldButtonRow('before'));
71
        $config->addComponent(new GridFieldAddNewButton('buttons-before-left'));
72
        $config->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-right'));
73
        $config->addComponent(new GridFieldDataColumns());
74
        $config->addComponent(new GridFieldEditButton());
75
        $config->addComponent(new GridFieldDeleteAction(true));
76
        $config->addComponent(new GridField_ActionMenu());
77
        $config->addComponent(new GridFieldDetailForm());
78
79
        // Set the data class of the list
80
        $this->setDataClass($dataClass);
81
        // Set the owner data object that contains the has one relation
82
        $this->setOwner($owner);
83
        // Load relation value from session
84
        $this->loadRelationFromSession();
85
86
        // Instance of data list that manages the grid field data
87
        $dataList = DataList::create($this);
88
89
        // Set empty string based on the data class
90
        $this->setEmptyString(sprintf('No %s selected', strtolower(singleton($dataClass)->singular_name())));
91
92
        parent::__construct($name, $title, $dataList, $config);
93
    }
94
95
    /**
96
     * Set instance of value holder field
97
     *
98
     * @param  FormField $field
99
     * @return $this
100
     */
101
    public function setValueHolderField(FormField $field)
102
    {
103
        $this->valueField = $field;
104
105
        return $this;
106
    }
107
108
    /**
109
     * Defined the columns to be rendered in the field
110
     *
111
     * @param  array $fields
112
     * @return $this
113
     */
114
    public function setDisplayFields(array $fields)
115
    {
116
        // Get grid field configuration
117
        $config = $this->getConfig();
118
119
        // Define columns to display in grid field
120
        $config->getComponentByType(GridFieldDataColumns::class)->setDisplayFields($fields);
0 ignored issues
show
Bug introduced by
The method setDisplayFields() does not exist on SilverStripe\Forms\GridField\GridFieldComponent. It seems like you code against a sub-type of SilverStripe\Forms\GridField\GridFieldComponent such as SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldDataColumns or SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldDetailForm. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
        $config->getComponentByType(GridFieldDataColumns::class)->/** @scrutinizer ignore-call */ setDisplayFields($fields);
Loading history...
121
122
        return $this;
123
    }
124
125
    /**
126
     * Apply transformation of the displayed data within a specific column(s)
127
     *
128
     * @param  array $formatting
129
     * @return $this
130
     */
131
    public function setFieldFormatting(array $formatting)
132
    {
133
        // Get grid field configuration
134
        $config = $this->getConfig();
135
136
        // Customise the display of the column
137
        $config->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting($formatting);
0 ignored issues
show
Bug introduced by
The method setFieldFormatting() does not exist on SilverStripe\Forms\GridField\GridFieldComponent. It seems like you code against a sub-type of SilverStripe\Forms\GridField\GridFieldComponent such as SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldDataColumns or SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldDetailForm. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
        $config->getComponentByType(GridFieldDataColumns::class)->/** @scrutinizer ignore-call */ setFieldFormatting($formatting);
Loading history...
138
139
        return $this;
140
    }
141
142
    /**
143
     * Set empty string when no record selected
144
     *
145
     * @param  string $string
146
     * @return $this
147
     */
148
    public function setEmptyString($string)
149
    {
150
        $this->emptyString = $string;
151
152
        return $this;
153
    }
154
155
    /**
156
     * set the name of the data class for current list
157
     *
158
     * @param  string $class
159
     * @return $this
160
     */
161
    public function setDataClass($class)
162
    {
163
        $this->dataClass = $class;
164
165
        return $this;
166
    }
167
168
    /**
169
     * Get the name of the data class for current list
170
     *
171
     * @return string
172
     */
173
    public function getDataClass()
174
    {
175
        return $this->dataClass;
176
    }
177
178
    /**
179
     * Get the record of the has one relation for current owner object
180
     *
181
     * @return DataObject|null
182
     * @throws Exception
183
     */
184
    public function getRecord()
185
    {
186
        return $this->getOwner()->{rtrim($this->getName(), 'ID')}();
187
    }
188
189
    /**
190
     * Set the record of the has one relation for current owner object
191
     *
192
     * @param  DataObject|null $object
193
     * @return void
194
     * @throws Exception
195
     */
196
    public function setRecord($object)
197
    {
198
        $owner      = $this->getOwner();
199
        $recordName = $this->getRelationName();
200
201
        $owner->{$recordName} = is_null($object) ? 0 : $object->ID;
202
203
        // Store relation value in session
204
        $this->storeRelationInSession($owner->{$recordName});
205
    }
206
207
    /**
208
     * Set instance of data object that has the has one relation
209
     *
210
     * @param  DataObject $owner
211
     * @return $this
212
     */
213
    public function setOwner(DataObject $owner)
214
    {
215
        $this->owner = $owner;
216
217
        return $this;
218
    }
219
220
    /**
221
     * Get instance of data object that has the has one relation
222
     *
223
     * @return DataObject
224
     */
225
    public function getOwner()
226
    {
227
        return $this->owner;
228
    }
229
230
    /**
231
     * Get the data source.
232
     *
233
     * @return SS_List
234
     */
235
    public function getList()
236
    {
237
        // Get current record ID
238
        $id = (int) $this->getOwner()->{$this->getRelationName()};
239
240
        // Filter current list to display current record (has one) value
241
        return $this->list->filter('ID', $id);
0 ignored issues
show
Bug introduced by
The method filter() does not exist on SilverStripe\ORM\SS_List. It seems like you code against a sub-type of said class. However, the method does not exist in SilverStripe\ORM\Sortable or SilverStripe\ORM\Limitable. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

241
        return $this->list->/** @scrutinizer ignore-call */ filter('ID', $id);
Loading history...
242
    }
243
244
    /**
245
     * Get the data source after applying every {@link GridField_DataManipulator} to it.
246
     *
247
     * @return SS_List
248
     */
249
    public function getManipulatedList()
250
    {
251
        // Call manipulation from parent class to update current record (has one)
252
        parent::getManipulatedList();
253
254
        // Get list of data based on new record
255
        return $this->getList();
256
    }
257
258
    /**
259
     * @param  array  $content
260
     * @return string
261
     */
262
    protected function getOptionalTableBody(array $content)
263
    {
264
        // Text used by grid field for no items
265
        $noItemsText = _t('GridField.NoItemsFound', 'No items found');
266
267
        // If we have no items text in the body, then replace the text with customised string
268
        if (strpos($content['body'], $noItemsText) !== false) {
269
            $content['body'] = str_replace($noItemsText, $this->emptyString, $content['body']);
270
        }
271
272
        // Append field to hold the value of has one relation
273
        $owner      = $this->getOwner();
274
        $recordName = $this->getRelationName();
275
        $content['body'] .= $this->valueField->setValue($owner->{$recordName})->Field();
276
277
        return parent::getOptionalTableBody($content);
278
    }
279
280
    /**
281
     * Get relation name within the owner object. This includes the "ID" at the end
282
     *
283
     * @return string
284
     */
285
    protected function getRelationName()
286
    {
287
        return $this->getName() . 'ID';
288
    }
289
290
    /**
291
     * Store relation value in session
292
     *
293
     * @param int $recordId
294
     */
295
    protected function storeRelationInSession($recordId)
296
    {
297
        // Session name for current owner
298
        $sessionName = $this->getSessionName();
299
300
        // Store relation and owner in session
301
        $session = Controller::curr()->getRequest()->getSession();
302
        $session->set($sessionName, [
303
            'Relation'   => $this->getRelationName(),
304
            'RelationID' => (int) $recordId,
305
        ]);
306
    }
307
308
    /**
309
     * Load relation value from data stored in session
310
     */
311
    protected function loadRelationFromSession()
312
    {
313
        // Session name for current owner
314
        $sessionName = $this->getSessionName();
315
316
        // Store relation value in session
317
        $session = Controller::curr()->getRequest()->getSession();
318
        $data    = $session->get($sessionName);
319
        if (!empty($data['Relation']) && !empty($data['RelationID'])) {
320
            // Get owner object
321
            $owner = $this->getOwner();
322
323
            // Set relation value
324
            $owner->{$data['Relation']} = $data['RelationID'];
325
        }
326
    }
327
328
    /**
329
     * Get session name for current owner to store relation value
330
     *
331
     * @return string
332
     */
333
    protected function getSessionName()
334
    {
335
        // Get owner object
336
        $owner = $this->getOwner();
337
338
        // Session name for current owner
339
        return static::formatSessionName($owner);
340
    }
341
342
    /**
343
     * Get formatted name for session to store relation value
344
     *
345
     * @param  DataObject $owner
346
     * @return string
347
     */
348
    public static function formatSessionName($owner)
349
    {
350
        return sprintf('%s_%s_%s', self::class, $owner->ClassName, $owner->ID);
351
    }
352
}
353