Issues (6)

src/PureModalAction.php (1 issue)

1
<?php
2
3
namespace LeKoala\PureModal;
4
5
use SilverStripe\Forms\Form;
6
use SilverStripe\Forms\FieldList;
7
use SilverStripe\Forms\DatalessField;
8
9
/**
10
 * Custom modal action
11
 * Requires cms-actions to work out of the box
12
 */
13
class PureModalAction extends DatalessField
14
{
15
    /**
16
     * Default classes applied in constructor by the FormField
17
     * @config
18
     * @var array<string>
19
     */
20
    private static $default_classes = ["btn", "btn-info"];
21
22
    /**
23
     * @var FieldList
24
     */
25
    protected $fieldList;
26
27
    /**
28
     * A custom title for the dialog button
29
     * @var string
30
     */
31
    protected $dialogButtonTitle;
32
33
    /**
34
     * Should it show the dialog button
35
     * @var boolean
36
     */
37
    protected $showDialogButton = true;
38
39
    /**
40
     * An icon for this button
41
     * @var string
42
     */
43
    protected $buttonIcon;
44
45
    /**
46
     * @var boolean
47
     */
48
    protected $shouldRefresh = false;
49
50
    /**
51
     * Whether to place the button in a dot-menu.
52
     * @see https://github.com/lekoala/silverstripe-cms-actions
53
     * @var bool
54
     */
55
    protected $dropUp = false;
56
57
    /**
58
     * @var boolean
59
     */
60
    protected $fillHeight = false;
61
62
    /**
63
     * @param string $name
64
     * @param string $title
65
     */
66
    public function __construct($name, $title)
67
    {
68
        $name = 'doCustomAction[' . $name . ']';
69
        $this->title = $title;
70
        $this->name = $name;
71
72
        parent::__construct($name, $title);
73
    }
74
75
    public function Type()
76
    {
77
        return 'modal-action';
78
    }
79
80
    /**
81
     * For template usage
82
     * @return bool
83
     */
84
    public function getOverlayTriggersClose()
85
    {
86
        return PureModal::getOverlayTriggersCloseConfig();
87
    }
88
89
    /**
90
     * If the modal is in the body, it needs to go back to the form to submit properly
91
     * @return string
92
     */
93
    public function SubmitOnClickScript()
94
    {
95
        if (!PureModal::getMoveModalScript()) {
96
            return '';
97
        }
98
        $formId = PureModal::config()->edit_form_id;
99
        return "event.stopPropagation();var f=document.getElementById('$formId');var m=this.closest('.pure-modal');m.style.display='none';f.appendChild(m);f.submit();";
100
    }
101
102
    /**
103
     * Move modal when clicking on the open button. Trigger only once.
104
     * @return string
105
     */
106
    public static function getMoveModalScript()
107
    {
108
        if (!PureModal::config()->move_modal_to_body) {
109
            return '';
110
        }
111
        $formId = PureModal::config()->edit_form_id;
112
        return "document.getElementById('$formId').appendChild(this.parentElement.querySelector('.pure-modal'));this.onclick=null;";
113
    }
114
115
    /**
116
     * @return array<string,mixed>
117
     */
118
    public function getAttributes()
119
    {
120
        $attrs = [];
121
        // Move modal to form to avoid nesting issues
122
        // We cannot append to body because this breaks form submission
123
        $attrs['onclick'] = self::getMoveModalScript();
124
        return $attrs;
125
    }
126
127
    /**
128
     * Get the title with icon if set
129
     *
130
     * @return string
131
     */
132
    protected function getButtonTitle()
133
    {
134
        $title = $this->title;
135
        if ($this->buttonIcon) {
136
            $title = '<span class="font-icon-' . $this->buttonIcon . '"></span> ' . $title;
137
        }
138
        return $title;
139
    }
140
141
    /**
142
     * Get the dialog button title with icon if set
143
     *
144
     * @return string
145
     */
146
    protected function getDialogButtonTitle()
147
    {
148
        $title = $this->dialogButtonTitle ?: $this->title;
149
        if ($this->buttonIcon) {
150
            $title = '<span class="font-icon-' . $this->buttonIcon . '"></span> ' . $title;
151
        }
152
        return $title;
153
    }
154
155
    /**
156
     * Set dialog button customised button title
157
     *
158
     * @param string $value
159
     * @return self
160
     */
161
    public function setDialogButtonTitle($value)
162
    {
163
        $this->dialogButtonTitle = $value;
164
        return $this;
165
    }
166
167
    /**
168
     * Get an icon for this button
169
     *
170
     * @return string
171
     */
172
    public function getButtonIcon()
173
    {
174
        return $this->buttonIcon;
175
    }
176
177
    /**
178
     * Set an icon for this button
179
     *
180
     * Feel free to use SilverStripeIcons constants
181
     *
182
     * @param string $buttonIcon An icon for this button
183
     * @return $this
184
     */
185
    public function setButtonIcon(string $buttonIcon)
186
    {
187
        $this->buttonIcon = $buttonIcon;
188
        return $this;
189
    }
190
191
    /**
192
     * Set a new type of btn-something. It will remove any existing btn- class
193
     * @param string $type Leave blank to simply remove default button type
194
     * @return $this
195
     */
196
    public function setButtonType($type = null)
197
    {
198
        if ($this->extraClasses) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->extraClasses of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
199
            foreach ($this->extraClasses as $k => $v) {
200
                if (strpos($k, 'btn-') !== false) {
201
                    unset($this->extraClasses[$k]);
202
                }
203
            }
204
        }
205
        if ($type) {
206
            $btn = "btn-$type";
207
            $this->extraClasses[$btn] = $btn;
208
        }
209
        return $this;
210
    }
