Passed
Push — master ( 48e2e4...58f05f )
by Marwan
08:52
created

Flash::__call()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 10
eloc 4
nc 1
nop 2
1
<?php
2
3
/**
4
 * @author Marwan Al-Soltany <[email protected]>
5
 * @copyright Marwan Al-Soltany 2021
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace MAKS\Velox\Backend\Session;
13
14
use MAKS\Velox\Backend\Globals;
15
use MAKS\Velox\Frontend\HTML;
16
use MAKS\Velox\Helper\Misc;
17
18
/**
19
 * A class that offers a simple interface to write flash messages.
20
 *
21
 * Example:
22
 * ```
23
 * // write a flash message
24
 * $flash = new Flash();
25
 * $flash->message('Some message!');
26
 *
27
 * // write a flash message that will be rendered immediately
28
 * $flash->message('Some other message!', 'success', true);
29
 *
30
 * // write a flash message with a predefined type
31
 * $flash->error('Some error!', true);
32
 *
33
 * // write a flash message with your own type
34
 * $flash->yourCustomType('Custom type!');
35
 *
36
 * // render the flash messages
37
 * $flash->render();
38
 *
39
 * // render the flash messages using a custom callback
40
 * $flash->render(function ($text, $type) {
41
 *      return sprintf('<div class="alert alert-%s">%s</div>', $type, $text);
42
 * });
43
 * ```
44
 *
45
 * @package Velox\Backend\Session
46
 * @since 1.5.4
47
 *
48
 * @method static success(string $text, bool $now = false) Adds a `success` message to the flash.
49
 * @method static info(string $text, bool $now = false) Adds an `info` message to the flash.
50
 * @method static warning(string $text, bool $now = false) Adds a `warning` message to the flash.
51
 * @method static error(string $text, bool $now = false) Adds an `error` message to the flash.
52
 * @method static anyType(string $text, bool $now = false) Adds a message of `anyType` to the flash. `anyType` is user defined and will be used as a CSS class if the default rendering callback is used (`camelCase` will be changed to `kebab-case` automatically).
53
 */
54
class Flash
55
{
56
    private string $name;
57
58
    private array $messages;
59
60
61
    /**
62
     * Class constructor.
63
     *
64
     * @param string|null $name The name of the flash messages store (session key).
65
     */
66 1
    public function __construct(?string $name = null)
67
    {
68 1
        $this->name     = $name ?? '_flash';
69 1
        $this->messages = Globals::getSession($this->name) ?? [];
70
71 1
        Globals::setSession($this->name, []);
72 1
    }
73
74
    /**
75
     * Makes the class callable as a function, the call is forwarded to `self::message()`.
76
     */
77 1
    public function __invoke()
78
    {
79 1
        return $this->message(...func_get_args());
80
    }
81
82
    /**
83
     * Aliases some magic methods for `self::message()`.
84
     */
85 1
    public function __call(string $method, array $arguments)
86
    {
87 1
        return $this->message(
88 1
            Misc::transform($method, 'kebab'),
89 1
            $arguments[0] ?? '',
90 1
            $arguments[1] ?? false
91
        );
92
    }
93
94
    /**
95
     * Returns the HTML containing the flash messages.
96
     */
97 1
    public function __toString()
98
    {
99 1
        return $this->render();
100
    }
101
102
103
    /**
104
     * Writes a flash message to the session.
105
     *
106
     * @param string $type Message type.
107
     * @param string $text Message text.
108
     * @param bool $now [optional] Whether to write and make the message available for rendering immediately or wait for the next request.
109
     *
110
     * @return $this
111
     */
112 1
    public function message(string $type, string $text, bool $now = false)
113
    {
114 1
        $id = uniqid(md5($text) . '-');
115
116 1
        if ($now) {
117 1
            $this->messages[$id] = [
118 1
                'type' => $type,
119 1
                'text' => $text
120
            ];
121
122 1
            return $this;
123
        }
124
125 1
        Globals::setSession($this->name . '.' . $id, [
126 1
            'type' => $type,
127 1
            'text' => $text
128
        ]);
129
130 1
        return $this;
131
    }
132
133
    /**
134
     * Renders the flash messages using the default callback or the passed one.
135
     * This method will be called automatically if the object is casted to a string.
136
     *
137
     * @param callable|null $callback Rendering callback. The callback will be passed: `$text`, `$type`
138
     *
139
     * @return string The result of the passed callback or the default one.
140
     */
141 1
    public function render(?callable $callback = null): string
142
    {
143 1
        $callback = $callback ?? function ($text, $type) {
144 1
            return HTML::div($text, [
145 1
                'class' => 'flash-message ' . $type
146
            ]);
147 1
        };
148
149 1
        $html = '';
150
151 1
        foreach ($this->messages as $message) {
152 1
            $html .= $callback($message['text'], $message['type']);
153
        }
154
155 1
        return $html;
156
    }
157
}
158