1 <?php
2
3 /*
4 * This file is part of the Brickrouge package.
5 *
6 * (c) Olivier Laviale <olivier.laviale@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Brickrouge;
13
14 use ICanBoogie\Errors;
15
16 /**
17 * A `<DIV.alert>` element.
18 */
19 class Alert extends Element
20 {
21 /**
22 * The context of the alert, one of "error", "success" or "info".
23 *
24 * @var string
25 */
26 const CONTEXT = '#alert-context';
27 const CONTEXT_SUCCESS = 'success';
28 const CONTEXT_INFO = 'info';
29 const CONTEXT_ERROR = 'error';
30
31 /**
32 * The heading of the alert.
33 *
34 * @var string
35 */
36 const HEADING = '#alert-heading';
37
38 /**
39 * Set to `true` for undissmisable alerts.
40 *
41 * @var string
42 */
43 const UNDISSMISABLE = '#alert-undissmisable';
44
45 const DISSMISS_BUTTON = '<button type="button" class="close" data-dismiss="alert">×</button>';
46
47 /**
48 * Alert message.
49 *
50 * @var string|array|\ICanBoogie\Errors
51 */
52 protected $message;
53
54 /**
55 * Alert type, one of "error", "success" or "info".
56 *
57 * @var string
58 */
59 protected $alert_type;
60
61 /**
62 * Creates a `<DIV.alert>` element.
63 *
64 * @param string|array|\ICanBoogie\Errors $message The alert message is provided as a string,
65 * an array of strings or a {@link \ICanBoogie\Errors} object.
66 *
67 * If the message is provided as a string it is used as is. If the message is provided as an
68 * array each value of the array is considered as a message. If the message is provided as
69 * an {@link Errors} object each entry of the object is considered as a message.
70 *
71 * Each message is wrapped in a `<P>` element and they are concatenated to create the final
72 * message.
73 *
74 * If the message is an instance of {@link \ICanBoogie\Errors} the {@link CONTEXT} attribute is
75 * set to "error" in the initial attributes.
76 *
77 * @param array $attributes Additional attributes.
78 */
79 public function __construct($message, array $attributes=array())
80 {
81 $this->message = $message;
82
83 parent::__construct
84 (
85 'div', $attributes + array
86 (
87 self::CONTEXT => $message instanceof Errors ? 'error' : null,
88
89 'class' => 'alert'
90 )
91 );
92 }
93
94 /**
95 * Adds the `alert-error`, `alert-info` and `alert-success` class names according to the
96 * {@link CONTEXT} attribute.
97 *
98 * Adds the `alert-block` class name if the {@link HEADING} attribute is defined.
99 *
100 * Adds the `undissmisable` class name if the {@link UNDISSMISABLE} attribute is true.
101 */
102 protected function alter_class_names(array $class_names)
103 {
104 $class_names = parent::alter_class_names($class_names);
105
106 $context = $this[self::CONTEXT];
107
108 if ($context)
109 {
110 $class_names['alert-' . $context] = true;
111 }
112
113 if ($this[self::HEADING])
114 {
115 $class_names['alert-block'] = true;
116 }
117
118 if ($this[self::UNDISSMISABLE])
119 {
120 $class_names['undissmisable'] = true;
121 }
122
123 return $class_names;
124 }
125
126 /**
127 * @throws ElementIsEmpty if the message is empty.
128 */
129 public function render_inner_html()
130 {
131 $heading = $this[self::HEADING];
132
133 if ($heading)
134 {
135 $heading = '<h4 class="alert-heading">' . escape($heading) . '</h4>';
136 }
137
138 $message = $this->message;
139
140 if (!$message)
141 {
142 throw new ElementIsEmpty;
143 }
144 if ($message instanceof Errors)
145 {
146 $errors = $message;
147
148 if (!count($errors))
149 {
150 throw new ElementIsEmpty;
151 }
152
153 $message = '';
154
155 foreach ($errors as $error)
156 {
157 if ($error === true)
158 {
159 continue;
160 }
161
162 $message .= '<p>' . $error . '</p>';
163 }
164 }
165 else if (is_array($message))
166 {
167 $message = '<p>' . implode('</p><p>', $message) . '</p>';
168 }
169
170 $dismiss = '';
171
172 if (!$this[self::UNDISSMISABLE])
173 {
174 $dismiss = self::DISSMISS_BUTTON;
175 }
176
177 return $dismiss . $heading . '<div class="content">' . $message . '</div>';
178 }
179 }