211
212
    /**
213
     * Get whether it must display the dialog button
214
     *
215
     * @return boolean
216
     */
217
    protected function getShowDialogButton()
218
    {
219
        return $this->showDialogButton;
220
    }
221
222
    /**
223
     * Set whether it must display the dialog button
224
     *
225
     * @param string $value
226
     * @return self
227
     */
228
    public function setShowDialogButton($value)
229
    {
230
        $this->showDialogButton = !!$value;
231
        return $this;
232
    }
233
234
    /**
235
     * Get the value of fieldList
236
     * @return FieldList
237
     */
238
    public function getFieldList()
239
    {
240
        return $this->fieldList;
241
    }
242
243
    /**
244
     * Set the value of fieldList
245
     *
246
     * @param FieldList $fieldList
247
     * @return $this
248
     */
249
    public function setFieldList(FieldList $fieldList)
250
    {
251
        $this->fieldList = $fieldList;
252
        foreach ($fieldList->dataFields() as $f) {
253
            $f->addExtraClass('no-change-track');
254
        }
255
        return $this;
256
    }
257
258
    /**
259
     * Make sure our nested fieldlist is bound to form
260
     *
261
     * @param Form $form
262
     * @return $this
263
     */
264
    public function setForm($form)
265
    {
266
        //@link https://github.com/unclecheese/silverstripe-display-logic/pull/155#issuecomment-1540966157
267
        /** @var FieldList|null $fieldList */
268
        $fieldList = $this->fieldList;
269
        if ($fieldList) {
270
            foreach ($fieldList as $field) {
271
                $field->setForm($form);
272
            }
273
        }
274
        return parent::setForm($form);
275
    }
276
277
    /**
278
     * Get the dropUp value
279
     * Called by ActionsGridFieldItemRequest to determine placement
280
     *
281
     * @see https://github.com/lekoala/silverstripe-cms-actions
282
     * @return bool
283
     */
284
    public function getDropUp()
285
    {
286
        return $this->dropUp;
287
    }
288
289
    /**
290
     * Set the value of dropUp
291
     * You might want to call also setButtonType(null) for better styles
292
     *
293
     * @see https://github.com/lekoala/silverstripe-cms-actions
294
     * @param bool $is
295
     * @return $this
296
     */
297
    public function setDropUp($is)
298
    {
299
        $this->dropUp = !!$is;
300
        return $this;
301
    }
302
303
    /**
304
     * Required for cms-actions
305
     * @return string
306
     */
307
    public function actionName()
308
    {
309
        return rtrim(str_replace('doCustomAction[', '', $this->name), ']');
310
    }
311
312
    /**
313
     * Get the value of shouldRefresh
314
     * @return mixed
315
     */
316
    public function getShouldRefresh()
317
    {
318
        return $this->shouldRefresh;
319
    }
320
321
    /**
322
     * Set the value of shouldRefresh
323
     *
324
     * @param mixed $shouldRefresh
325
     * @return $this
326
     */
327
    public function setShouldRefresh($shouldRefresh)
328
    {
329
        $this->shouldRefresh = $shouldRefresh;
330
        return $this;
331
    }
332
333
    /**
334
     * @return string
335
     */
336
    public function getModalID()
337
    {
338
        return 'modal_' . $this->name;
339
    }
340
341
    /**
342
     * @return string
343
     */
344
    public function getTitle()
345
    {
346
        return $this->title;
347
    }
348
349
    /**
350
     * @return bool
351
     */
352
    public function getFillHeight()
353
    {
354
        return $this->fillHeight;
355
    }
356
357
    /**
358
     * @param bool $fillHeight
359
     * @return $this
360
     */
361
    public function setFillHeight($fillHeight)
362
    {
363
        $this->fillHeight = $fillHeight;
364
        return $this;
365
    }
366
}
367