1 <?php
2
3 /*
4 * This file is part of the Icybee 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 Icybee\Modules\Forms;
13
14 use ICanBoogie\Exception;
15 use ICanBoogie\Operation;
16 use ICanBoogie\Mailer;
17
18 class Hooks
19 {
20 static public function markup_form(array $args, \Patron\Engine $patron, $template)
21 {
22 global $core;
23
24 $id = $args['select'];
25 $model = $core->models['forms'];
26
27 if (is_numeric($id))
28 {
29 $form = $model[$id];
30 }
31 else
32 {
33 $form = $model->own->visible->filter_by_slug($id)->one;
34 }
35
36 if (!$form)
37 {
38 throw new Exception('Unable to retrieve form using supplied conditions: %conditions', array('%conditions' => json_encode($args['select'])));
39 }
40
41 new \BlueTihi\Context\LoadedNodesEvent($patron->context, array($form));
42
43 if (!$form->is_online)
44 {
45 throw new Exception('The form %title is offline', array('%title' => $form->title));
46 }
47
48 return (string) $form;
49 }
50
51 /**
52 * Tries to load the form associated with the operation.
53 *
54 * This function is a callback for the `ICanBoogie\Operation::get_form` event.
55 *
56 * The {@link OPERATION_POST_ID} parameter provides the key of the form active record to load.
57 *
58 * If the form is successfully retrieved a callback is added to the
59 * "<operation_class>::process" event, it is used to send a notify message with the parameters
60 * provided by the form active record. The callback also provides further processing.
61 *
62 * At the very end of the process, the `Icybee\Modules\Forms\Form::sent` event is fired.
63 *
64 * Notifying
65 * =========
66 *
67 * If defined, the `alter_notify` method of the form is invoked to alter the notify options.
68 * The method is wrapped with the `Icybee\Modules\Forms\Form::alter_notify:before` and
69 * `Icybee\Modules\Forms\Form::alter_notify` events.
70 *
71 * If the `is_notify` property of the record is true a notify message is sent with the notify
72 * options.
73 *
74 * Result tracking
75 * ===============
76 *
77 * The result of the operation using the form is stored in the session under
78 * `[modules][forms][rc][<record_nid>]`. This stored value is used when the form is
79 * rendered to choose what to render. For example, if the value is empty, the form is rendered
80 * with the `before` and `after` messages, otherwise only the `complete` message is rendered.
81 *
82 * @param \ICanBoogie\Operation\GetFormEvent $event
83 * @param Operation $operation
84 */
85 static public function on_operation_get_form(Operation\GetFormEvent $event, Operation $operation)
86 {
87 global $core;
88
89 $request = $event->request;
90
91 if (!$request[Module::OPERATION_POST_ID])
92 {
93 return;
94 }
95
96 $record = $core->models['forms'][(int) $request[Module::OPERATION_POST_ID]];
97 $form = $record->form;
98
99 $event->form = $form;
100 $event->stop();
101
102 $core->events->attach
103 (
104 get_class($operation) . '::process', function(Operation\ProcessEvent $event, Operation $operation) use ($record, $form)
105 {
106 global $core;
107
108 $rc = $event->rc;
109 $bind = $event->request->params;
110 $template = $record->notify_template;
111 $mailer = null;
112 $mailer_tags = [
113
114 'bcc' => $record->notify_bcc,
115 'to' => $record->notify_destination,
116 'from' => $record->notify_from,
117 'subject' => $record->notify_subject,
118 'body' => null
119
120 ];
121
122 $notify_params = new NotifyParams
123 (
124 array
125 (
126 'rc' => &$rc,
127 'bind' => &$bind,
128 'template' => &$template,
129 'mailer' => &$mailer,
130 'mailer_tags' => &$mailer_tags
131 )
132 );
133
134 new Form\BeforeAlterNotifyEvent
135 (
136 $record, array
137 (
138 'params' => $notify_params,
139 'event' => $event,
140 'operation' => $operation
141 )
142 );
143
144 if ($form instanceof AlterNotify || method_exists($form, 'alter_notify')) // TODO-20130122: remove method_exists()
145 {
146 $form->alter_notify($notify_params, $record, $event, $operation);
147 }
148
149 new Form\AlterNotifyEvent
150 (
151 $record, array
152 (
153 'params' => $notify_params,
154 'event' => $event,
155 'operation' => $operation
156 )
157 );
158
159 #
160 # The result of the operation is stored in the session and is used in the next
161 # session to present the `success` message instead of the form.
162 #
163 # Note: The result is not stored for XHR.
164 #
165
166 if (!$event->request->is_xhr)
167 {
168 $core->session->modules['forms']['rc'][$record->nid] = $rc;
169 }
170
171 $message = null;
172
173 if ($record->is_notify)
174 {
175 $patron = new \Patron\Engine();
176
177 if (!$mailer_tags['body'])
178 {
179 $mailer_tags['body'] = $template;
180 }
181
182 foreach ($mailer_tags as &$value)
183 {
184 $value = $patron($value, $bind);
185 }
186
187 $message = $mailer_tags['body'];
188
189 if ($mailer)
190 {
191 $mailer($mailer_tags);
192 }
193 else
194 {
195 $core->mail($mailer_tags);
196 }
197 }
198
199 new Form\NotifyEvent
200 (
201 $record, array
202 (
203 'params' => $notify_params,
204 'message' => &$message,
205 'event' => $event,
206 'request' => $event->request,
207 'operation' => $operation
208 )
209 );
210 }
211 );
212 }
213 }
214
215 class NotifyParams
216 {
217 /**
218 * Reference to the result of the operation.
219 *
220 * @var mixed
221 */
222 public $rc;
223
224 /**
225 * Reference to the `this` value used to render the template.
226 *
227 * @var mixed
228 */
229 public $bind;
230
231 /**
232 * Reference to the template used to render the message.
233 *
234 * @var string
235 */
236 public $template;
237
238 /**
239 * Reference to the mailer object.
240 *
241 * Use this property to provide your own mailer.
242 *
243 * @var \ICanBoogie\Mailer
244 */
245 public $mailer;
246
247 /**
248 * Reference to the tags used to create the mailer object.
249 *
250 * @var array
251 */
252 public $mailer_tags;
253
254 public function __construct(array $input)
255 {
256 foreach ($input as $k => &$v)
257 {
258 $this->$k = &$v;
259 }
260 }
261 }
262
263 namespace Icybee\Modules\Forms\Form;
264
265 /**
266 * Event class for the `Icybee\Modules\Forms\Form::alter_notify:before` event.
267 */
268 class BeforeAlterNotifyEvent extends \ICanBoogie\Event
269 {
270 /**
271 * Notify parameters.
272 *
273 * @var \Icybee\Modules\Forms\NotifyParams
274 */
275 public $params;
276
277 /**
278 * The event that triggered the notification.
279 *
280 * @var \ICanBoogie\Operation\ProcessEvent
281 */
282 public $event;
283
284 /**
285 * The operation that triggered the {@link ProcessEvent} event.
286 *
287 * @var \ICanBoogie\Operation
288 */
289 public $operation;
290
291 /**
292 * The event is constructed with the type `alter_notify:before`.
293 *
294 * @param \Icybee\Modules\Forms\Form $target
295 * @param array $payload
296 */
297 public function __construct(\Icybee\Modules\Forms\Form $target, array $payload)
298 {
299 parent::__construct($target, 'alter_notify:before', $payload);
300 }
301 }
302
303 /**
304 * Event class for the `Icybee\Modules\Forms\Form::alter_notify` event.
305 */
306 class AlterNotifyEvent extends \ICanBoogie\Event
307 {
308 /**
309 * Notify parameters.
310 *
311 * @var \Icybee\Modules\Forms\NotifyParams
312 */
313 public $params;
314
315 /**
316 * The event that triggered the notification.
317 *
318 * @var \ICanBoogie\Operation\ProcessEvent
319 */
320 public $event;
321
322 /**
323 * The operation that triggered the {@link ProcessEvent} event.
324 *
325 * @var \ICanBoogie\Operation
326 */
327 public $operation;
328
329 /**
330 * The event is constructed with the type `alter_notify`.
331 *
332 * @param \Icybee\Modules\Forms\Form $target
333 * @param array $payload
334 */
335 public function __construct(\Icybee\Modules\Forms\Form $target, array $payload)
336 {
337 parent::__construct($target, 'alter_notify', $payload);
338 }
339 }
340
341 /**
342 * Event class for the `Icybee\Modules\Forms\Form::notify` event.
343 */
344 class NotifyEvent extends \ICanBoogie\Event
345 {
346 /**
347 * Notify parameters.
348 *
349 * @var \Icybee\Modules\Forms\NotifyParams
350 */
351 public $params;
352
353 /**
354 * Reference to the message sent.
355 *
356 * @var string
357 */
358 public $message;
359
360 /**
361 * The operation `process` event.
362 *
363 * @var \ICanBoogie\OperationProcessEvent
364 */
365 public $event;
366
367 /**
368 * The request that triggered the operation.
369 *
370 * @var \ICanBoogie\HTTP\Request
371 */
372 public $request;
373
374 /**
375 * The operation that submitted the form.
376 *
377 * @var \ICanBoogie\Operation
378 */
379 public $operation;
380
381 /**
382 * The event is constructed with the type `notify`.
383 *
384 * @param \Icybee\Modules\Forms\Form $target
385 * @param array $payload
386 */
387 public function __construct(\Icybee\Modules\Forms\Form $target, array $payload)
388 {
389 parent::__construct($target, 'notify', $payload);
390 }
391 }