JsExpr::toInt()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
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 0
dl 0
loc 4
rs 10
1
<?php
2
3
/**
4
 * JsExpr.php
5
 *
6
 * An expression to be formatted in json, that represents a call to a js function or selector.
7
 *
8
 * @package jaxon-core
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2024 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
14
15
namespace Jaxon\Script;
16
17
use Jaxon\Plugin\Response\Dialog\DialogCommand;
18
use Jaxon\Script\Call\Attr;
19
use Jaxon\Script\Call\Event;
20
use Jaxon\Script\Call\Func;
21
use Jaxon\Script\Call\Parameter;
22
use Jaxon\Script\Call\ParameterInterface;
23
use JsonSerializable;
24
use Stringable;
25
26
use function array_map;
27
use function array_shift;
28
use function count;
29
use function func_get_args;
30
use function implode;
31
use function is_a;
32
use function json_encode;
33
34
class JsExpr implements ParameterInterface
35
{
36
    /**
37
     * Dialog for confirm questions and messages
38
     *
39
     * @var DialogCommand
40
     */
41
    protected $xDialog;
42
43
    /**
44
     * The actions to be applied on the selected element
45
     *
46
     * @var array
47
     */
48
    protected $aCalls = [];
49
50
    /**
51
     * The arguments of the else() calls
52
     *
53
     * @var array
54
     */
55
    protected $aMessage = [];
56
57
    /**
58
     * A condition to check before making the call
59
     *
60
     * @var array
61
     */
62
    protected $aCondition = [];
63
64
    /**
65
     * The arguments of the confirm() call
66
     *
67
     * @var array
68
     */
69
    protected $aConfirm = [];
70
71
    /**
72
     * Convert the expression value to int
73
     *
74
     * @var bool
75
     */
76
    protected $bToInt = false;
77
78
    /**
79
     * @param DialogCommand $xDialog
80
     */
81
    public function __construct(DialogCommand $xDialog, ...$aCalls)
82
    {
83
        $this->xDialog = $xDialog;
84
        $this->aCalls = $aCalls;
85
    }
86
87
    /**
88
     * Get the first function in the calls
89
     *
90
     * @return Func|null
91
     */
92
    public function func(): ?Func
93
    {
94
        foreach($this->aCalls as $xCall)
95
        {
96
            if(is_a($xCall, Func::class))
97
            {
98
                return $xCall;
99
            }
100
        }
101
        return null;
102
    }
103
104
    /**
105
     * Add a call to a js function on the current object
106
     *
107
     * @param string  $sMethod
108
     * @param array  $aArguments
109
     *
110
     * @return self
111
     */
112
    public function __call(string $sMethod, array $aArguments): self
113
    {
114
        $bHasParent = count($this->aCalls) > 0;
115
        // Append the action into the array
116
        $this->aCalls[] = new Func($sMethod, $aArguments, $bHasParent);
117
        return $this;
118
    }
119
120
    /**
121
     * Get the value of an attribute of the current object
122
     *
123
     * @param string  $sAttribute
124
     *
125
     * @return self
126
     */
127
    public function __get(string $sAttribute): self
128
    {
129
        $bHasParent = count($this->aCalls) > 0;
130
        // Append the action into the array
131
        $this->aCalls[] = Attr::get($sAttribute, $bHasParent);
132
        return $this;
133
    }
134
135
    /**
136
     * Set the value of an attribute of the current object
137
     *
138
     * @param string $sAttribute
139
     * @param mixed $xValue
140
     *
141
     * @return void
142
     */
143
    public function __set(string $sAttribute, $xValue)
144
    {
145
        $bHasParent = count($this->aCalls) > 0;
146
        // Append the action into the array
147
        $this->aCalls[] = Attr::set($sAttribute, $xValue, $bHasParent);
148
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Jaxon\Script\JsExpr which is incompatible with the documented return type void.
Loading history...
149
    }
150
151
    /**
152
     * Set an event handler on the selected elements
153
     *
154
     * @param string $sName
155
     * @param JsExpr $xHandler
156
     *
157
     * @return self
158
     */
159
    public function on(string $sName, JsExpr $xHandler): self
160
    {
161
        $this->aCalls[] = new Event($sName, $xHandler);
162
        return $this;
163
    }
164
165
    /**
166
     * Set a "click" event handler on the selected elements
167
     *
168
     * @param JsExpr $xHandler
169
     *
170
     * @return self
171
     */
172
    public function click(JsExpr $xHandler): self
