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;
13
14 use ICanBoogie\Event;
15 use ICanBoogie\Exception;
16 use ICanBoogie\I18n;
17 use ICanBoogie\Operation;
18 use ICanBoogie\Route;
19
20 use Brickrouge\A;
21 use Brickrouge\Button;
22 use Brickrouge\Element;
23 use Brickrouge\Form;
24
25 /**
26 * Base class for form type blocks.
27 *
28 * @property array $actions The actions for the {@link Form} element.
29 * @property array $attributes The attributes for the {@link Form} element.
30 * @property Form $element The {@link Form} element.
31 * @property array $values The values for the {@link Form} element.
32 */
33 abstract class FormBlock extends \ICanBoogie\Object
34 {
35 /**
36 * Adds assets to the document.
37 *
38 * The method doesn't add any asset.
39 *
40 * @param \Brickrouge\Document $document
41 */
42 static protected function add_assets(\Brickrouge\Document $document)
43 {
44
45 }
46
47 /**
48 * Module requesting the block.
49 *
50 * @var Module
51 */
52 protected $module;
53
54 /**
55 * Attributes provided during construct.
56 *
57 * @var array
58 */
59 protected $initial_attributes;
60
61 /**
62 * Constructor.
63 *
64 * @param Module $module
65 * @param array $attributes
66 */
67 public function __construct(Module $module, array $attributes=array())
68 {
69 $this->module = $module;
70 $this->initial_attributes = $attributes;
71
72 $this->access_control();
73 }
74
75 /**
76 * Returns whether the user has permission to display this block.
77 *
78 * @return bool
79 */
80 abstract protected function get_permission();
81
82 /**
83 * Controls the access to the block.
84 *
85 * @throws \Exception if the used has no permission to access the block.
86 */
87 abstract protected function access_control();
88
89 /**
90 * Alters the various parameters of the block.
91 *
92 * For each parameter the method checks if a `alter_<param>` method exists. If the method
93 * exists the following methods are invoked to alter the value of the parameter:
94 *
95 * 1. `fire_before_<param>`: Fires the `alter_<param>:before` event.
96 * 2. `alter_<param>`: Alters the values of the parameter.
97 * 3. `fire_<param>`: Fires the `alter_<param>` event.
98 *
99 * @param array $params The parameters to alter.
100 *
101 * @return array
102 */
103 protected function alter(array $params)
104 {
105 foreach ($params as $param => &$value)
106 {
107 $method_name = 'alter_' . $param;
108
109 if (!method_exists($this, $method_name))
110 {
111 continue;
112 }
113
114 call_user_func(array($this, 'fire_before_' . $method_name), $params);
115 $value = $this->$method_name($value, $params);
116 call_user_func(array($this, 'fire_' . $method_name), $params);
117 }
118
119 return $params;
120 }
121
122 /**
123 * Renders the block into a {@link Form} element.
124 *
125 * The method invokes the {@link alter()} method to alter the attribute for the {@link Form}
126 * element, and invokes the {@link alter_element()} method to alter the {@link Form} element
127 * with the following properties:
128 *
129 * - `module`: The module creating the block.
130 * - `attributes`: The attributes of the {@link Form} element.
131 * - `actions`: The actions of the {@link Form} element.
132 * - `children`: The children of the {@link Form} element.
133 * - `values`: The values of the {@link Form} element.
134 *
135 * @return Form
136 */
137 public function render()
138 {
139 global $core;
140
141 static::add_assets($core->document);
142
143 $this->attributes;
144 $attributes = &$this->attributes;
145 $this->values;
146 $values = &$this->values;
147 $this->children;
148 $children = &$this->children;
149 $this->actions;
150 $actions = &$this->actions;
151
152 $params = $this->alter
153 (
154 array
155 (
156 'module' => $this->module,
157 'attributes' => &$attributes,
158 'actions' => &$actions,
159 'children' => &$children,
160 'values' => &$values
161 )
162 );
163
164 $attributes = array
165 (
166 Form::ACTIONS => &$actions,
167 Form::CHILDREN => &$children,
168 Form::VALUES => &$values
169 )
170
171 + $params['attributes'];
172
173 $this->alter_element($this->element, $params);
174
175 return $this;
176 }
177
178 /**
179 * Renders the block into a HTML string.
180 *
181 * The method invokes the {@link render()} method.
182 *
183 * @return string
184 */
185 public function __toString()
186 {
187 try
188 {
189 // $html = (string) $this->render();
190
191 $this->render();
192
193 I18n::push_scope($this->module->flat_id . '.' . \ICanBoogie\underscore(basename(strtr(get_class($this), '\\', '/'))));
194
195 $html = (string) $this->element;
196
197 I18n::pop_scope();
198
199 return $html;
200 }
201 catch (\Exception $e)
202 {
203 return \Brickrouge\render_exception($e);
204 }
205 }
206
207 /*
208 * ATTRIBUTES
209 */
210
211 /**
212 * Returns the attributes for the {@link Form} element.
213 *
214 * The following attributes are defined:
215 *
216 * - The destination of the operation: The module id.
217 * - The form renderer: An instance of {@link Brickrouge\Renderer\Simple} with the
218 * {@link Icybee\Element\Group} group class.
219 * - Groups: The `primary` group.
220 * - id: `editor.
221 * - action: An empty string.
222 * - class: `form-primary edit`.
223 * - name: The identifier of the module.
224 *
225 * @return array
226 */
227 protected function lazy_get_attributes()
228 {
229 $module = $this->module;
230
231 return \ICanBoogie\array_merge_recursive
232 (
233 $this->initial_attributes, array
234 (
235 Form::HIDDENS => array
236 (
237 Operation::DESTINATION => $module->id
238 ),
239
240 Form::RENDERER => new \Brickrouge\Renderer\Simple
241 (
242 array
243 (
244 \Brickrouge\Renderer\Simple::GROUP_CLASS => 'Icybee\Element\Group'
245 )
246 ),
247
248 Element::GROUPS => array
249 (
250 'primary' => array
251 (
252
253 )
254 ),
255
256 'id' => 'editor',
257 'action' => '',
258 'class' => 'form-primary edit',
259 'name' => (string) $module
260 )
261 );
262 }
263
264 /**
265 * Alters the attributes of the {@link Form} element.
266 *
267 * The method returns the attributes as is.
268 *
269 * @param array $attributes The attributes to alter.
270 * @param array $params The alter parameters.
271 *
272 * @return array
273 */
274 protected function alter_attributes(array $attributes, array $params)
275 {
276 return $attributes;
277 }
278
279 /**
280 * Fires the `alter_attributes:before` event of class {@link FormBlock\BeforeAlterAttributesEvent}.
281 *
282 * @param array $payload The properties of the event.
283 */
284 protected function fire_before_alter_attributes(array $payload)
285 {
286 new FormBlock\BeforeAlterAttributesEvent($this, $payload);
287 }
288
289 /**
290 * Fires the `alter_attributes` event of class {@link FormBlock\AlterAttributesEvent}.
291 *
292 * @param array $payload The properties of the event.
293 */
294 protected function fire_alter_attributes(array $payload)
295 {
296 new FormBlock\AlterAttributesEvent($this, $payload);
297 }
298
299 /*
300 * VALUES
301 */
302
303 /**
304 * Returns the values for the {@link Form} element.
305 *
306 * The method returns the values defined in the initial attributes or an empty array
307 * if they were not defined.
308 *
309 * @return array
310 */
311 protected function lazy_get_values()
312 {
313 return isset($this->initial_attributes[Form::VALUES]) ? $this->initial_attributes[Form::VALUES] : array();
314 }
315
316 /**
317 * Alerts the values for the {@link Form} element.
318 *
319 * The method returns the values as is.
320 *
321 * @param array $values The values to alter.
322 * @param array $params The alter parameters.
323 *
324 * @return array
325 */
326 protected function alter_values(array $values, array $params)
327 {
328 return $values;
329 }
330
331 /**
332 * Fires the `alter_values:before` event of class {@link FormBlock\BeforeAlterValuesEvent}.
333 *
334 * @param array $payload The properties of the event.
335 */
336 protected function fire_before_alter_values(array $payload)
337 {
338 new FormBlock\BeforeAlterValuesEvent($this, $payload);
339 }
340
341 /**
342 * Fires the `alter_values` event of class {@link FormBlock\AlterValuesEvent}.
343 *
344 * @param array $payload The properties of the event.
345 */
346 protected function fire_alter_values(array $payload)
347 {
348 new FormBlock\AlterValuesEvent($this, $payload);
349 }
350
351 /*
352 * CHILDREN
353 */
354
355 /**
356 * Returns the children of the {@link Form} element.
357 *
358 * The method returns the children defined in the initial attributes or an empty array
359 * if they were not defined.
360 *
361 * @return array
362 */
363 protected function lazy_get_children()
364 {
365 return isset($this->initial_attributes[Element::CHILDREN]) ? $this->initial_attributes[Element::CHILDREN] : array();
366 }
367
368 /**
369 * Alters the children for the {@link Form} element.
370 *
371 * The method returns the children as is.
372 *
373 * @param array $children The children to alter.
374 * @param array $params The alter parameters.
375 *
376 * @return array
377 */
378 protected function alter_children(array $children, array $params)
379 {
380 return $children;
381 }
382
383 /**
384 * Fires the `alter_children:before` event of class {@link FormBlock\BeforeAlterChildrenEvent}.
385 *
386 * @param array $payload The properties of the event.
387 */
388 protected function fire_before_alter_children(array $payload)
389 {
390 new FormBlock\BeforeAlterChildrenEvent($this, $payload);
391 }
392
393 /**
394 * Fires the `alter_children` event of class {@link FormBlock\AlterChildrenEvent}.
395 *
396 * @param array $payload The properties of the event.
397 */
398 protected function fire_alter_children(array $payload)
399 {
400 new FormBlock\AlterChildrenEvent($this, $payload);
401 }
402
403 /*
404 * ACTIONS
405 */
406
407 /**
408 * Returns the actions for the {@link Form} element.
409 *
410 * The method returns an array with a `Send` button. The button can be overrode using the
411 * `primary` key.
412 *
413 * @return array
414 */
415 protected function lazy_get_actions()
416 {
417 return array
418 (
419 'primary' => new Button
420 (
421 'Send', array
422 (
423 'class' => 'btn-primary',
424 'type' => 'submit',
425 'name' => false
426 )
427 )
428 );
429 }
430
431 /**
432 * Alters the actions for the {@link Form} element.
433 *
434 * The method returns the actions as is.
435 *
436 * @param array $actions The actions to alter.
437 * @param array $params The alter parameters.
438 *
439 * @return array
440 */
441 protected function alter_actions(array $actions, array $params)
442 {
443 return $actions;
444 }
445
446 /**
447 * Fires the `alter_actions:before` event of class {@link FormBlock\BeforeAlterActionsEvent}.
448 *
449 * @param array $payload The properties of the event.
450 */
451 protected function fire_before_alter_actions(array $payload)
452 {
453 new FormBlock\BeforeAlterActionsEvent($this, $payload);
454 }
455
456 /**
457 * Fires the `alter_actions` event of class {@link FormBlock\AlterActionsEvent}.
458 *
459 * @param array $payload The properties of the event.
460 */
461 protected function fire_alter_actions(array $payload)
462 {
463 new FormBlock\AlterActionsEvent($this, $payload);
464 }
465
466 /*
467 * ELEMENT
468 */
469
470 /**
471 * Returns the {@link Form} element.
472 *
473 * @return \Brickrouge\Form
474 */
475 protected function lazy_get_element()
476 {
477 return new Form($this->attributes);
478 }
479
480 /**
481 * Alters the {@link Form} element.
482 *
483 * The method return the element as is.
484 *
485 * @param Form $element The element to alter.
486 * @param array $params The alter parameters.
487 *
488 * @return Form
489 */
490 protected function alter_element(Form $element, array $params)
491 {
492 return $element;
493 }
494 }
495
496 namespace Icybee\FormBlock;
497
498 /**
499 * Base class for the alter events of the {@link FormBlock} class.
500 */
501 abstract class AlterEvent extends \ICanBoogie\Event
502 {
503 /**
504 * The module creating the block.
505 *
506 * @var \ICanBoogie\Module
507 */
508 public $module;
509
510 /**
511 * Reference to the attributes for the {@link Form} element.
512 *
513 * @var array
514 */
515 public $attributes;
516
517 /**
518 * Reference to the actions for the {@link Form} element.
519 *
520 * @var array
521 */
522 public $actions;
523
524 /**
525 * Reference to the children for the {@link Form} element.
526 *
527 * @var array
528 */
529 public $children;
530
531 /**
532 * Reference to the values for the {@link Form} element.
533 *
534 * @var array
535 */
536 public $values;
537 }
538
539 /**
540 * Event class for the `Icybee\FormBlock::alter_attributes:before` event.
541 */
542 class BeforeAlterAttributesEvent extends AlterEvent
543 {
544 /**
545 * The event is constructed with the type `alter_attributes:before`.
546 *
547 * @param \Icybee\FormBlock $target
548 * @param array $payload
549 */
550 public function __construct(\Icybee\FormBlock $target, array $payload)
551 {
552 parent::__construct($target, 'alter_attributes:before', $payload);
553 }
554 }
555
556 /**
557 * Event class for the `Icybee\FormBlock::alter_attributes` event.
558 */
559 class AlterAttributesEvent extends AlterEvent
560 {
561 /**
562 * The event is constructed with the type `alter_attributes`.
563 *
564 * @param \Icybee\FormBlock $target
565 * @param array $payload
566 */
567 public function __construct(\Icybee\FormBlock $target, array $payload)
568 {
569 parent::__construct($target, 'alter_attributes', $payload);
570 }
571 }
572
573 /**
574 * Event class for the `Icybee\FormBlock::alter_properties:before` event.
575 */
576 class BeforeAlterValuesEvent extends AlterEvent
577 {
578 /**
579 * The event is constructed with the type `alter_properties:before`.
580 *
581 * @param \Icybee\FormBlock $target
582 * @param array $payload
583 */
584 public function __construct(\Icybee\FormBlock $target, array $payload)
585 {
586 parent::__construct($target, 'alter_values:before', $payload);
587 }
588 }
589
590 /**
591 * Event class for the `Icybee\FormBlock::alter_values` event.
592 */
593 class AlterValuesEvent extends AlterEvent
594 {
595 /**
596 * The event is constructed with the type `alter_properties`.
597 *
598 * @param \Icybee\FormBlock $target
599 * @param array $payload
600 */
601 public function __construct(\Icybee\FormBlock $target, array $payload)
602 {
603 parent::__construct($target, 'alter_values', $payload);
604 }
605 }
606
607 /**
608 * Event class for the `Icybee\FormBlock::alter_children:before` event.
609 */
610 class BeforeAlterChildrenEvent extends AlterEvent
611 {
612 /**
613 * The event is constructed with the type `alter_children:before`.
614 *
615 * @param \Icybee\FormBlock $target
616 * @param array $payload
617 */
618 public function __construct(\Icybee\FormBlock $target, array $payload)
619 {
620 parent::__construct($target, 'alter_children:before', $payload);
621 }
622 }
623
624 /**
625 * Event class for the `Icybee\FormBlock::alter_children` event.
626 */
627 class AlterChildrenEvent extends AlterEvent
628 {
629 /**
630 * The event is constructed with the type `alter_children`.
631 *
632 * @param \Icybee\FormBlock $target
633 * @param array $payload
634 */
635 public function __construct(\Icybee\FormBlock $target, array $payload)
636 {
637 parent::__construct($target, 'alter_children', $payload);
638 }
639 }
640
641 /**
642 * Event class for the `Icybee\FormBlock::alter_actions:before` event.
643 */
644 class BeforeAlterActionsEvent extends AlterEvent
645 {
646 /**
647 * The event is constructed with the type `alter_actions:before`.
648 *
649 * @param \Icybee\FormBlock $target
650 * @param array $payload
651 */
652 public function __construct(\Icybee\FormBlock $target, array $payload)
653 {
654 parent::__construct($target, 'alter_actions:before', $payload);
655 }
656 }
657
658 /**
659 * Event class for the `Icybee\FormBlock::alter_actions` event.
660 */
661 class AlterActionsEvent extends AlterEvent
662 {
663 /**
664 * The event is constructed with the type `alter_actions`.
665 *
666 * @param \Icybee\FormBlock $target
667 * @param array $payload
668 */
669 public function __construct(\Icybee\FormBlock $target, array $payload)
670 {
671 parent::__construct($target, 'alter_actions', $payload);
672 }
673 }