Completed
Push — master ( 1db3b4...e2f1ad )
by Song
02:46
created

Action::getHandleRoute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Actions;
4
5
use Encore\Admin\Admin;
6
use Encore\Admin\Form\Field;
7
use Illuminate\Contracts\Support\Renderable;
8
use Illuminate\Http\Request;
9
10
/**
11
 * @method $this success($title, $text = '', $options = [])
12
 * @method $this error($title, $text = '', $options = [])
13
 * @method $this warning($title, $text = '', $options = [])
14
 * @method $this info($title, $text = '', $options = [])
15
 * @method $this question($title, $text = '', $options = [])
16
 * @method $this confirm($title, $text = '', $options = [])
17
 * @method Field\Text           text($column, $label = '')
18
 * @method Field\Email          email($column, $label = '')
19
 * @method Field\Integer        integer($column, $label = '')
20
 * @method Field\Ip             ip($column, $label = '')
21
 * @method Field\Url            url($column, $label = '')
22
 * @method Field\Password       password($column, $label = '')
23
 * @method Field\Mobile         mobile($column, $label = '')
24
 * @method Field\Textarea       textarea($column, $label = '')
25
 * @method Field\Select         select($column, $label = '')
26
 * @method Field\MultipleSelect multipleSelect($column, $label = '')
27
 * @method Field\Checkbox       checkbox($column, $label = '')
28
 * @method Field\Radio          radio($column, $label = '')
29
 * @method Field\File           file($column, $label = '')
30
 * @method Field\Image          image($column, $label = '')
31
 * @method Field\Date           date($column, $label = '')
32
 * @method Field\Datetime       datetime($column, $label = '')
33
 * @method Field\Time           time($column, $label = '')
34
 * @method Field\Hidden         hidden($column, $label = '')
35
 */