173
    {
174
        return $this->on('click', $xHandler);
175
    }
176
177
    /**
178
     * @param array $aArgs
179
     *
180
     * @return array
181
     */
182
    private function getArgs(array $aArgs): array
183
    {
184
        array_shift($aArgs);
185
        return $aArgs;
186
    }
187
188
    /**
189
     * Show a message if the condition to the call is not met
190
     *
191
     * @param string $sMessage  The message to show
192
     *
193
     * @return self
194
     */
195
    public function elseShow(string $sMessage): self
196
    {
197
        $this->aMessage = $this->xDialog->warning($sMessage, $this->getArgs(func_get_args()));
198
        return $this;
199
    }
200
201
    /**
202
     * Show an information message if the condition to the call is not met
203
     *
204
     * @param string $sMessage  The message to show
205
     *
206
     * @return self
207
     */
208
    public function elseInfo(string $sMessage): self
209
    {
210
        $this->aMessage = $this->xDialog->info($sMessage, $this->getArgs(func_get_args()));
211
        return $this;
212
    }
213
214
    /**
215
     * Show a success message if the condition to the call is not met
216
     *
217
     * @param string $sMessage  The message to show
218
     *
219
     * @return self
220
     */
221
    public function elseSuccess(string $sMessage): self
222
    {
223
        $this->aMessage = $this->xDialog->success($sMessage, $this->getArgs(func_get_args()));
224
        return $this;
225
    }
226
227
    /**
228
     * Show a warning message if the condition to the call is not met
229
     *
230
     * @param string $sMessage  The message to show
231
     *
232
     * @return self
233
     */
234
    public function elseWarning(string $sMessage): self
235
    {
236
        $this->aMessage = $this->xDialog->warning($sMessage, $this->getArgs(func_get_args()));
237
        return $this;
238
    }
239
240
    /**
241
     * Show an error message if the condition to the call is not met
242
     *
243
     * @param string $sMessage  The message to show
244
     *
245
     * @return self
246
     */
247
    public function elseError(string $sMessage): self
248
    {
249
        $this->aMessage = $this->xDialog->error($sMessage, $this->getArgs(func_get_args()));
250
        return $this;
251
    }
252
253
    /**
254
     * Add a confirmation question to the request
255
     *
256
     * @param string $sQuestion    The question to ask
257
     *
258
     * @return self
259
     */
260
    public function confirm(string $sQuestion): self
261
    {
262
        $this->aConfirm = $this->xDialog->confirm($sQuestion, $this->getArgs(func_get_args()));
263
        return $this;
264
    }
265
266
    /**
267
     * Check if a value is equal to another before sending the request
268
     *
269
     * @param mixed $xValue1    The first value to compare
270
     * @param mixed $xValue2    The second value to compare
271
     *
272
     * @return self
273
     */
274
    public function ifeq($xValue1, $xValue2): self
275
    {
276
        $this->aCondition = ['eq', Parameter::make($xValue1), Parameter::make($xValue2)];
277
        return $this;
278
    }
279
280
    /**
281
     * Check if a value is equal to another before sending the request
282
     *
283
     * @param mixed $xValue1    The first value to compare
284
     * @param mixed $xValue2    The second value to compare
285
     *
286
     * @return self
287
     */
288
    public function ifteq($xValue1, $xValue2): self
289
    {
290
        $this->aCondition = ['teq', Parameter::make($xValue1), Parameter::make($xValue2)];
291
        return $this;
292
    }
293
294
    /**
295
     * Check if a value is not equal to another before sending the request
296
     *
297
     * @param mixed $xValue1    The first value to compare
298
     * @param mixed $xValue2    The second value to compare
299
     *
300
     * @return self
301
     */
302
    public function ifne($xValue1, $xValue2): self
303
    {
304
        $this->aCondition = ['ne', Parameter::make($xValue1), Parameter::make($xValue2)];
305
        return $this;
306
    }
307
308
    /**
309
     * Check if a value is not equal to another before sending the request
310
     *
311
     * @param mixed $xValue1    The first value to compare
312
     * @param mixed $xValue2    The second value to compare
313
     *
314
     * @return self
315
     */
316
    public function ifnte($xValue1, $xValue2): self
317
    {
318
        $this->aCondition = ['nte', Parameter::make($xValue1), Parameter::make($xValue2)];
319
        return $this;
320
    }
321
322
    /**
323
     * Check if a value is greater than another before sending the request
324
     *
325
     * @param mixed $xValue1    The first value to compare
326
     * @param mixed $xValue2    The second value to compare
327
     *
328
     * @return self
329
     */
