1 <?php
  2 
  3 /**
  4  * @package redaxo\core
  5  */
  6 class rex_view
  7 {
  8     const JS_DEFERED = 'defer';
  9     const JS_ASYNC = 'async';
 10     const JS_IMMUTABLE = 'immutable';
 11 
 12     private static $cssFiles = [];
 13     private static $jsFiles = [];
 14     private static $jsProperties = [];
 15     private static $favicon;
 16 
 17     /**
 18      * Adds a CSS file.
 19      *
 20      * @param string $file
 21      * @param string $media
 22      *
 23      * @throws rex_exception
 24      */
 25     public static function addCssFile($file, $media = 'all')
 26     {
 27         if (isset(self::$cssFiles[$media]) && in_array($file, self::$cssFiles[$media])) {
 28             throw new rex_exception(sprintf('The CSS file "%s" is already added to media "%s".', $file, $media));
 29         }
 30 
 31         self::$cssFiles[$media][] = $file;
 32     }
 33 
 34     /**
 35      * Returns the CSS files.
 36      *
 37      * @return string[]
 38      */
 39     public static function getCssFiles()
 40     {
 41         return self::$cssFiles;
 42     }
 43 
 44     /**
 45      * Adds a JS file.
 46      *
 47      * @param string $file
 48      *
 49      * @throws rex_exception
 50      */
 51     public static function addJsFile($file, array $options = [])
 52     {
 53         if (empty($options)) {
 54             $options[self::JS_IMMUTABLE] = false;
 55         }
 56 
 57         if (in_array($file, self::$jsFiles)) {
 58             throw new rex_exception(sprintf('The JS file "%s" is already added.', $file));
 59         }
 60 
 61         self::$jsFiles[] = [$file, $options];
 62     }
 63 
 64     /**
 65      * Returns the JS files.
 66      *
 67      * @return string[]
 68      */
 69     public static function getJsFiles()
 70     {
 71         // transform for BC
 72         return array_map(function ($jsFile) {
 73             return $jsFile[0];
 74         }, self::$jsFiles);
 75     }
 76 
 77     /**
 78      * Returns all JS files besides their options.
 79      *
 80      * @return array
 81      */
 82     public static function getJsFilesWithOptions()
 83     {
 84         return self::$jsFiles;
 85     }
 86 
 87     /**
 88      * Sets a JS property.
 89      *
 90      * @param string $key
 91      * @param mixed  $value
 92      */
 93     public static function setJsProperty($key, $value)
 94     {
 95         self::$jsProperties[$key] = $value;
 96     }
 97 
 98     /**
 99      * Returns the JS properties.
100      *
101      * @return array
102      */
103     public static function getJsProperties()
104     {
105         return self::$jsProperties;
106     }
107 
108     /**
109      * Sets the favicon path.
110      *
111      * @param string $file
112      */
113     public static function setFavicon($file)
114     {
115         self::$favicon = $file;
116     }
117 
118     /**
119      * Returns the favicon.
120      *
121      * @return string
122      */
123     public static function getFavicon()
124     {
125         return self::$favicon;
126     }
127 
128     /**
129      * Returns an info message.
130      *
131      * @param string $message
132      * @param string $cssClass
133      *
134      * @return string
135      */
136     public static function info($message, $cssClass = '')
137     {
138         $cssClassMessage = 'alert-info';
139         if ($cssClass != '') {
140             $cssClassMessage .= ' ' . $cssClass;
141         }
142 
143         return self::message($message, $cssClassMessage);
144     }
145 
146     /**
147      * Returns a success message.
148      *
149      * @param string $message
150      * @param string $cssClass
151      *
152      * @return string
153      */
154     public static function success($message, $cssClass = '')
155     {
156         $cssClassMessage = 'alert-success';
157         if ($cssClass != '') {
158             $cssClassMessage .= ' ' . $cssClass;
159         }
160 
161         return self::message($message, $cssClassMessage);
162     }
163 
164     /**
165      * Returns an warning message.
166      *
167      * @param string $message
168      * @param string $cssClass
169      *
170      * @return string
171      */
172     public static function warning($message, $cssClass = '')
173     {
174         $cssClassMessage = 'alert-warning';
175         if ($cssClass != '') {
176             $cssClassMessage .= ' ' . $cssClass;
177         }
178 
179         return self::message($message, $cssClassMessage);
180     }
181 
182     /**
183      * Returns an error message.
184      *
185      * @param string $message
186      * @param string $cssClass
187      *
188      * @return string
189      */
190     public static function error($message, $cssClass = '')
191     {
192         $cssClassMessage = 'alert-danger';
193         if ($cssClass != '') {
194             $cssClassMessage .= ' ' . $cssClass;
195         }
196 
197         return self::message($message, $cssClassMessage);
198     }
199 
200     /**
201      * Returns a message.
202      *
203      * @param string $message
204      * @param string $cssClass
205      *
206      * @return string
207      */
208     private static function message($message, $cssClass)
209     {
210         $cssClassMessage = 'alert';
211         if ($cssClass != '') {
212             $cssClassMessage .= ' ' . $cssClass;
213         }
214 
215         $return = '<div class="' . $cssClassMessage . '">' . $message . '</div>';
216 
217         /*
218         $fragment = new rex_fragment();
219         $fragment->setVar('class', $cssClass);
220         $fragment->setVar('message', $content, false);
221         $return = $fragment->parse('message.php');
222         */
223         return $return;
224     }
225 
226     /**
227      * Returns a toolbar.
228      *
229      * @param string $content
230      * @param string $brand
231      * @param string $cssClass
232      *
233      * @return string
234      */
235     public static function toolbar($content, $brand = null, $cssClass = null, $inverse = false)
236     {
237         $fragment = new rex_fragment();
238         $fragment->setVar('inverse', $inverse);
239         $fragment->setVar('cssClass', $cssClass);
240         $fragment->setVar('brand', $brand);
241         $fragment->setVar('content', $content, false);
242         $return = $fragment->parse('core/toolbar.php');
243 
244         return $return;
245     }
246 
247     /**
248      * Returns a content block.
249      *
250      * @param string $content
251      * @param string $title
252      *
253      * @return string
254      */
255     public static function content($content, $title = '')
256     {
257         $fragment = new rex_fragment();
258         $fragment->setVar('title', $title, false);
259         $fragment->setVar('body', $content, false);
260         return $fragment->parse('core/page/section.php');
261     }
262 
263     /**
264      * Returns the formatted title.
265      *
266      * @param string            $head
267      * @param null|string|array $subtitle
268      *
269      * @throws InvalidArgumentException
270      *
271      * @return string
272      */
273     public static function title($head, $subtitle = null)
274     {
275         if ($subtitle !== null && !is_string($subtitle) && (!is_array($subtitle) || count($subtitle) > 0 && !reset($subtitle) instanceof rex_be_page)) {
276             throw new InvalidArgumentException('Expecting $subtitle to be a string or an array of rex_be_page!');
277         }
278 
279         if ($subtitle === null) {
280             $subtitle = rex_be_controller::getPageObject(rex_be_controller::getCurrentPagePart(1))->getSubpages();
281         }
282 
283         if (is_array($subtitle) && count($subtitle) && reset($subtitle) instanceof rex_be_page) {
284             $nav = rex_be_navigation::factory();
285             $nav->setHeadline('default', rex_i18n::msg('subnavigation', $head));
286             foreach ($subtitle as $pageObj) {
287                 $nav->addPage($pageObj);
288             }
289             $blocks = $nav->getNavigation();
290             $navigation = [];
291             if (count($blocks) == 1) {
292                 $navigation = current($blocks);
293                 $navigation = $navigation['navigation'];
294             }
295 
296             if (!empty($navigation)) {
297                 $fragment = new rex_fragment();
298                 $fragment->setVar('left', $navigation, false);
299                 $subtitle = $fragment->parse('core/navigations/content.php');
300             } else {
301                 $subtitle = '';
302             }
303         } elseif (!is_string($subtitle)) {
304             $subtitle = '';
305         }
306 
307         $title = rex_extension::registerPoint(new rex_extension_point('PAGE_TITLE', $head));
308 
309         $fragment = new rex_fragment();
310         $fragment->setVar('heading', $title, false);
311         $fragment->setVar('subtitle', $subtitle, false);
312         $return = $fragment->parse('core/page/header.php');
313 
314         $return .= rex_extension::registerPoint(new rex_extension_point('PAGE_TITLE_SHOWN', ''));
315 
316         return $return;
317     }
318 
319     /**
320      * Returns a clang switch.
321      *
322      * @param rex_context $context
323      * @param bool        $drop
324      *
325      * @return string
326      */
327     public static function clangSwitch(rex_context $context, $drop = true)
328     {
329         if (rex_clang::count() == 1) {
330             return '';
331         }
332 
333         if ($drop && rex_clang::count() >= 4) {
334             return self::clangSwitchAsDropdown($context);
335         }
336 
337         $items = [];
338         foreach (rex_clang::getAll() as $id => $clang) {
339             if (rex::getUser()->getComplexPerm('clang')->hasPerm($id)) {
340                 $icon = ($id == $context->getParam('clang')) ? '<i class="rex-icon rex-icon-language-active"></i> ' : '<i class="rex-icon rex-icon-language"></i> ';
341                 $item = [];
342                 $item['href'] = $context->getUrl(['clang' => $id]);
343                 $item['title'] = $icon . rex_i18n::translate($clang->getName());
344                 if ($id == $context->getParam('clang')) {
345                     $item['active'] = true;
346                 }
347                 $items[] = $item;
348             }
349         }
350         $fragment = new rex_fragment();
351         $fragment->setVar('left', $items, false);
352 
353         return $fragment->parse('core/navigations/content.php');
354     }
355 
356     /**
357      * Returns a clang switch.
358      *
359      * @param rex_context $context
360      * @param bool        $drop
361      *
362      * @return string
363      */
364     public static function clangSwitchAsButtons(rex_context $context, $drop = true)
365     {
366         if (rex_clang::count() == 1) {
367             return '';
368         }
369 
370         if ($drop && rex_clang::count() >= 4) {
371             return self::clangSwitchAsDropdown($context);
372         }
373 
374         $items = [];
375         foreach (rex_clang::getAll() as $id => $clang) {
376             if (rex::getUser()->getComplexPerm('clang')->hasPerm($id)) {
377                 $icon = $clang->isOnline() ? '<i class="rex-icon rex-icon-online"></i> ' : '<i class="rex-icon rex-icon-offline"></i> ';
378                 $item = [];
379                 $item['label'] = $icon . rex_i18n::translate($clang->getName());
380                 $item['url'] = $context->getUrl(['clang' => $id]);
381                 $item['attributes']['class'][] = 'btn-clang';
382                 $item['attributes']['title'] = rex_i18n::translate($clang->getName());
383                 if ($id == $context->getParam('clang')) {
384                     $item['attributes']['class'][] = 'active';
385                 }
386                 $items[] = $item;
387             }
388         }
389 
390         $fragment = new rex_fragment();
391         $fragment->setVar('buttons', $items, false);
392         return '<div class="rex-nav-btn rex-nav-language"><div class="btn-toolbar">' . $fragment->parse('core/buttons/button_group.php') . '</div></div>';
393     }
394 
395     /**
396      * Returns a clang switch.
397      *
398      * @param rex_context $context
399      *
400      * @return string
401      */
402     public static function clangSwitchAsDropdown(rex_context $context)
403     {
404         if (rex_clang::count() == 1) {
405             return '';
406         }
407 
408         $button_label = '';
409         $items = [];
410         foreach (rex_clang::getAll() as $id => $clang) {
411             if (rex::getUser()->getComplexPerm('clang')->hasPerm($id)) {
412                 $item = [];
413                 $item['title'] = rex_i18n::translate($clang->getName());
414                 $item['href'] = $context->getUrl(['clang' => $id]);
415                 if ($id == $context->getParam('clang')) {
416                     $item['active'] = true;
417                     $button_label = rex_i18n::translate($clang->getName());
418                 }
419                 $items[] = $item;
420             }
421         }
422 
423         $fragment = new rex_fragment();
424         $fragment->setVar('class', 'rex-language');
425         $fragment->setVar('button_prefix', rex_i18n::msg('language'));
426         $fragment->setVar('button_label', $button_label);
427         $fragment->setVar('header', rex_i18n::msg('clang_select'));
428         $fragment->setVar('items', $items, false);
429 
430         if (rex::getUser()->isAdmin()) {
431             $fragment->setVar('footer', '<a href="' . rex_url::backendPage('system/lang') . '"><i class="fa fa-flag"></i> ' . rex_i18n::msg('languages_edit') . '</a>', false);
432         }
433 
434         return $fragment->parse('core/dropdowns/dropdown.php');
435     }
436 }
437