36
abstract class Action implements Renderable
37
{
38
    use Authorizable;
39
40
    /**
41
     * @var Response
42
     */
43
    protected $response;
44
45
    /**
46
     * @var string
47
     */
48
    protected $selector;
49
50
    /**
51
     * @var string
52
     */
53
    public $event = 'click';
54
55
    /**
56
     * @var string
57
     */
58
    protected $method = 'POST';
59
60
    /**
61
     * @var array
62
     */
63
    protected $attributes = [];
64
65
    /**
66
     * @var string
67
     */
68
    public $selectorPrefix = '.action-';
69
70
    /**
71
     * @var Interactor\Interactor
72
     */
73
    protected $interactor;
74
75
    /**
76
     * @var array
77
     */
78
    protected static $selectors = [];
79
80
    /**
81
     * @var string
82
     */
83
    public $name;
84
85
    /**
86
     * Action constructor.
87
     */
88
    public function __construct()
89
    {
90
        $this->initInteractor();
91
    }
92
93
    /**
94
     * @throws \Exception
95
     */
96
    protected function initInteractor()
97
    {
98
        if ($hasForm = method_exists($this, 'form')) {
99
            $this->interactor = new Interactor\Form($this);
100
        }
101
102
        if ($hasDialog = method_exists($this, 'dialog')) {
103
            $this->interactor = new Interactor\Dialog($this);
104
        }
105
106
        if ($hasForm && $hasDialog) {
107
            throw new \Exception('Can only define one of the methods in `form` and `dialog`');
108
        }
109
    }
110
111
    /**
112
     * Get batch action title.
113
     *
114
     * @return string
115
     */
116
    public function name()
117
    {
118
        return $this->name;
119
    }
120
121
    /**
122
     * @param string $prefix
123
     *
124
     * @return mixed|string
125
     */
126
    public function selector($prefix)
127
    {
128
        if (is_null($this->selector)) {
129
            return static::makeSelector(get_called_class(), $prefix);
130
        }
131
132
        return $this->selector;
133
    }
134
135
    /**
136
     * @param string $class
137
     * @param string $prefix
138
     *
139
     * @return string
140
     */
141
    public static function makeSelector($class, $prefix)
142
    {
143
        if (!isset(static::$selectors[$class])) {
144
            static::$selectors[$class] = uniqid($prefix).mt_rand(1000, 9999);
145
        }
146
147
        return static::$selectors[$class];
148
    }
149
150
    /**
151
     * @param string $name
152
     * @param string $value
153
     *
154
     * @return $this
155
     */
156
    public function attribute($name, $value)
157
    {
158
        $this->attributes[$name] = $value;
159
160
        return $this;
161
    }
162
163
    /**
164
     * Format the field attributes.
165
     *
166
     * @return string
167
     */
168 View Code Duplication
    protected function formatAttributes()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
    {
170
        $html = [];
171
172
        foreach ($this->attributes as $name => $value) {
173
            $html[] = $name.'="'.e($value).'"';
174
        }
175
176
        return implode(' ', $html);
177
    }
178
179
    /**
180
     * @return string
181
     */
182
    protected function getElementClass()
183
    {
184
        return ltrim($this->selector($this->selectorPrefix), '.');
185
    }
186
187
    /**
188
     * @return Response
189
     */
190
    public function response()
191
    {
192
        if (is_null($this->response)) {
193
            $this->response = new Response();
194
        }
195
196
        if (method_exists($this, 'dialog')) {
197
            $this->response->swal();
198
        } else {
199
            $this->response->toastr();
200
        }
201
202
        return $this->response;
203
    }
204
205
    /**
206
     * @return string
207
     */
208
    public function getMethod()
209
    {
210
        return $this->method;
211
    }
212
213
    /**
214
     * @return mixed
215
     */
216
    public function getCalledClass()
217
    {
218
        return str_replace('\\', '_', get_called_class());
219
    }
220
221
    /**
222
     * @return string
223
     */
224
    public function getHandleRoute()
225
    {
226
        return admin_url('_handle_action_');
227
    }
228
229
    /**
230
     * @return string
231
     */
232
    protected function getModelClass()
233
    {
234
        return '';
235
    }
236
237
    /**
238
     * @return array
239
     */
240
    public function parameters()
241
    {
242
        return [];
243
    }
244
245
    /**
246
     * @param Request $request
247
     *
248
     * @return $this
249
     */
250
    public function validate(Request $request)
251
    {
252
        if ($this->interactor instanceof Interactor\Form) {
253
            $this->interactor->validate($request);
254
        }
255
256
        return $this;
257
    }
258
259
    /**
260
     * @return mixed
261
     */
262
    protected function addScript()
263
    {
264
        if (!is_null($this->interactor)) {
265
            return $this->interactor->addScript();
266
        }
267
268
        $parameters = json_encode($this->parameters());
269
270
        $script = <<<SCRIPT
271
272
(function ($) {
273
    $('{$this->selector($this->selectorPrefix)}').off('{$this->event}').on('{$this->event}', function() {
274
        var data = $(this).data();
275
        var target = $(this);
276
        Object.assign(data, {$parameters});
277
        {$this->actionScript()}
278
        {$this->buildActionPromise()}
279
        {$this->handleActionPromise()}
280
    });
281
})(jQuery);
282
283
SCRIPT;
284
285
        Admin::script($script);
286
    }
287
288
    /**
289
     * @return string
290
     */
291
    public function actionScript()
292
    {
293
        return '';
294
    }
295
296
    /**
297
     * @return string
298
     */
299
    protected function buildActionPromise()
300
    {
301
        return <<<SCRIPT
302
        var process = new Promise(function (resolve,reject) {
303
            
304
            Object.assign(data, {
305
                _token: $.admin.token,
306
                _action: '{$this->getCalledClass()}',
307
            });
308
        
309
            $.ajax({
310
                method: '{$this->method}',
311
                url: '{$this->getHandleRoute()}',
312
                data: data,
313
                success: function (data) {
314
                    resolve([data, target]);
315
                },
316
                error:function(request){
317
                    reject(request);
318
                }
319
            });
320
        });
321
322
SCRIPT;
323
    }
324
325
    /**
326
     * @return string
327
     */
328
    public function handleActionPromise()
329
    {
330
        $resolve = <<<'SCRIPT'
331
var actionResolver = function (data) {
332
333
            var response = data[0];
334
            var target   = data[1];
335
                
336
            if (typeof response !== 'object') {
337
                return $.admin.swal({type: 'error', title: 'Oops!'});
338
            }
339
            
340
            var then = function (then) {
341
                if (then.action == 'refresh') {
342
                    $.admin.reload();
343
                }
344
                
345
                if (then.action == 'download') {
346
                    window.open(then.value, '_blank');
347
                }
348
                
349
                if (then.action == 'redirect') {
350
                    $.admin.redirect(then.value);
351
                }
352
            };
353
            
354
            if (typeof response.html === 'string') {
355
                target.html(response.html);
356
            }
357
358
            if (typeof response.swal === 'object') {
359
                $.admin.swal(response.swal);
360
            }
361
            
362
            if (typeof response.toastr === 'object') {
363
                $.admin.toastr[response.toastr.type](response.toastr.content, '', response.toastr.options);
364
            }
365
            
366
            if (response.then) {
367
              then(response.then);
368
            }
369
        };
370
        
371
        var actionCatcher = function (request) {
372
            if (request && typeof request.responseJSON === 'object') {
373
                $.admin.toastr.error(request.responseJSON.message, '', {positionClass:"toast-bottom-center", timeOut: 10000}).css("width","500px")
374
            }
375
        };
376
SCRIPT;
377
378
        Admin::script($resolve);
379
380
        return <<<'SCRIPT'
381
process.then(actionResolver).catch(actionCatcher);
382
SCRIPT;
383
    }
384
385
    /**
386
     * @param string $method
387
     * @param array  $arguments
388
     *
389
     * @throws \Exception
390
     *
391
     * @return mixed
392
     */
393
    public function __call($method, $arguments = [])
394
    {
395
        if (in_array($method, Interactor\Interactor::$elements)) {
396
            return $this->interactor->{$method}(...$arguments);
397
        }
398
399
        throw new \BadMethodCallException("Method {$method} does not exist.");
400
    }
401
402
    /**
403
     * @return string
404
     */
405
    public function html()
406
    {
407
    }
408
409
    /**
410
     * @return mixed
411
     */
412
    public function render()
413
    {
414
        $this->addScript();
415
416
        $content = $this->html();
417
418
        if ($content && $this->interactor instanceof Interactor\Form) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $content of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
419
            return $this->interactor->addElementAttr($content, $this->selector);
420
        }
421
422
        return $this->html();
423
    }
424
}
425