330
    public function ifgt($xValue1, $xValue2): self
331
    {
332
        $this->aCondition = ['gt', Parameter::make($xValue1), Parameter::make($xValue2)];
333
        return $this;
334
    }
335
336
    /**
337
     * Check if a value is greater or equal to another before sending the request
338
     *
339
     * @param mixed $xValue1    The first value to compare
340
     * @param mixed $xValue2    The second value to compare
341
     *
342
     * @return self
343
     */
344
    public function ifge($xValue1, $xValue2): self
345
    {
346
        $this->aCondition = ['ge', Parameter::make($xValue1), Parameter::make($xValue2)];
347
        return $this;
348
    }
349
350
    /**
351
     * Check if a value is lower than another before sending the request
352
     *
353
     * @param mixed $xValue1    The first value to compare
354
     * @param mixed $xValue2    The second value to compare
355
     *
356
     * @return self
357
     */
358
    public function iflt($xValue1, $xValue2): self
359
    {
360
        $this->aCondition = ['lt', Parameter::make($xValue1), Parameter::make($xValue2)];
361
        return $this;
362
    }
363
364
    /**
365
     * Check if a value is lower or equal to another before sending the request
366
     *
367
     * @param mixed $xValue1    The first value to compare
368
     * @param mixed $xValue2    The second value to compare
369
     *
370
     * @return self
371
     */
372
    public function ifle($xValue1, $xValue2): self
373
    {
374
        $this->aCondition = ['le', Parameter::make($xValue1), Parameter::make($xValue2)];
375
        return $this;
376
    }
377
378
    /**
379
     * Add a condition to the request
380
     *
381
     * The request is sent only if the condition is true.
382
     *
383
     * @param mixed $xCondition    The condition to check
384
     *
385
     * @return self
386
     */
387
    public function when($xCondition): self
388
    {
389
        return $this->ifeq(true, $xCondition);
390
    }
391
392
    /**
393
     * Add a condition to the request
394
     *
395
     * The request is sent only if the condition is false.
396
     *
397
     * @param mixed $xCondition    The condition to check
398
     *
399
     * @return self
400
     */
401
    public function unless($xCondition): self
402
    {
403
        return $this->ifeq(false, $xCondition);
404
    }
405
406
    /**
407
     * @return self
408
     */
409
    public function toInt(): self
410
    {
411
        $this->bToInt = true;
412
        return $this;
413
    }
414
415
    /**
416
     * return array
417
     */
418
    protected function toIntCall(): array
419
    {
420
        return [
421
            '_type' => 'method',
422
            '_name' => 'toInt',
423
            'args' => [],
424
        ];
425
    }
426
427
    /**
428
     * @inheritDoc
429
     */
430
    public function getType(): string
431
    {
432
        return 'expr';
433
    }
434
435
    /**
436
     * Convert this call to array, when converting the response into json.
437
     *
438
     * @return array
439
     */
440
    public function jsonSerialize(): array
441
    {
442
        $aCalls = array_map(function(JsonSerializable $xCall) {
443
            return $xCall->jsonSerialize();
444
        }, $this->aCalls);
445
        if($this->bToInt)
446
        {
447
            $aCalls[] = $this->toIntCall();
448
        }
449
450
        $aJsExpr = ['_type' => $this->getType(), 'calls' => $aCalls];
451
        if(($this->aConfirm))
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->aConfirm 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...
452
        {
453
            $aJsExpr['question'] = $this->aConfirm;
454
        }
455
        if(($this->aCondition))
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->aCondition 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...
456
        {
457
            $aJsExpr['condition'] = $this->aCondition;
458
        }
459
        if(($this->aMessage))
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->aMessage 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...
460
        {
461
            $aJsExpr['message'] = $this->aMessage;
462
        }
463
        return $aJsExpr;
464
    }
465
466
    /**
467
     * Returns a call to jaxon as a string
468
     *
469
     * @return string
470
     */
471
    public function __toString(): string
472
    {
473
        return 'jaxon.exec(' . json_encode($this->jsonSerialize()) . ')';
474
    }
475
476
    /**
477
     * Returns the js code of the call
478
     *
479
     * @return string
480
     */
481
    public function raw(): string
482
    {
483
        $sScript = implode('.', array_map(function(Stringable $xParam) {
484
            return $xParam->__toString();
485
        }, $this->aCalls));
486
        return $this->bToInt ? "parseInt($sScript)" : $sScript;
487
    }
488
}
489