Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • AdminDecorator
  • AdminIndexController
  • BlockController
  • BlockDecorator
  • ConfigBlock
  • ConfigController
  • ConfigOperation
  • Core
  • DeleteBlock
  • DeleteController
  • Document
  • DocumentDecorator
  • EditBlock
  • EditController
  • FormBlock
  • Hooks
  • InterlockBlock
  • Kses
  • ManageBlock
  • Module
  • Modules
  • StatsDecorator

Constants

  • OPERATION_SAVE_MODE
  • OPERATION_SAVE_MODE_CONTINUE
  • OPERATION_SAVE_MODE_DISPLAY
  • OPERATION_SAVE_MODE_LIST
  • OPERATION_SAVE_MODE_NEW

Functions

  • slugize
  • start
  • strip_stopwords
  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\HTTP\ForceRedirect;
 17 use ICanBoogie\HTTP\HTTPError;
 18 use ICanBoogie\I18n;
 19 use ICanBoogie\Operation;
 20 use ICanBoogie\Route;
 21 
 22 use Brickrouge\A;
 23 use Brickrouge\Button;
 24 use Brickrouge\Element;
 25 use Brickrouge\Form;
 26 use Brickrouge\SplitButton;
 27 
 28 use Icybee\Element\ActionbarToolbar;
 29 
 30 /**
 31  * A record editor.
 32  */
 33 class EditBlock extends FormBlock
 34 {
 35     static protected function add_assets(\Brickrouge\Document $document)
 36     {
 37         parent::add_assets($document);
 38 
 39         $document->js->add('edit.js');
 40     }
 41 
 42     /**
 43      * The key of the record to edit.
 44      *
 45      * @var int
 46      */
 47     protected $key;
 48 
 49     /**
 50      * Constructor.
 51      *
 52      * @param Module $module
 53      * @param array $attributes
 54      * @param array $params
 55      */
 56     public function __construct(Module $module, array $attributes=array(), array $params=array())
 57     {
 58         $key = isset($params[0]) ? $params[0] : null;
 59 
 60         $this->key = $key;
 61 
 62         parent::__construct($module, $attributes);
 63     }
 64 
 65     /**
 66      * Adds the `key` and `record` properties to the alter parameters.
 67      */
 68     protected function alter(array $params)
 69     {
 70         return parent::alter
 71         (
 72             $params + array
 73             (
 74                 'key' => $this->key,
 75                 'record' => $this->record
 76             )
 77         );
 78     }
 79 
 80     /**
 81      * If the record to edit is locked by another user a {@link InterlockBlock} is returned
 82      * instead of the {@link Form} element.
 83      */
 84     public function render()
 85     {
 86         $module = $this->module;
 87         $key = $this->key;
 88 
 89         if ($key)
 90         {
 91             $locked = $module->lock_entry($key, $lock);
 92 
 93             $this->locked = $locked;
 94 
 95             if (!$locked)
 96             {
 97                 return new InterlockBlock($module, array(), array('lock' => $lock));
 98             }
 99         }
100 
101         I18n::push_scope($module->flat_id . '.edit');
102 
103         try
104         {
105             $element = parent::render();
106             $this->element->save();
107 
108             I18n::pop_scope();
109 
110             return $element;
111         }
112         catch (\Exception $e)
113         {
114             I18n::pop_scope();
115 
116             throw $e;
117         }
118     }
119 
120     protected function get_permission()
121     {
122         global $core;
123 
124         $user = $core->user;
125         $permission = $user->has_permission(Module::PERMISSION_CREATE, $this->module);
126 
127         #
128         # check user ownership
129         #
130 
131         $record = $this->record;
132 
133         if ($record && isset($record->uid))
134         {
135             $permission = $user->has_ownership($this->module, $record);
136         }
137 
138         return $permission;
139     }
140 
141     protected function access_control()
142     {
143         global $core;
144 
145         $key = $this->key;
146         $module_id = $this->module->id;
147 
148         if (!$key && !$this->permission)
149         {
150             throw new HTTPError(\ICanBoogie\format("You don't have permission to create records in the %id module.", array('id' => $module_id)), 403);
151         }
152 
153         #
154         # Records that belong to a site can only be edited on that site, thus we need to change
155         # site if the current site if not the one associated with the record.
156         #
157 
158         $record = $this->record;
159 
160         if ($record && !($record instanceof \Icybee\Modules\Sites\Site)
161         && !empty($record->siteid) && $record->siteid != $core->site_id)
162         {
163             $url = $core->models['sites'][$record->siteid]->url;
164 
165             throw new ForceRedirect("$url/admin/$module_id/$key/edit");
166         }
167     }
168 
169     /**
170      * Returns the record being edited or null if its a new record.
171      *
172      * @return \ICanBoogie\ActiveRecord
173      */
174     protected function lazy_get_record()
175     {
176         return $this->key ? $this->module->model[$this->key] : null;
177     }
178 
179     /*
180      * ATTRIBUTES
181      */
182 
183     /**
184      * Adds the following:
185      *
186      * - The name of the operation: `save`.
187      * - The key of the operation: The key provided during construct.
188      * - The `admin` element group.
189      */
190     protected function lazy_get_attributes()
191     {
192         return \ICanBoogie\array_merge_recursive
193         (
194             parent::lazy_get_attributes(), array
195             (
196                 Form::HIDDENS => array
197                 (
198                     Operation::NAME => 'save',
199                     Operation::KEY => $this->key
200                 ),
201 
202                 Element::GROUPS => array
203                 (
204                     'admin' => array
205                     (
206                         'title' => 'Admin',
207                         'weight' => 1000
208                     )
209                 )
210             )
211         );
212     }
213 
214     /**
215      * Fires the `alter_attributes:before` event of class {@link EditBlock\BeforeAlterAttributesEvent}.
216      */
217     protected function fire_before_alter_attributes(array $properties)
218     {
219         new EditBlock\BeforeAlterAttributesEvent($this, $properties);
220     }
221 
222     /**
223      * Fires the `alter_attributes` event of class {@link EditBlock\AlterAttributesEvent}.
224      */
225     protected function fire_alter_attributes(array $properties)
226     {
227         new EditBlock\AlterAttributesEvent($this, $properties);
228     }
229 
230     /*
231      * VALUES
232      */
233 
234     /**
235      * Merges the values returned by the parent with the following arrays:
236      *
237      * - An array with all the properties of the extended schema set to `null`.
238      * - An array with the properties of the record.
239      * - An array with the request params of the request.
240      */
241     protected function lazy_get_values()
242     {
243         global $core;
244 
245         $schema = $this->module->model->extended_schema;
246         $record = $this->record;
247         $params = $core->request->request_params;
248 
249         return array_merge
250         (
251             parent::lazy_get_values(),
252             $schema ? array_fill_keys(array_keys($schema['fields']), null) : array(),
253             $record ? $record->to_array() : array(),
254             $params ? $params : array()
255         );
256     }
257 
258     /**
259      * Fires the `alter_values:before` event of class {@link EditBlock\BeforeAlterValuesEvent}.
260      */
261     protected function fire_before_alter_values(array $properties)
262     {
263         new EditBlock\BeforeAlterValuesEvent($this, $properties);
264     }
265 
266     /**
267      * Fires the `alter_values` event of class {@link EditBlock\AlterValuesEvent}.
268      */
269     protected function fire_alter_values(array $properties)
270     {
271         new EditBlock\AlterValuesEvent($this, $properties);
272     }
273 
274     /*
275      * CHILDREN
276      */
277 
278     /**
279      * Fires the `alter_children:before` event of class {@link EditBlock\BeforeAlterChildrenEvent}.
280      */
281     protected function fire_before_alter_children(array $properties)
282     {
283         new EditBlock\BeforeAlterChildrenEvent($this, $properties);
284     }
285 
286     /**
287      * Fires the `alter_children` event of class {@link EditBlock\AlterChildrenEvent}.
288      */
289     protected function fire_alter_children(array $properties)
290     {
291         new EditBlock\AlterChildrenEvent($this, $properties);
292     }
293 
294     /*
295      * ACTIONS
296      */
297 
298     /**
299      * Replaces the primary button with a button with the label "Save".
300      */
301     protected function lazy_get_actions()
302     {
303         return array
304         (
305             'primary' => new Button
306             (
307                 'Save', array
308                 (
309                     'class' => 'btn-primary',
310                     'type' => 'submit',
311                     'name' => false
312                 )
313             )
314         );
315     }
316 
317     /**
318      * Adds the save mode checkbox group of the actions as well as the action bar.
319      */
320     protected function alter_actions(array $actions, array $params)
321     {
322         global $core;
323 
324         $module = $this->module;
325         $record = $this->record;
326 
327         $mode = isset($core->session->operation_save_mode[$module->id]) ? $core->session->operation_save_mode[$module->id] : OPERATION_SAVE_MODE_LIST;
328 
329         $save_mode_options = array
330         (
331             OPERATION_SAVE_MODE_LIST => I18n\t('save_mode_list', array(), array('scope' => 'option')),
332             OPERATION_SAVE_MODE_CONTINUE => I18n\t('save_mode_continue', array(), array('scope' => 'option')),
333             OPERATION_SAVE_MODE_NEW => I18n\t('save_mode_new', array(), array('scope' => 'option')),
334         );
335 
336         try
337         {
338             $core->views["{$module->id}/view"];
339             $save_mode_options[OPERATION_SAVE_MODE_DISPLAY] = I18n\t('save_mode_display', array(), array('scope' => 'option'));
340         }
341         catch (\Icybee\Modules\Views\Collection\ViewNotDefined $e)
342         {
343             if ($record instanceof \ICanBoogie\Object && $record->has_property('url'))
344             {
345                 $url = $record->url;
346 
347                 if ($url)
348                 {
349                     $save_mode_options[OPERATION_SAVE_MODE_DISPLAY] = I18n\t('save_mode_display', array(), array('scope' => 'option'));
350                 }
351             }
352         }
353 
354         if (empty($save_mode_options[$mode]))
355         {
356             $mode = key($save_mode_options);
357         }
358 
359         $key = $this->key;
360         $block = $this;
361 
362         $core->events->attach(function(ActionbarToolbar\CollectEvent $event, ActionbarToolbar $sender) use($record, $module, $key, $save_mode_options, $mode, $block)
363         {
364             global $core;
365 
366             if ($record)
367             {
368                 try
369                 {
370                     $url = $record->url;
371 
372                     if ($url[0] != '#')
373                     {
374                         $event->buttons[] = '<a href="' . $record->url . '" class="actionbar-link">' . I18n\t('View', array(), array('scope' => 'button')) . '</a>';
375                     }
376                 }
377                 catch (\Exception $e) {}
378             }
379 
380             $locked = true;
381 
382             if ($key)
383             {
384                 $locked = $module->lock_entry($key, $lock);
385             }
386 
387             if (!$locked)
388             {
389                 return;
390             }
391 
392             if ($key
393             && $core->user->has_permission(Module::PERMISSION_MANAGE, $module)
394             && $core->user->has_ownership($module, $record))
395             {
396                 $event->buttons[] = new A
397                 (
398                     I18n\t('Delete', array(), array('scope' => 'button')), \ICanBoogie\Routing\contextualize('/admin/' . $module . '/' . $key . '/delete'), array
399                     (
400                         'class' => 'btn btn-danger'
401                     )
402                 );
403             }
404 
405             if (isset($block->actions[OPERATION_SAVE_MODE]))
406             {
407                 $event->buttons[] = new SplitButton
408                 (
409                     $save_mode_options[$mode], array
410                     (
411                         Element::OPTIONS => $save_mode_options,
412 
413                         'value' => $mode,
414                         'class' => 'btn-primary record-save-mode'
415                     )
416                 );
417             }
418         });
419 
420         return array_merge
421         (
422             array
423             (
424                 OPERATION_SAVE_MODE => new Element
425                 (
426                     Element::TYPE_RADIO_GROUP, array
427                     (
428                         Element::GROUP => 'save',
429                         Element::OPTIONS => $save_mode_options,
430 
431                         'value' => $mode,
432                         'class' => 'inputs-list save-mode'
433                     )
434                 )
435             ),
436 
437             $actions
438         );
439     }
440 
441     /**
442      * Fires the `alter_actions:before` event of class {@link EditBlock\BeforeAlterActionsEvent}.
443      */
444     protected function fire_before_alter_actions(array $properties)
445     {
446         new EditBlock\BeforeAlterActionsEvent($this, $properties);
447     }
448 
449     /**
450      * Fires the `alter_actions` event of class {@link EditBlock\AlterActionsEvent}.
451      */
452     protected function fire_alter_actions(array $properties)
453     {
454         new EditBlock\AlterActionsEvent($this, $properties);
455     }
456 
457     /**
458      * If the user doesn't have the permission to edit the record, the actions of the
459      * {@link Form} element are set to `null` and the form is disabled.
460      */
461     protected function alter_element(Form $element, array $params)
462     {
463         global $core;
464 
465         $element = parent::alter_element($element, $params);
466 
467         if (!$this->permission)
468         {
469             $element[Form::ACTIONS] = null;
470             $element[Form::DISABLED] = true;
471         }
472 
473         $language = $core->site->language;
474 
475         foreach ($element as $control)
476         {
477             if ($control->tag_name != 'textarea')
478             {
479                 continue;
480             }
481 
482             $control['lang'] = $language;
483         }
484 
485         return $element;
486     }
487 }
488 
489 namespace Icybee\EditBlock;
490 
491 /**
492  * Base class for the alter events of the {@link EditBlock} class.
493  *
494  * The class extends {@link FormBlock\AlterEvent} with the `key` and `record` properties.
495  */
496 abstract class AlterEvent extends \Icybee\FormBlock\AlterEvent
497 {
498     /**
499      * Key of the record being edited.
500      *
501      * @var int
502      */
503     public $key;
504 
505     /**
506      * The record being edited.
507      *
508      * @var \ICanBoogie\ActiveRecord
509      */
510     public $record;
511 }
512 
513 /**
514  * Event class for the `Icybee\EditBlock::alter_attributes:before` event.
515  */
516 class BeforeAlterAttributesEvent extends AlterEvent
517 {
518     /**
519      * The event is constructed with the type `alter_attributes:before`.
520      *
521      * @param \Icybee\EditBlock $target
522      * @param array $properties
523      */
524     public function __construct(\Icybee\EditBlock $target, array $properties)
525     {
526         parent::__construct($target, 'alter_attributes:before', $properties);
527     }
528 }
529 
530 /**
531  * Event class for the `Icybee\EditBlock::alter_attributes` event.
532  */
533 class AlterAttributesEvent extends AlterEvent
534 {
535     /**
536      * The event is constructed with the type `alter_attributes`.
537      *
538      * @param \Icybee\EditBlock $target
539      * @param array $properties
540      */
541     public function __construct(\Icybee\EditBlock $target, array $properties)
542     {
543         parent::__construct($target, 'alter_attributes', $properties);
544     }
545 }
546 
547 /**
548  * Event class for the `Icybee\EditBlock::alter_values:before` event.
549  */
550 class BeforeAlterValuesEvent extends AlterEvent
551 {
552     /**
553      * The event is constructed with the type `alter_values:before`.
554      *
555      * @param \Icybee\EditBlock $target
556      * @param array $properties
557      */
558     public function __construct(\Icybee\EditBlock $target, array $properties)
559     {
560         parent::__construct($target, 'alter_values:before', $properties);
561     }
562 }
563 
564 /**
565  * Event class for the `Icybee\EditBlock::alter_values` event.
566  */
567 class AlterValuesEvent extends AlterEvent
568 {
569     /**
570      * The event is constructed with the type `alter_values`.
571      *
572      * @param \Icybee\EditBlock $target
573      * @param array $properties
574      */
575     public function __construct(\Icybee\EditBlock $target, array $properties)
576     {
577         parent::__construct($target, 'alter_values', $properties);
578     }
579 }
580 
581 /**
582  * Event class for the `Icybee\EditBlock::alter_children:before` event.
583  */
584 class BeforeAlterChildrenEvent extends AlterEvent
585 {
586     /**
587      * The event is constructed with the type `alter_children:before`.
588      *
589      * @param \Icybee\EditBlock $target
590      * @param array $properties
591      */
592     public function __construct(\Icybee\EditBlock $target, array $properties)
593     {
594         parent::__construct($target, 'alter_children:before', $properties);
595     }
596 }
597 
598 /**
599  * Event class for the `Icybee\EditBlock::alter_children` event.
600  */
601 class AlterChildrenEvent extends AlterEvent
602 {
603     /**
604      * The event is constructed with the type `alter_children`.
605      *
606      * @param \Icybee\EditBlock $target
607      * @param array $properties
608      */
609     public function __construct(\Icybee\EditBlock $target, array $properties)
610     {
611         parent::__construct($target, 'alter_children', $properties);
612     }
613 }
614 
615 /**
616  * Event class for the `Icybee\EditBlock::alter_actions:before` event.
617  */
618 class BeforeAlterActionsEvent extends AlterEvent
619 {
620     /**
621      * The event is constructed with the type `alter_actions:before`.
622      *
623      * @param \Icybee\EditBlock $target
624      * @param array $properties
625      */
626     public function __construct(\Icybee\EditBlock $target, array $properties)
627     {
628         parent::__construct($target, 'alter_actions:before', $properties);
629     }
630 }
631 
632 /**
633  * Event class for the `Icybee\EditBlock::alter_actions` event.
634  */
635 class AlterActionsEvent extends AlterEvent
636 {
637     /**
638      * The event is constructed with the type `alter_actions`.
639      *
640      * @param \Icybee\EditBlock $target
641      * @param array $properties
642      */
643     public function __construct(\Icybee\EditBlock $target, array $properties)
644     {
645         parent::__construct($target, 'alter_actions', $properties);
646     }
647 }
Autodoc API documentation generated by ApiGen 2.8.0