1 <?php
  2 
  3 /**
  4  * Erweiterung eines Artikels um slicemanagement.
  5  *
  6  * @package redaxo\structure\content
  7  */
  8 class rex_article_content_editor extends rex_article_content
  9 {
 10     private $MODULESELECT;
 11     private $sliceAddPosition = 0;
 12 
 13     public function __construct($article_id = null, $clang = null)
 14     {
 15         parent::__construct($article_id, $clang);
 16     }
 17 
 18     /**
 19      * {@inheritdoc}
 20      */
 21     protected function outputSlice(rex_sql $artDataSql, $moduleIdToAdd)
 22     {
 23         if ($this->mode != 'edit') {
 24             // ----- wenn mode nicht edit
 25             $slice_content = parent::outputSlice(
 26                 $artDataSql,
 27                 $moduleIdToAdd
 28             );
 29         } else {
 30             $sliceId = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.id');
 31             $sliceCtype = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.ctype_id');
 32 
 33             $moduleInput = $artDataSql->getValue(rex::getTablePrefix() . 'module.input');
 34             $moduleOutput = $artDataSql->getValue(rex::getTablePrefix() . 'module.output');
 35             $moduleId = $artDataSql->getValue(rex::getTablePrefix() . 'module.id');
 36 
 37             // ----- add select box einbauen
 38             $slice_content = $this->getModuleSelect($sliceId);
 39 
 40             if ($this->function == 'add' && $this->slice_id == $sliceId) {
 41                 $slice_content .= $this->addSlice($sliceId, $moduleIdToAdd);
 42             }
 43 
 44             $panel = '';
 45             // ----- Display message at current slice
 46             //if(rex::getUser()->getComplexPerm('modules')->hasPerm($moduleId)) {
 47             if ($this->function != 'add' && $this->slice_id == $sliceId) {
 48                 $msg = '';
 49                 if ($this->warning != '') {
 50                     $msg .= rex_view::warning($this->warning);
 51                 }
 52                 if ($this->info != '') {
 53                     $msg .= rex_view::success($this->info);
 54                 }
 55                 $panel .= $msg;
 56             }
 57             //}
 58 
 59             // ----- EDIT/DELETE BLOCK - Wenn Rechte vorhanden
 60             if (rex::getUser()->getComplexPerm('modules')->hasPerm($moduleId)) {
 61                 if ($this->function == 'edit' && $this->slice_id == $sliceId) {
 62                     // **************** Aktueller Slice
 63 
 64                     // ----- PRE VIEW ACTION [EDIT]
 65                     $action = new rex_article_action($moduleId, 'edit', $artDataSql);
 66                     if (rex_request_method() == 'post' && rex_request('function', 'string') == 'edit') {
 67                         $action->setRequestValues();
 68                     }
 69                     $action->exec(rex_article_action::PREVIEW);
 70                     // ----- / PRE VIEW ACTION
 71 
 72                     $moduleInput = $this->replaceVars($artDataSql, $moduleInput);
 73                     return $slice_content . $this->editSlice($sliceId, $moduleInput, $sliceCtype, $moduleId, $artDataSql);
 74                 }
 75                 // Modulinhalt ausgeben
 76                 $moduleOutput = $this->replaceVars($artDataSql, $moduleOutput);
 77                 $panel .= $this->getWrappedModuleOutput($moduleId, $moduleOutput);
 78             } else {
 79                 // ----- hat keine rechte an diesem modul, einfach ausgeben
 80                 $moduleOutput = $this->replaceVars($artDataSql, $moduleOutput);
 81                 $panel .= $this->getWrappedModuleOutput($moduleId, $moduleOutput);
 82             }
 83 
 84             $fragment = new rex_fragment();
 85             $fragment->setVar('title', $this->getSliceHeading($artDataSql), false);
 86             $fragment->setVar('options', $this->getSliceMenu($artDataSql), false);
 87             $fragment->setVar('body', $panel, false);
 88             $slice_content .= '<li class="rex-slice rex-slice-output" id="slice'.$sliceId.'">' . $fragment->parse('core/page/section.php') . '</li>';
 89         }
 90 
 91         return $slice_content;
 92     }
 93 
 94     /**
 95      * Returns the slice heading.
 96      *
 97      * @param rex_sql $artDataSql rex_sql istance containing all the slice and module information
 98      *
 99      * @return string
100      */
101     private function getSliceHeading(rex_sql $artDataSql)
102     {
103         $sliceId = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.id');
104         $sliceCtype = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.ctype_id');
105 
106         $moduleId = $artDataSql->getValue(rex::getTablePrefix() . 'module.id');
107         $moduleName = rex_i18n::translate($artDataSql->getValue(rex::getTablePrefix() . 'module.name'));
108 
109         return $moduleName;
110     }
111 
112     /**
113      * Returns the slice menu.
114      *
115      * @param rex_sql $artDataSql rex_sql istance containing all the slice and module information
116      *
117      * @return string
118      */
119     private function getSliceMenu(rex_sql $artDataSql)
120     {
121         $sliceId = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.id');
122         $sliceCtype = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.ctype_id');
123 
124         $moduleId = $artDataSql->getValue(rex::getTablePrefix() . 'module.id');
125         $moduleName = rex_i18n::translate($artDataSql->getValue(rex::getTablePrefix() . 'module.name'));
126 
127         $context = new rex_context([
128             'page' => rex_be_controller::getCurrentPage(),
129             'article_id' => $this->article_id,
130             'slice_id' => $sliceId,
131             'clang' => $this->clang,
132             'ctype' => $this->ctype,
133         ]);
134         $fragment = '#slice' . $sliceId;
135 
136         $header_right = '';
137 
138         $menu_items_action = [];
139         $menu_items_move = [];
140 
141         if (rex::getUser()->getComplexPerm('modules')->hasPerm($moduleId)) {
142             $templateHasModule = rex_template::hasModule($this->template_attributes, $this->ctype, $moduleId);
143             if ($templateHasModule) {
144                 // edit
145                 $item = [];
146                 $item['hidden_label'] = rex_i18n::msg('module') . ' ' . $moduleName . ' ' . rex_i18n::msg('edit');
147                 $item['url'] = $context->getUrl(['function' => 'edit']) . $fragment;
148                 $item['attributes']['class'][] = 'btn-edit';
149                 $item['attributes']['title'] = rex_i18n::msg('edit');
150                 $item['icon'] = 'edit';
151                 $menu_items_action[] = $item;
152             }
153 
154             // delete
155             $item = [];
156             $item['hidden_label'] = rex_i18n::msg('module') . ' ' . $moduleName . ' ' . rex_i18n::msg('delete');
157             $item['url'] = $context->getUrl(['function' => 'delete', 'save' => 1]) . $fragment;
158             $item['attributes']['class'][] = 'btn-delete';
159             $item['attributes']['title'] = rex_i18n::msg('delete');
160             $item['attributes']['data-confirm'] = rex_i18n::msg('confirm_delete_block');
161             $item['icon'] = 'delete';
162             $menu_items_action[] = $item;
163 
164             if ($templateHasModule && rex::getUser()->hasPerm('moveSlice[]')) {
165                 // moveup
166                 $item = [];
167                 $item['hidden_label'] = rex_i18n::msg('module') . ' ' . $moduleName . ' ' . rex_i18n::msg('move_slice_up');
168                 $item['url'] = $context->getUrl(['upd' => time(), 'direction' => 'moveup'] + rex_api_content_move_slice::getUrlParams()) . $fragment;
169                 $item['attributes']['class'][] = 'btn-move';
170                 $item['attributes']['title'] = rex_i18n::msg('move_slice_up');
171                 $item['icon'] = 'up';
172                 $menu_items_move[] = $item;
173 
174                 // movedown
175                 $item = [];
176                 $item['hidden_label'] = rex_i18n::msg('module') . ' ' . $moduleName . ' ' . rex_i18n::msg('move_slice_down');
177                 $item['url'] = $context->getUrl(['upd' => time(), 'direction' => 'movedown'] + rex_api_content_move_slice::getUrlParams()) . $fragment;
178                 $item['attributes']['class'][] = 'btn-move';
179                 $item['attributes']['title'] = rex_i18n::msg('move_slice_down');
180                 $item['icon'] = 'down';
181                 $menu_items_move[] = $item;
182             }
183         } else {
184             $header_right .= rex_i18n::msg('no_editing_rights') . ' ' . $moduleName;
185         }
186 
187         // ----- EXTENSION POINT
188         $menu_items_ep = [];
189         $menu_items_ep = rex_extension::registerPoint(new rex_extension_point(
190             'STRUCTURE_CONTENT_SLICE_MENU',
191                 $menu_items_ep,
192             [
193                 'article_id' => $this->article_id,
194                 'clang' => $this->clang,
195                 'ctype' => $sliceCtype,
196                 'module_id' => $moduleId,
197                 'slice_id' => $sliceId,
198                 'perm' => rex::getUser()->getComplexPerm('modules')->hasPerm($moduleId),
199             ]
200         ));
201 
202         if (count($menu_items_action) > 0) {
203             $fragment = new rex_fragment();
204             $fragment->setVar('items', $menu_items_action, false);
205             $header_right .= $fragment->parse('slice_menu_action.php');
206         }
207 
208         if (count($menu_items_ep) > 0) {
209             $fragment = new rex_fragment();
210             $fragment->setVar('items', $menu_items_ep, false);
211             $header_right .= $fragment->parse('slice_menu_ep.php');
212         }
213 
214         if (count($menu_items_move) > 0) {
215             $fragment = new rex_fragment();
216             $fragment->setVar('items', $menu_items_move, false);
217             $header_right .= $fragment->parse('slice_menu_move.php');
218         }
219 
220         //$header_right = $header_right != '' ? '<div class="col-md-4 text-right">' . $header_right . '</div>' : '';
221 
222         return $header_right;
223     }
224 
225     /**
226      * Wraps the output of a module.
227      *
228      * @param int    $moduleId     The id of the module
229      * @param string $moduleOutput The output of the module
230      *
231      * @return string
232      */
233     private function getWrappedModuleOutput($moduleId, $moduleOutput)
234     {
235         return $this->getStreamOutput('module/' . $moduleId . '/output', $moduleOutput);
236     }
237 
238     private function getModuleSelect($sliceId)
239     {
240         // ----- BLOCKAUSWAHL - SELECT
241         $context = new rex_context([
242             'page' => rex_be_controller::getCurrentPage(),
243             'article_id' => $this->article_id,
244             'clang' => $this->clang,
245             'ctype' => $this->ctype,
246             'slice_id' => $sliceId,
247             'function' => 'add',
248         ]);
249 
250         $position = ++$this->sliceAddPosition;
251 
252         $items = [];
253         if (isset($this->MODULESELECT[$this->ctype])) {
254             foreach ($this->MODULESELECT[$this->ctype] as $module) {
255                 $item = [];
256                 $item['title'] = rex_escape($module['name']);
257                 $item['href'] = $context->getUrl(['module_id' => $module['id']]) . '#slice-add-pos-' . $position;
258                 $items[] = $item;
259             }
260         }
261 
262         $fragment = new rex_fragment();
263         $fragment->setVar('block', true);
264         $fragment->setVar('button_label', rex_i18n::msg('add_block'));
265         $fragment->setVar('items', $items, false);
266         $select = $fragment->parse('core/dropdowns/dropdown.php');
267         $select = rex_extension::registerPoint(new rex_extension_point(
268             'STRUCTURE_CONTENT_MODULE_SELECT',
269                 $select,
270             [
271                 'page' => rex_be_controller::getCurrentPage(),
272                 'article_id' => $this->article_id,
273                 'clang' => $this->clang,
274                 'ctype' => $this->ctype,
275                 'slice_id' => $sliceId,
276             ]
277         ));
278         return '<li class="rex-slice rex-slice-select" id="slice-add-pos-' . $position . '">' . $select . '</li>';
279     }
280 
281     /**
282      * {@inheritdoc}
283      */
284     protected function preArticle($articleContent, $module_id)
285     {
286         // ---------- moduleselect: nur module nehmen auf die der user rechte hat
287         if ($this->mode == 'edit') {
288             $MODULE = rex_sql::factory();
289             $modules = $MODULE->getArray('select * from ' . rex::getTablePrefix() . 'module order by name');
290 
291             $template_ctypes = isset($this->template_attributes['ctype']) ? $this->template_attributes['ctype'] : [];
292             // wenn keine ctyes definiert sind, gibt es immer den CTYPE=1
293             if (count($template_ctypes) == 0) {
294                 $template_ctypes = [1 => 'default'];
295             }
296 
297             $this->MODULESELECT = [];
298             foreach ($template_ctypes as $ct_id => $ct_name) {
299                 foreach ($modules as $m) {
300                     if (rex::getUser()->getComplexPerm('modules')->hasPerm($m['id'])) {
301                         if (rex_template::hasModule($this->template_attributes, $ct_id, $m['id'])) {
302                             $this->MODULESELECT[$ct_id][] = ['name' => rex_i18n::translate($m['name'], false), 'id' => $m['id']];
303                         }
304                     }
305                 }
306             }
307         }
308 
309         return parent::preArticle($articleContent, $module_id);
310     }
311 
312     /**
313      * {@inheritdoc}
314      */
315     protected function postArticle($articleContent, $moduleIdToAdd)
316     {
317         // special identifier for the slot behind the last slice
318         $LCTSL_ID = -1;
319 
320         // ----- add module im edit mode
321         if ($this->mode == 'edit') {
322             if ($this->function == 'add' && $this->slice_id == $LCTSL_ID) {
323                 $slice_content = $this->addSlice($LCTSL_ID, $moduleIdToAdd);
324             } else {
325                 // ----- BLOCKAUSWAHL - SELECT
326                 $slice_content = $this->getModuleSelect($LCTSL_ID);
327             }
328             $articleContent .= $slice_content;
329         }
330 
331         return $articleContent;
332     }
333 
334     // ----- ADD Slice
335     protected function addSlice($sliceId, $moduleIdToAdd)
336     {
337         $MOD = rex_sql::factory();
338         $MOD->setQuery('SELECT * FROM ' . rex::getTablePrefix() . 'module WHERE id="' . $moduleIdToAdd . '"');
339 
340         if ($MOD->getRows() != 1) {
341             $slice_content = rex_view::warning(rex_i18n::msg('module_doesnt_exist'));
342         } else {
343             $initDataSql = rex_sql::factory();
344             $initDataSql
345                 ->setValue('module_id', $moduleIdToAdd)
346                 ->setValue('ctype_id', $this->ctype);
347 
348             // ----- PRE VIEW ACTION [ADD]
349             $action = new rex_article_action($moduleIdToAdd, 'add', $initDataSql);
350             $action->setRequestValues();
351             $action->exec(rex_article_action::PREVIEW);
352             // ----- / PRE VIEW ACTION
353 
354             $moduleInput = $this->replaceVars($initDataSql, $MOD->getValue('input'));
355 
356             $moduleInput = $this->getStreamOutput('module/' . $moduleIdToAdd . '/input', $moduleInput);
357 
358             $msg = '';
359             if ($this->warning != '') {
360                 $msg .= rex_view::warning($this->warning);
361             }
362             if ($this->info != '') {
363                 $msg .= rex_view::success($this->info);
364             }
365 
366             $formElements = [];
367 
368             $n = [];
369             $n['field'] = '<a class="btn btn-abort" href="' . rex_url::currentBackendPage(['article_id' => $this->article_id, 'slice_id' => $sliceId, 'clang' => $this->clang, 'ctype' => $this->ctype]) . '#slice-add-pos-' . $this->sliceAddPosition . '">' . rex_i18n::msg('form_abort') . '</a>';
370             $formElements[] = $n;
371 
372             $n = [];
373             $n['field'] = '<button class="btn btn-save" type="submit" name="btn_save" value="1"' . rex::getAccesskey(rex_i18n::msg('add_block'), 'save') . '>' . rex_i18n::msg('add_block') . '</button>';
374             $formElements[] = $n;
375 
376             $fragment = new rex_fragment();
377             $fragment->setVar('elements', $formElements, false);
378             $slice_footer = $fragment->parse('core/form/submit.php');
379 
380             $panel = '
381                 <fieldset>
382                     <legend>' . rex_i18n::msg('add_block') . '</legend>
383                     <input type="hidden" name="function" value="add" />
384                     <input type="hidden" name="module_id" value="' . $moduleIdToAdd . '" />
385                     <input type="hidden" name="save" value="1" />
386 
387                     <div class="rex-slice-input">
388                         ' . $moduleInput . '
389                     </div>
390                 </fieldset>
391                         ';
392 
393             $fragment = new rex_fragment();
394             $fragment->setVar('before', $msg, false);
395             $fragment->setVar('class', 'add', false);
396             $fragment->setVar('title', rex_i18n::msg('module') . ': ' . rex_i18n::translate($MOD->getValue('name')), false);
397             $fragment->setVar('body', $panel, false);
398             $fragment->setVar('footer', $slice_footer, false);
399             $slice_content = $fragment->parse('core/page/section.php');
400 
401             $slice_content = '
402                 <li class="rex-slice rex-slice-add">
403                     <form action="' . rex_url::currentBackendPage(['article_id' => $this->article_id, 'slice_id' => $sliceId, 'clang' => $this->clang, 'ctype' => $this->ctype]) . '#slice-add-pos-' . $this->sliceAddPosition . '" method="post" id="REX_FORM" enctype="multipart/form-data">
404                         ' . $slice_content . '
405                     </form>
406                     <script type="text/javascript">
407                          <!--
408                         jQuery(function($) {
409                             $(":input:visible:enabled:not([readonly]):first", $("#REX_FORM")).focus();
410                         });
411                          //-->
412                     </script>
413                 </li>
414                 ';
415         }
416 
417         return $slice_content;
418     }
419 
420     // ----- EDIT Slice
421     protected function editSlice($RE_CONTS, $RE_MODUL_IN, $RE_CTYPE, $RE_MODUL_ID, $artDataSql)
422     {
423         $msg = '';
424         if ($this->slice_id == $RE_CONTS) {
425             if ($this->warning != '') {
426                 $msg .= rex_view::warning($this->warning);
427             }
428             if ($this->info != '') {
429                 $msg .= rex_view::success($this->info);
430             }
431         }
432 
433         $formElements = [];
434 
435         $n = [];
436         $n['field'] = '<a class="btn btn-abort" href="' . rex_url::currentBackendPage(['article_id' => $this->article_id, 'slice_id' => $RE_CONTS, 'ctype' => $RE_CTYPE, 'clang' => $this->clang]) . '#slice' . $RE_CONTS . '">' . rex_i18n::msg('form_abort') . '</a>';
437         $formElements[] = $n;
438 
439         $n = [];
440         $n['field'] = '<button class="btn btn-save" type="submit" name="btn_save" value="1"' . rex::getAccesskey(rex_i18n::msg('save_block'), 'save') . '>' . rex_i18n::msg('save_block') . '</button>';
441         $formElements[] = $n;
442 
443         $n = [];
444         $n['field'] = '<button class="btn btn-apply" type="submit" name="btn_update" value="1"' . rex::getAccesskey(rex_i18n::msg('update_block'), 'apply') . '>' . rex_i18n::msg('update_block') . '</button>';
445         $formElements[] = $n;
446 
447         $fragment = new rex_fragment();
448         $fragment->setVar('elements', $formElements, false);
449         $slice_footer = $fragment->parse('core/form/submit.php');
450 
451         $panel = '
452                 <fieldset>
453                     <legend>' . rex_i18n::msg('edit_block') . '</legend>
454                     <input type="hidden" name="module_id" value="' . $RE_MODUL_ID . '" />
455                     <input type="hidden" name="save" value="1" />
456                     <input type="hidden" name="update" value="0" />
457 
458                     <div class="rex-slice-input">
459                         ' . $msg . $this->getStreamOutput('module/' . $RE_MODUL_ID . '/input', $RE_MODUL_IN) . '
460                     </div>
461                 </fieldset>
462 
463             </form>';
464 
465         $fragment = new rex_fragment();
466         $fragment->setVar('class', 'edit', false);
467         $fragment->setVar('title', $this->getSliceHeading($artDataSql), false);
468         $fragment->setVar('options', $this->getSliceMenu($artDataSql), false);
469         $fragment->setVar('body', $panel, false);
470         $fragment->setVar('footer', $slice_footer, false);
471         $slice_content = $fragment->parse('core/page/section.php');
472 
473         $slice_content = '
474             <li class="rex-slice rex-slice-edit" id="slice' . $RE_CONTS . '">
475                 <form enctype="multipart/form-data" action="' . rex_url::currentBackendPage(['article_id' => $this->article_id, 'slice_id' => $RE_CONTS, 'ctype' => $RE_CTYPE, 'clang' => $this->clang, 'function' => 'edit']) . '#slice' . $RE_CONTS . '" method="post" id="REX_FORM">
476                     ' . $slice_content . '
477                 </form>
478                 <script type="text/javascript">
479                      <!--
480                     jQuery(function($) {
481                         $(":input:visible:enabled:not([readonly]):first", $("#REX_FORM")).focus();
482                     });
483                      //-->
484                 </script>
485             </li>
486             ';
487 
488         return $slice_content;
489     }
490 }
491