Passed
Push — 1.11.x ( 3a94ac...aacdbc )
by Julito
12:47
created

Display::display_normal_message()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 3
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
5
use Chamilo\CoreBundle\Entity\ExtraField;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ExtraField. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use ChamiloSession as Session;
7
8
/**
9
 * Class Display
10
 * Contains several public functions dealing with the display of
11
 * table data, messages, help topics, ...
12
 *
13
 * Include/require it in your code to use its public functionality.
14
 * There are also several display public functions in the main api library.
15
 *
16
 * All public functions static public functions inside a class called Display,
17
 * so you use them like this: e.g.
18
 * Display::return_message($message)
19
 *
20
 * @package chamilo.library
21
 */
22
class Display
23
{
24
    /** @var Template */
25
    public static $global_template;
26
    public static $preview_style = null;
27
28
    /**
29
     * Constructor.
30
     */
31
    public function __construct()
32
    {
33
    }
34
35
    /**
36
     * @return array
37
     */
38
    public static function toolList()
39
    {
40
        return [
41
            'group',
42
            'work',
43
            'glossary',
44
            'forum',
45
            'course_description',
46
            'gradebook',
47
            'attendance',
48
            'course_progress',
49
            'notebook',
50
        ];
51
    }
52
53
    /**
54
     * Displays the page header.
55
     *
56
     * @param string The name of the page (will be showed in the page title)
57
     * @param string Optional help file name
58
     * @param string $page_header
59
     */
60
    public static function display_header(
61
        $tool_name = '',
62
        $help = null,
63
        $page_header = null
64
    ) {
65
        $origin = api_get_origin();
66
        $showHeader = true;
67
        if (isset($origin) && $origin == 'learnpath') {
68
            $showHeader = false;
69
        }
70
71
        /* USER_IN_ANON_SURVEY is defined in fillsurvey.php when survey is marked as anonymous survey */
72
        $userInAnonSurvey = defined('USER_IN_ANON_SURVEY') && USER_IN_ANON_SURVEY;
73
74
        self::$global_template = new Template($tool_name, $showHeader, $showHeader, false, $userInAnonSurvey);
75
        self::$global_template->assign('user_in_anon_survey', $userInAnonSurvey);
76
77
        // Fixing tools with any help it takes xxx part of main/xxx/index.php
78
        if (empty($help)) {
79
            $currentURL = api_get_self();
80
            preg_match('/main\/([^*\/]+)/', $currentURL, $matches);
81
            $toolList = self::toolList();
82
            if (!empty($matches)) {
83
                foreach ($matches as $match) {
84
                    if (in_array($match, $toolList)) {
85
                        $help = explode('_', $match);
86
                        $help = array_map('ucfirst', $help);
87
                        $help = implode('', $help);
88
                        break;
89
                    }
90
                }
91
            }
92
        }
93
94
        self::$global_template->setHelp($help);
95
96
        if (!empty(self::$preview_style)) {
97
            self::$global_template->preview_theme = self::$preview_style;
98
            self::$global_template->set_system_parameters();
99
            self::$global_template->setCssFiles();
100
            self::$global_template->set_js_files();
101
            self::$global_template->setCssCustomFiles();
102
        }
103
104
        if (!empty($page_header)) {
105
            self::$global_template->assign('header', $page_header);
106
        }
107
108
        echo self::$global_template->show_header_template();
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::global_template->show_header_template() targeting Template::show_header_template() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
109
    }
110
111
    /**
112
     * Displays the reduced page header (without banner).
113
     */
114
    public static function display_reduced_header()
115
    {
116
        global $show_learnpath, $tool_name;
117
        self::$global_template = new Template(
118
            $tool_name,
119
            false,
120
            false,
121
            $show_learnpath
122
        );
123
        echo self::$global_template->show_header_template();
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::global_template->show_header_template() targeting Template::show_header_template() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
124
    }
125
126
    /**
127
     * Display no header.
128
     */
129
    public static function display_no_header()
130
    {
131
        global $tool_name, $show_learnpath;
132
        $disable_js_and_css_files = true;
133
        self::$global_template = new Template(
134
            $tool_name,
135
            false,
136
            false,
137
            $show_learnpath
138
        );
139
    }
140
141
    /**
142
     * Displays the reduced page header (without banner).
143
     */
144
    public static function set_header()
145
    {
146
        global $show_learnpath, $tool_name;
147
        self::$global_template = new Template(
148
            $tool_name,
149
            false,
150
            false,
151
            $show_learnpath
152
        );
153
    }
154
155
    /**
156
     * Display the page footer.
157
     */
158
    public static function display_footer()
159
    {
160
        echo self::$global_template->show_footer_template();
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::global_template->show_footer_template() targeting Template::show_footer_template() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
161
    }
162
163
    /**
164
     * Display the page footer.
165
     */
166
    public static function display_reduced_footer()
167
    {
168
        echo '</body></html>';
169
    }
170
171
    /**
172
     * Displays the tool introduction of a tool.
173
     *
174
     * @author Patrick Cool <[email protected]>, Ghent University
175
     *
176
     * @param string $tool          these are the constants that are used for indicating the tools
177
     * @param array  $editor_config Optional configuration settings for the online editor.
178
     *                              return: $tool return a string array list with the "define" in main_api.lib
179
     *
180
     * @return string html code for adding an introduction
181
     */
182
    public static function display_introduction_section(
183
        $tool,
184
        $editor_config = null
185
    ) {
186
        echo self::return_introduction_section($tool, $editor_config);
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::return_introductio...($tool, $editor_config) targeting Display::return_introduction_section() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
187
    }
188
189
    /**
190
     * @param string $tool
191
     * @param array  $editor_config
192
     */
193
    public static function return_introduction_section(
194
        $tool,
195
        $editor_config = null
196
    ) {
197
        $moduleId = $tool;
198
        if (api_get_setting('enable_tool_introduction') == 'true' || $tool == TOOL_COURSE_HOMEPAGE) {
199
            $introduction_section = null;
200
            require api_get_path(SYS_INC_PATH).'introductionSection.inc.php';
201
202
            return $introduction_section;
203
        }
204
    }
205
206
    /**
207
     * Displays a table.
208
     *
209
     * @param array  $header          Titles for the table header
210
     *                                each item in this array can contain 3 values
211
     *                                - 1st element: the column title
212
     *                                - 2nd element: true or false (column sortable?)
213
     *                                - 3th element: additional attributes for
214
     *                                th-tag (eg for column-width)
215
     *                                - 4the element: additional attributes for the td-tags
216
     * @param array  $content         2D-array with the tables content
217
     * @param array  $sorting_options Keys are:
218
     *                                'column' = The column to use as sort-key
219
     *                                'direction' = SORT_ASC or SORT_DESC
220
     * @param array  $paging_options  Keys are:
221
     *                                'per_page_default' = items per page when switching from
222
     *                                full-    list to per-page-view
223
     *                                'per_page' = number of items to show per page
224
     *                                'page_nr' = The page to display
225
     * @param array  $query_vars      Additional variables to add in the query-string
226
     * @param array  $form_actions
227
     * @param string $style           The style that the table will show. You can set 'table' or 'grid'
228
     * @param string $tableName
229
     * @param string $tableId
230
     *
231
     * @author [email protected]
232
     */
233
    public static function display_sortable_table(
234
        $header,
235
        $content,
236
        $sorting_options = [],
237
        $paging_options = [],
238
        $query_vars = null,
239
        $form_actions = [],
240
        $style = 'table',
241
        $tableName = 'tablename',
242
        $tableId = ''
243
    ) {
244
        $column = isset($sorting_options['column']) ? $sorting_options['column'] : 0;
245
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
246
        $table = new SortableTableFromArray($content, $column, $default_items_per_page, $tableName, null, $tableId);
247
        if (is_array($query_vars)) {
248
            $table->set_additional_parameters($query_vars);
249
        }
250
        if ($style === 'table') {
251
            if (is_array($header) && count($header) > 0) {
252
                foreach ($header as $index => $header_item) {
253
                    $table->set_header(
254
                        $index,
255
                        isset($header_item[0]) ? $header_item[0] : null,
256
                        isset($header_item[1]) ? $header_item[1] : null,
257
                        isset($header_item[2]) ? $header_item[2] : null,
258
                        isset($header_item[3]) ? $header_item[3] : null
259
                    );
260
                }
261
            }
262
            $table->set_form_actions($form_actions);
263
            $table->display();
264
        } else {
265
            $table->display_grid();
266
        }
267
    }
268
269
    /**
270
     * Returns an HTML table with sortable column (through complete page refresh).
271
     *
272
     * @param array  $header
273
     * @param array  $content         Array of row arrays
274
     * @param array  $sorting_options
275
     * @param array  $paging_options
276
     * @param array  $query_vars
277
     * @param array  $form_actions
278
     * @param string $style
279
     *
280
     * @return string HTML string for array
281
     */
282
    public static function return_sortable_table(
283
        $header,
284
        $content,
285
        $sorting_options = [],
286
        $paging_options = [],
287
        $query_vars = null,
288
        $form_actions = [],
289
        $style = 'table'
290
    ) {
291
        ob_start();
292
        self::display_sortable_table(
293
            $header,
294
            $content,
295
            $sorting_options,
296
            $paging_options,
297
            $query_vars,
298
            $form_actions,
299
            $style
300
        );
301
        $content = ob_get_contents();
302
        ob_end_clean();
303
304
        return $content;
305
    }
306
307
    /**
308
     * Shows a nice grid.
309
     *
310
     * @param string grid name (important to create css)
311
     * @param array header content
312
     * @param array array with the information to show
313
     * @param array $paging_options Keys are:
314
     *                              'per_page_default' = items per page when switching from
315
     *                              full-    list to per-page-view
316
     *                              'per_page' = number of items to show per page
317
     *                              'page_nr' = The page to display
318
     *                              'hide_navigation' =  true to hide the navigation
319
     * @param array $query_vars     Additional variables to add in the query-string
320
     * @param array $form           actions Additional variables to add in the query-string
321
     * @param mixed An array with bool values to know which columns show.
322
     * i.e: $visibility_options= array(true, false) we will only show the first column
323
     *                Can be also only a bool value. TRUE: show all columns, FALSE: show nothing
324
     */
325
    public static function display_sortable_grid(
326
        $name,
327
        $header,
328
        $content,
329
        $paging_options = [],
330
        $query_vars = null,
331
        $form_actions = [],
332
        $visibility_options = true,
333
        $sort_data = true,
334
        $grid_class = []
335
    ) {
336
        echo self::return_sortable_grid(
337
            $name,
338
            $header,
339
            $content,
340
            $paging_options,
341
            $query_vars,
342
            $form_actions,
343
            $visibility_options,
344
            $sort_data,
345
            $grid_class
346
        );
347
    }
348
349
    /**
350
     * Gets a nice grid in html string.
351
     *
352
     * @param string grid name (important to create css)
353
     * @param array header content
354
     * @param array array with the information to show
355
     * @param array $paging_options Keys are:
356
     *                              'per_page_default' = items per page when switching from
357
     *                              full-    list to per-page-view
358
     *                              'per_page' = number of items to show per page
359
     *                              'page_nr' = The page to display
360
     *                              'hide_navigation' =  true to hide the navigation
361
     * @param array $query_vars     Additional variables to add in the query-string
362
     * @param array $form           actions Additional variables to add in the query-string
363
     * @param mixed An array with bool values to know which columns show. i.e:
364
     *  $visibility_options= array(true, false) we will only show the first column
365
     *    Can be also only a bool value. TRUE: show all columns, FALSE: show nothing
366
     * @param bool  true for sorting data or false otherwise
367
     * @param array grid classes
368
     *
369
     * @return string html grid
370
     */
371
    public static function return_sortable_grid(
372
        $name,
373
        $header,
374
        $content,
375
        $paging_options = [],
376
        $query_vars = null,
377
        $form_actions = [],
378
        $visibility_options = true,
379
        $sort_data = true,
380
        $grid_class = [],
381
        $elementCount = 0
382
    ) {
383
        $column = 0;
384
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
385
        $table = new SortableTableFromArray($content, $column, $default_items_per_page, $name);
386
        $table->total_number_of_items = intval($elementCount);
387
        if (is_array($query_vars)) {
388
            $table->set_additional_parameters($query_vars);
389
        }
390
391
        return $table->display_simple_grid(
392
            $visibility_options,
393
            $paging_options['hide_navigation'],
394
            $default_items_per_page,
395
            $sort_data,
396
            $grid_class
397
        );
398
    }
399
400
    /**
401
     * Displays a table with a special configuration.
402
     *
403
     * @param array $header          Titles for the table header
404
     *                               each item in this array can contain 3 values
405
     *                               - 1st element: the column title
406
     *                               - 2nd element: true or false (column sortable?)
407
     *                               - 3th element: additional attributes for th-tag (eg for column-width)
408
     *                               - 4the element: additional attributes for the td-tags
409
     * @param array $content         2D-array with the tables content
410
     * @param array $sorting_options Keys are:
411
     *                               'column' = The column to use as sort-key
412
     *                               'direction' = SORT_ASC or SORT_DESC
413
     * @param array $paging_options  Keys are:
414
     *                               'per_page_default' = items per page when switching from full list to per-page-view
415
     *                               'per_page' = number of items to show per page
416
     *                               'page_nr' = The page to display
417
     * @param array $query_vars      Additional variables to add in the query-string
418
     * @param array $column_show     Array of binaries 1= show columns 0. hide a column
419
     * @param array $column_order    An array of integers that let us decide how the columns are going to be sort.
420
     *                               i.e:  $column_order=array('1''4','3','4'); The 2nd column will be order like the 4th column
421
     * @param array $form_actions    Set optional forms actions
422
     *
423
     * @author Julio Montoya
424
     */
425
    public static function display_sortable_config_table(
426
        $table_name,
427
        $header,
428
        $content,
429
        $sorting_options = [],
430
        $paging_options = [],
431
        $query_vars = null,
432
        $column_show = [],
433
        $column_order = [],
434
        $form_actions = []
435
    ) {
436
        $column = isset($sorting_options['column']) ? $sorting_options['column'] : 0;
437
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
438
439
        $table = new SortableTableFromArrayConfig(
440
            $content,
441
            $column,
442
            $default_items_per_page,
443
            $table_name,
444
            $column_show,
445
            $column_order
446
        );
447
448
        if (is_array($query_vars)) {
449
            $table->set_additional_parameters($query_vars);
450
        }
451
        // Show or hide the columns header
452
        if (is_array($column_show)) {
453
            for ($i = 0; $i < count($column_show); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
454
                if (!empty($column_show[$i])) {
455
                    $val0 = isset($header[$i][0]) ? $header[$i][0] : null;
456
                    $val1 = isset($header[$i][1]) ? $header[$i][1] : null;
457
                    $val2 = isset($header[$i][2]) ? $header[$i][2] : null;
458
                    $val3 = isset($header[$i][3]) ? $header[$i][3] : null;
459
                    $table->set_header($i, $val0, $val1, $val2, $val3);
460
                }
461
            }
462
        }
463
        $table->set_form_actions($form_actions);
464
        $table->display();
465
    }
466
467
    /**
468
     * @param string $message
469
     * @param string $type
470
     * @param bool   $filter
471
     */
472
    public static function return_message_and_translate(
473
        $message,
474
        $type = 'normal',
475
        $filter = true
476
    ) {
477
        $message = get_lang($message);
478
        echo self::return_message($message, $type, $filter);
479
    }
480
481
    /**
482
     * Returns a div html string with.
483
     *
484
     * @param string $message
485
     * @param string $type    Example: confirm, normal, warning, error
486
     * @param bool   $filter  Whether to XSS-filter or not
487
     *
488
     * @return string Message wrapped into an HTML div
489
     */
490
    public static function return_message(
491
        $message,
492
        $type = 'normal',
493
        $filter = true
494
    ) {
495
        if (empty($message)) {
496
            return '';
497
        }
498
499
        if ($filter) {
500
            $message = api_htmlentities(
501
                $message,
502
                ENT_QUOTES,
503
                api_is_xml_http_request() ? 'UTF-8' : api_get_system_encoding()
504
            );
505
        }
506
507
        $class = '';
508
        switch ($type) {
509
            case 'warning':
510
                $class .= 'alert alert-warning';
511
                break;
512
            case 'error':
513
                $class .= 'alert alert-danger';
514
                break;
515
            case 'confirmation':
516
            case 'confirm':
517
            case 'success':
518
                $class .= 'alert alert-success';
519
                break;
520
            case 'normal':
521
            default:
522
                $class .= 'alert alert-info';
523
        }
524
525
        return self::div($message, ['class' => $class]);
526
    }
527
528
    /**
529
     * Returns an encrypted mailto hyperlink.
530
     *
531
     * @param string  e-mail
0 ignored issues
show
Documentation Bug introduced by
The doc comment e-mail at position 0 could not be parsed: Unknown type name 'e-mail' at position 0 in e-mail.
Loading history...
532
     * @param string  clickable text
533
     * @param string  optional, class from stylesheet
534
     * @param bool $addExtraContent
535
     *
536
     * @return string encrypted mailto hyperlink
537
     */
538
    public static function encrypted_mailto_link(
539
        $email,
540
        $clickable_text = null,
541
        $style_class = '',
542
        $addExtraContent = false
543
    ) {
544
        if (is_null($clickable_text)) {
545
            $clickable_text = $email;
546
        }
547
548
        // "mailto:" already present?
549
        if (substr($email, 0, 7) !== 'mailto:') {
550
            $email = 'mailto:'.$email;
551
        }
552
553
        // Class (stylesheet) defined?
554
        if ($style_class !== '') {
555
            $style_class = ' class="'.$style_class.'"';
556
        }
557
558
        // Encrypt email
559
        $hmail = '';
560
        for ($i = 0; $i < strlen($email); $i++) {
561
            $hmail .= '&#'.ord($email[$i]).';';
562
        }
563
564
        $value = api_get_configuration_value('add_user_course_information_in_mailto');
565
566
        if ($value) {
567
            if (api_get_setting('allow_email_editor') === 'false') {
568
                $hmail .= '?';
569
            }
570
571
            if (!api_is_anonymous()) {
572
                $hmail .= '&subject='.Security::remove_XSS(api_get_setting('siteName'));
573
            }
574
            if ($addExtraContent) {
575
                $content = '';
576
                if (!api_is_anonymous()) {
577
                    $userInfo = api_get_user_info();
578
                    $content .= get_lang('User').': '.$userInfo['complete_name']."\n";
579
580
                    $courseInfo = api_get_course_info();
581
                    if (!empty($courseInfo)) {
582
                        $content .= get_lang('Course').': ';
583
                        $content .= $courseInfo['name'];
584
                        $sessionInfo = api_get_session_info(api_get_session_id());
585
                        if (!empty($sessionInfo)) {
586
                            $content .= ' '.$sessionInfo['name'].' <br />';
587
                        }
588
                    }
589
                }
590
                $hmail .= '&body='.rawurlencode($content);
591
            }
592
        }
593
594
        $hclickable_text = '';
595
        // Encrypt clickable text if @ is present
596
        if (strpos($clickable_text, '@')) {
597
            for ($i = 0; $i < strlen($clickable_text); $i++) {
598
                $hclickable_text .= '&#'.ord($clickable_text[$i]).';';
599
            }
600
        } else {
601
            $hclickable_text = @htmlspecialchars(
602
                $clickable_text,
603
                ENT_QUOTES,
604
                api_get_system_encoding()
605
            );
606
        }
607
        // Return encrypted mailto hyperlink
608
        return '<a href="'.$hmail.'"'.$style_class.' class="clickable_email_link">'.$hclickable_text.'</a>';
609
    }
610
611
    /**
612
     * Returns an mailto icon hyperlink.
613
     *
614
     * @param string  e-mail
0 ignored issues
show
Documentation Bug introduced by
The doc comment e-mail at position 0 could not be parsed: Unknown type name 'e-mail' at position 0 in e-mail.
Loading history...
615
     * @param string  icon source file from the icon lib
616
     * @param int  icon size from icon lib
617
     * @param string  optional, class from stylesheet
618
     *
619
     * @return string encrypted mailto hyperlink
620
     */
621
    public static function icon_mailto_link(
622
        $email,
623
        $icon_file = "mail.png",
624
        $icon_size = 22,
625
        $style_class = ''
626
    ) {
627
        // "mailto:" already present?
628
        if (substr($email, 0, 7) != 'mailto:') {
629
            $email = 'mailto:'.$email;
630
        }
631
        // Class (stylesheet) defined?
632
        if ($style_class != '') {
633
            $style_class = ' class="'.$style_class.'"';
634
        }
635
        // Encrypt email
636
        $hmail = '';
637
        for ($i = 0; $i < strlen($email); $i++) {
638
            $hmail .= '&#'.ord($email[
639
            $i]).';';
640
        }
641
        // icon html code
642
        $icon_html_source = self::return_icon(
643
            $icon_file,
644
            $hmail,
645
            '',
646
            $icon_size
647
        );
648
        // Return encrypted mailto hyperlink
649
650
        return '<a href="'.$hmail.'"'.$style_class.' class="clickable_email_link">'.$icon_html_source.'</a>';
651
    }
652
653
    /**
654
     * Prints an <option>-list with all letters (A-Z).
655
     *
656
     * @param string $selected_letter The letter that should be selected
657
     *
658
     * @todo This is English language specific implementation.
659
     * It should be adapted for the other languages.
660
     *
661
     * @return string
662
     */
663
    public static function get_alphabet_options($selectedLetter = '')
664
    {
665
        $result = '';
666
        for ($i = 65; $i <= 90; $i++) {
667
            $letter = chr($i);
668
            $result .= '<option value="'.$letter.'"';
669
            if ($selectedLetter == $letter) {
670
                $result .= ' selected="selected"';
671
            }
672
            $result .= '>'.$letter.'</option>';
673
        }
674
675
        return $result;
676
    }
677
678
    /**
679
     * Get the options withing a select box within the given values.
680
     *
681
     * @param int   Min value
682
     * @param int   Max value
683
     * @param int   Default value
684
     *
685
     * @return string HTML select options
686
     */
687
    public static function get_numeric_options($min, $max, $selected_num = 0)
688
    {
689
        $result = '';
690
        for ($i = $min; $i <= $max; $i++) {
691
            $result .= '<option value="'.$i.'"';
692
            if (is_int($selected_num)) {
693
                if ($selected_num == $i) {
694
                    $result .= ' selected="selected"';
695
                }
696
            }
697
            $result .= '>'.$i.'</option>';
698
        }
699
700
        return $result;
701
    }
702
703
    /**
704
     * This public function displays an icon.
705
     *
706
     * @param string   The filename of the file (in the main/img/ folder
707
     * @param string   The alt text (probably a language variable)
708
     * @param array    additional attributes (for instance height, width, onclick, ...)
709
     * @param int  The wanted width of the icon (to be looked for in the corresponding img/icons/ folder)
710
     */
711
    public static function display_icon(
712
        $image,
713
        $alt_text = '',
714
        $additional_attributes = [],
715
        $size = null
716
    ) {
717
        echo self::return_icon($image, $alt_text, $additional_attributes, $size);
718
    }
719
720
    /**
721
     * Gets the path of an icon.
722
     *
723
     * @param string $icon
724
     * @param int    $size
725
     *
726
     * @return string
727
     */
728
    public static function returnIconPath($icon, $size = ICON_SIZE_SMALL)
729
    {
730
        return self::return_icon($icon, null, null, $size, null, true, false);
731
    }
732
733
    /**
734
     * This public function returns the HTML code for an icon.
735
     *
736
     * @param string $image                 The filename of the file (in the main/img/ folder
737
     * @param string $alt_text              The alt text (probably a language variable)
738
     * @param array  $additional_attributes Additional attributes (for instance height, width, onclick, ...)
739
     * @param int    $size                  The wanted width of the icon (to be looked for in the corresponding img/icons/ folder)
740
     * @param bool   $show_text             Whether to show the text next (usually under) the icon
741
     * @param bool   $return_only_path      Whether we only want the path to the icon or the whole HTML tag
742
     * @param bool   $loadThemeIcon         Whether we want to allow an overloaded theme icon, if it exists, to replace the default icon
743
     *
744
     * @return string An HTML string of the right <img> tag
745
     *
746
     * @author Patrick Cool <[email protected]>, Ghent University 2006
747
     * @author Julio Montoya 2010 Function improved, adding image constants
748
     * @author Yannick Warnier 2011 Added size handler
749
     *
750
     * @version Feb 2011
751
     */
752
    public static function return_icon(
753
        $image,
754
        $alt_text = '',
755
        $additional_attributes = [],
756
        $size = ICON_SIZE_SMALL,
757
        $show_text = true,
758
        $return_only_path = false,
759
        $loadThemeIcon = true
760
    ) {
761
        $code_path = api_get_path(SYS_CODE_PATH);
762
        $w_code_path = api_get_path(WEB_CODE_PATH);
763
        // The following path is checked to see if the file exist. It's
764
        // important to use the public path (i.e. web/css/) rather than the
765
        // internal path (/app/Resource/public/css/) because the path used
766
        // in the end must be the public path
767
        $alternateCssPath = api_get_path(SYS_PUBLIC_PATH).'css/';
768
        $alternateWebCssPath = api_get_path(WEB_PUBLIC_PATH).'css/';
769
770
        // Avoid issues with illegal string offset for legacy calls to this
771
        // method with an empty string rather than null or an empty array
772
        if (empty($additional_attributes)) {
773
            $additional_attributes = [];
774
        }
775
776
        $image = trim($image);
777
778
        if (isset($size)) {
779
            $size = intval($size);
780
        } else {
781
            $size = ICON_SIZE_SMALL;
782
        }
783
784
        $size_extra = $size.'/';
785
        $icon = $w_code_path.'img/'.$image;
786
        $theme = 'themes/chamilo/icons/';
787
788
        if ($loadThemeIcon) {
789
            $theme = 'themes/'.api_get_visual_theme().'/icons/';
790
            if (is_file($alternateCssPath.$theme.$image)) {
791
                $icon = $alternateWebCssPath.$theme.$image;
792
            }
793
            // Checking the theme icons folder example: app/Resources/public/css/themes/chamilo/icons/XXX
794
            if (is_file($alternateCssPath.$theme.$size_extra.$image)) {
795
                $icon = $alternateWebCssPath.$theme.$size_extra.$image;
796
            } elseif (is_file($code_path.'img/icons/'.$size_extra.$image)) {
797
                //Checking the main/img/icons/XXX/ folder
798
                $icon = $w_code_path.'img/icons/'.$size_extra.$image;
799
            }
800
        } else {
801
            if (is_file($code_path.'img/icons/'.$size_extra.$image)) {
802
                // Checking the main/img/icons/XXX/ folder
803
                $icon = $w_code_path.'img/icons/'.$size_extra.$image;
804
            }
805
        }
806
807
        // Special code to enable SVG - refs #7359 - Needs more work
808
        // The code below does something else to "test out" SVG: for each icon,
809
        // it checks if there is an SVG version. If so, it uses it.
810
        // When moving this to production, the return_icon() calls should
811
        // ask for the SVG version directly
812
        $svgIcons = api_get_setting('icons_mode_svg');
813
        if ($svgIcons === 'true' && $return_only_path == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
814
            $svgImage = substr($image, 0, -3).'svg';
815
            if (is_file($code_path.$theme.'svg/'.$svgImage)) {
816
                $icon = $w_code_path.$theme.'svg/'.$svgImage;
817
            } elseif (is_file($code_path.'img/icons/svg/'.$svgImage)) {
818
                $icon = $w_code_path.'img/icons/svg/'.$svgImage;
819
            }
820
821
            if (empty($additional_attributes['height'])) {
822
                $additional_attributes['height'] = $size;
823
            }
824
            if (empty($additional_attributes['width'])) {
825
                $additional_attributes['width'] = $size;
826
            }
827
        }
828
829
        $icon = api_get_cdn_path($icon);
830
831
        if ($return_only_path) {
832
            return $icon;
833
        }
834
835
        $img = self::img($icon, $alt_text, $additional_attributes);
836
        if (SHOW_TEXT_NEAR_ICONS == true && !empty($alt_text)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
837
            if ($show_text) {
838
                $img = "$img $alt_text";
839
            }
840
        }
841
842
        return $img;
843
    }
844
845
    /**
846
     * Returns the HTML code for an image.
847
     *
848
     * @param string $image_path            the filename of the file (in the main/img/ folder
849
     * @param string $alt_text              the alt text (probably a language variable)
850
     * @param array  $additional_attributes (for instance height, width, onclick, ...)
851
     * @param bool   $filterPath            Optional. Whether filter the image path. Default is true
852
     *
853
     * @return string
854
     *
855
     * @author Julio Montoya 2010
856
     */
857
    public static function img(
858
        $image_path,
859
        $alt_text = '',
860
        $additional_attributes = null,
861
        $filterPath = true
862
    ) {
863
        if (empty($image_path)) {
864
            // For some reason, the call to img() happened without a proper
865
            // image. Log the error and return an empty string to avoid
866
            // breaking the HTML
867
            $trace = debug_backtrace();
868
            $caller = $trace[1];
869
            error_log('No image provided in Display::img(). Caller info: '.print_r($caller, 1));
870
871
            return '';
872
        }
873
        // Sanitizing the parameter $image_path
874
        if ($filterPath) {
875
            $image_path = Security::filter_img_path($image_path);
876
        }
877
878
        // alt text = the image name if there is none provided (for XHTML compliance)
879
        if ($alt_text == '') {
880
            $alt_text = basename($image_path);
881
        }
882
883
        if (empty($additional_attributes)) {
884
            $additional_attributes = [];
885
        }
886
887
        $additional_attributes['src'] = $image_path;
888
889
        if (empty($additional_attributes['alt'])) {
890
            $additional_attributes['alt'] = $alt_text;
891
        }
892
        if (empty($additional_attributes['title'])) {
893
            $additional_attributes['title'] = $alt_text;
894
        }
895
896
        return self::tag('img', '', $additional_attributes);
897
    }
898
899
    /**
900
     * Returns the htmlcode for a tag (h3, h1, div, a, button), etc.
901
     *
902
     * @param string $tag                   the tag name
903
     * @param string $content               the tag's content
904
     * @param array  $additional_attributes (for instance height, width, onclick, ...)
905
     *
906
     * @return string
907
     *
908
     * @author Julio Montoya 2010
909
     */
910
    public static function tag($tag, $content, $additional_attributes = [])
911
    {
912
        $attribute_list = '';
913
        // Managing the additional attributes
914
        if (!empty($additional_attributes) && is_array($additional_attributes)) {
915
            $attribute_list = '';
916
            foreach ($additional_attributes as $key => &$value) {
917
                $attribute_list .= $key.'="'.$value.'" ';
918
            }
919
        }
920
        //some tags don't have this </XXX>
921
        if (in_array($tag, ['img', 'input', 'br'])) {
922
            $return_value = '<'.$tag.' '.$attribute_list.' />';
923
        } else {
924
            $return_value = '<'.$tag.' '.$attribute_list.' >'.$content.'</'.$tag.'>';
925
        }
926
927
        return $return_value;
928
    }
929
930
    /**
931
     * Creates a URL anchor.
932
     *
933
     * @param string $name
934
     * @param string $url
935
     * @param array  $attributes
936
     *
937
     * @return string
938
     */
939
    public static function url($name, $url, $attributes = [])
940
    {
941
        if (!empty($url)) {
942
            $url = preg_replace('#&amp;#', '&', $url);
943
            $url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
944
            $attributes['href'] = $url;
945
        }
946
947
        return self::tag('a', $name, $attributes);
948
    }
949
950
    /**
951
     * Creates a div tag.
952
     *
953
     * @param string $content
954
     * @param array  $attributes
955
     *
956
     * @return string
957
     */
958
    public static function div($content, $attributes = [])
959
    {
960
        return self::tag('div', $content, $attributes);
961
    }
962
963
    /**
964
     * Creates a span tag.
965
     */
966
    public static function span($content, $attributes = [])
967
    {
968
        return self::tag('span', $content, $attributes);
969
    }
970
971
    /**
972
     * Displays an HTML input tag.
973
     */
974
    public static function input($type, $name, $value, $attributes = [])
975
    {
976
        if (isset($type)) {
977
            $attributes['type'] = $type;
978
        }
979
        if (isset($name)) {
980
            $attributes['name'] = $name;
981
        }
982
        if (isset($value)) {
983
            $attributes['value'] = $value;
984
        }
985
986
        return self::tag('input', '', $attributes);
987
    }
988
989
    /**
990
     * @param $name
991
     * @param $value
992
     * @param array $attributes
993
     *
994
     * @return string
995
     */
996
    public static function button($name, $value, $attributes = [])
997
    {
998
        if (!empty($name)) {
999
            $attributes['name'] = $name;
1000
        }
1001
1002
        return self::tag('button', $value, $attributes);
1003
    }
1004
1005
    /**
1006
     * Displays an HTML select tag.
1007
     *
1008
     * @param string $name
1009
     * @param array  $values
1010
     * @param int    $default
1011
     * @param array  $extra_attributes
1012
     * @param bool   $show_blank_item
1013
     * @param null   $blank_item_text
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $blank_item_text is correct as it would always require null to be passed?
Loading history...
1014
     *
1015
     * @return string
1016
     */
1017
    public static function select(
1018
        $name,
1019
        $values,
1020
        $default = -1,
1021
        $extra_attributes = [],
1022
        $show_blank_item = true,
1023
        $blank_item_text = ''
1024
    ) {
1025
        $html = '';
1026
        $extra = '';
1027
        $default_id = 'id="'.$name.'" ';
1028
        $extra_attributes = array_merge(['class' => 'form-control'], $extra_attributes);
1029
        foreach ($extra_attributes as $key => $parameter) {
1030
            if ($key == 'id') {
1031
                $default_id = '';
1032
            }
1033
            $extra .= $key.'="'.$parameter.'" ';
1034
        }
1035
        $html .= '<select name="'.$name.'" '.$default_id.' '.$extra.'>';
1036
1037
        if ($show_blank_item) {
1038
            if (empty($blank_item_text)) {
1039
                $blank_item_text = get_lang('Select');
1040
            } else {
1041
                $blank_item_text = Security::remove_XSS($blank_item_text);
1042
            }
1043
            $html .= self::tag(
1044
                'option',
1045
                '-- '.$blank_item_text.' --',
1046
                ['value' => '-1']
1047
            );
1048
        }
1049
        if ($values) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $values of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1050
            foreach ($values as $key => $value) {
1051
                if (is_array($value) && isset($value['name'])) {
1052
                    $value = $value['name'];
1053
                }
1054
                $html .= '<option value="'.$key.'"';
1055
1056
                if (is_array($default)) {
1057
                    foreach ($default as $item) {
1058
                        if ($item == $key) {
1059
                            $html .= ' selected="selected"';
1060
                            break;
1061
                        }
1062
                    }
1063
                } else {
1064
                    if ($default == $key) {
1065
                        $html .= ' selected="selected"';
1066
                    }
1067
                }
1068
1069
                $html .= '>'.$value.'</option>';
1070
            }
1071
        }
1072
        $html .= '</select>';
1073
1074
        return $html;
1075
    }
1076
1077
    /**
1078
     * Creates a tab menu
1079
     * Requirements: declare the jquery, jquery-ui libraries + the jquery-ui.css
1080
     * in the $htmlHeadXtra variable before the display_header
1081
     * Add this script.
1082
     *
1083
     * @example
1084
     * <script>
1085
                </script>
1086
     * @param array  $headers       list of the tab titles
1087
     * @param array  $items
1088
     * @param string $id            id of the container of the tab in the example "tabs"
1089
     * @param array  $attributes    for the ul
1090
     * @param array  $ul_attributes
1091
     * @param int    $selected
1092
     *
1093
     * @return string
1094
     */
1095
    public static function tabs(
1096
        $headers,
1097
        $items,
1098
        $id = 'tabs',
1099
        $attributes = [],
1100
        $ul_attributes = [],
1101
        $selected = ''
1102
    ) {
1103
        if (empty($headers) || count($headers) == 0) {
1104
            return '';
1105
        }
1106
1107
        $lis = '';
1108
        $i = 1;
1109
        foreach ($headers as $item) {
1110
            $active = '';
1111
            if ($i == 1) {
1112
                $active = ' active';
1113
            }
1114
1115
            if (!empty($selected)) {
1116
                $active = '';
1117
                if ($selected == $i) {
1118
                    $active = ' active';
1119
                }
1120
            }
1121
1122
            $item = self::tag(
1123
                'a',
1124
                $item,
1125
                [
1126
                    'href' => '#'.$id.'-'.$i,
1127
                    'role' => 'tab',
1128
                    'data-toggle' => 'tab',
1129
                    'id' => $id.$i,
1130
                ]
1131
            );
1132
            $ul_attributes['role'] = 'presentation';
1133
            $ul_attributes['class'] = $active;
1134
            $lis .= self::tag('li', $item, $ul_attributes);
1135
            $i++;
1136
        }
1137
1138
        $ul = self::tag(
1139
            'ul',
1140
            $lis,
1141
            [
1142
                'class' => 'nav nav-tabs tabs-margin',
1143
                'role' => 'tablist',
1144
                'id' => 'ul_'.$id,
1145
            ]
1146
        );
1147
1148
        $i = 1;
1149
        $divs = '';
1150
        foreach ($items as $content) {
1151
            $active = '';
1152
            if ($i == 1) {
1153
                $active = ' active';
1154
            }
1155
1156
            if (!empty($selected)) {
1157
                $active = '';
1158
                if ($selected == $i) {
1159
                    $active = ' active';
1160
                }
1161
            }
1162
1163
            $divs .= self::tag(
1164
                'div',
1165
                $content,
1166
                ['id' => $id.'-'.$i, 'class' => 'tab-pane '.$active, 'role' => 'tabpanel']
1167
            );
1168
            $i++;
1169
        }
1170
1171
        $attributes['id'] = $id;
1172
        $attributes['role'] = 'tabpanel';
1173
        $attributes['class'] = 'tab-wrapper';
1174
1175
        $main_div = self::tag(
1176
            'div',
1177
            $ul.self::tag('div', $divs, ['class' => 'tab-content']),
1178
            $attributes
1179
        );
1180
1181
        return $main_div;
1182
    }
1183
1184
    /**
1185
     * @param $headers
1186
     * @param null $selected
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $selected is correct as it would always require null to be passed?
Loading history...
1187
     *
1188
     * @return string
1189
     */
1190
    public static function tabsOnlyLink($headers, $selected = null)
1191
    {
1192
        $id = uniqid();
1193
        $i = 1;
1194
        $lis = null;
1195
        foreach ($headers as $item) {
1196
            $class = null;
1197
            if ($i == $selected) {
1198
                $class = 'active';
1199
            }
1200
            $item = self::tag(
1201
                'a',
1202
                $item['content'],
1203
                ['id' => $id.'-'.$i, 'href' => $item['url']]
1204
            );
1205
            $lis .= self::tag('li', $item, ['class' => $class]);
1206
            $i++;
1207
        }
1208
1209
        return self::tag(
1210
            'ul',
1211
            $lis,
1212
            ['class' => 'nav nav-tabs tabs-margin']
1213
        );
1214
    }
1215
1216
    /**
1217
     * In order to display a grid using jqgrid you have to:.
1218
     *
1219
     * @example
1220
     * After your Display::display_header function you have to add the nex javascript code:
1221
     * <script>
1222
     *   echo Display::grid_js('my_grid_name', $url,$columns, $column_model, $extra_params,[]);
1223
     *   // for more information of this function check the grid_js() function
1224
     * </script>
1225
     * //Then you have to call the grid_html
1226
     * echo Display::grid_html('my_grid_name');
1227
     * As you can see both function use the same "my_grid_name" this is very important otherwise nothing will work
1228
     *
1229
     * @param   string  the div id, this value must be the same with the first parameter of Display::grid_js()
1230
     *
1231
     * @return string html
1232
     */
1233
    public static function grid_html($div_id)
1234
    {
1235
        $table = self::tag('table', '', ['id' => $div_id]);
1236
        $table .= self::tag('div', '', ['id' => $div_id.'_pager']);
1237
1238
        return $table;
1239
    }
1240
1241
    /**
1242
     * @param string $label
1243
     * @param string $form_item
1244
     *
1245
     * @return string
1246
     */
1247
    public static function form_row($label, $form_item)
1248
    {
1249
        $label = self::tag('label', $label, ['class' => 'col-sm-2 control-label']);
1250
        $form_item = self::div($form_item, ['class' => 'col-sm-10']);
1251
1252
        return self::div($label.$form_item, ['class' => 'form-group']);
1253
    }
1254
1255
    /**
1256
     * This is a wrapper to use the jqgrid in Chamilo.
1257
     * For the other jqgrid options visit http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options
1258
     * This function need to be in the ready jquery function
1259
     * example --> $(function() { <?php echo Display::grid_js('grid' ...); ?> }
1260
     * In order to work this function needs the Display::grid_html function with the same div id.
1261
     *
1262
     * @param string $div_id       div id
1263
     * @param string $url          url where the jqgrid will ask for data (if datatype = json)
1264
     * @param array  $column_names Visible columns (you should use get_lang).
1265
     *                             An array in which we place the names of the columns.
1266
     *                             This is the text that appears in the head of the grid (Header layer).
1267
     *                             Example: colname   {name:'date',     index:'date',   width:120, align:'right'},
1268
     * @param array  $column_model the column model :  Array which describes the parameters of the columns.
1269
     *                             This is the most important part of the grid.
1270
     *                             For a full description of all valid values see colModel API. See the url above.
1271
     * @param array  $extra_params extra parameters
1272
     * @param array  $data         data that will be loaded
1273
     * @param string $formatter    A string that will be appended to the JSON returned
1274
     * @param bool   $fixed_width  not implemented yet
1275
     *
1276
     * @return string the js code
1277
     */
1278
    public static function grid_js(
1279
        $div_id,
1280
        $url,
1281
        $column_names,
1282
        $column_model,
1283
        $extra_params,
1284
        $data = [],
1285
        $formatter = '',
1286
        $fixed_width = false
1287
    ) {
1288
        $obj = new stdClass();
1289
        $obj->first = 'first';
1290
1291
        if (!empty($url)) {
1292
            $obj->url = $url;
1293
        }
1294
1295
        //This line should only be used/modified in case of having characters
1296
        // encoding problems - see #6159
1297
        //$column_names = array_map("utf8_encode", $column_names);
1298
        $obj->colNames = $column_names;
1299
        $obj->colModel = $column_model;
1300
        $obj->pager = '#'.$div_id.'_pager';
1301
        $obj->datatype = 'json';
1302
        $obj->viewrecords = 'true';
1303
        $all_value = 10000000;
1304
1305
        // Sets how many records we want to view in the grid
1306
        $obj->rowNum = 20;
1307
1308
        // Default row quantity
1309
        if (!isset($extra_params['rowList'])) {
1310
            $extra_params['rowList'] = [20, 50, 100, 500, 1000, $all_value];
1311
            $rowList = api_get_configuration_value('table_row_list');
1312
            if (!empty($rowList) && isset($rowList['options'])) {
1313
                $rowList = $rowList['options'];
1314
                $rowList[] = $all_value;
1315
                $extra_params['rowList'] = $rowList;
1316
            }
1317
        }
1318
1319
        $defaultRow = api_get_configuration_value('table_default_row');
1320
        if (!empty($defaultRow)) {
1321
            $obj->rowNum = (int) $defaultRow;
1322
        }
1323
1324
        $json = '';
1325
        if (!empty($extra_params['datatype'])) {
1326
            $obj->datatype = $extra_params['datatype'];
1327
        }
1328
1329
        // Row even odd style.
1330
        $obj->altRows = true;
1331
        if (!empty($extra_params['altRows'])) {
1332
            $obj->altRows = $extra_params['altRows'];
1333
        }
1334
1335
        if (!empty($extra_params['sortname'])) {
1336
            $obj->sortname = $extra_params['sortname'];
1337
        }
1338
1339
        if (!empty($extra_params['sortorder'])) {
1340
            $obj->sortorder = $extra_params['sortorder'];
1341
        }
1342
1343
        if (!empty($extra_params['rowList'])) {
1344
            $obj->rowList = $extra_params['rowList'];
1345
        }
1346
1347
        if (!empty($extra_params['rowNum'])) {
1348
            $obj->rowNum = $extra_params['rowNum'];
1349
        } else {
1350
            // Try to load max rows from Session
1351
            $urlInfo = parse_url($url);
1352
            if (isset($urlInfo['query'])) {
1353
                parse_str($urlInfo['query'], $query);
1354
                if (isset($query['a'])) {
1355
                    $action = $query['a'];
1356
                    // This value is set in model.ajax.php
1357
                    $savedRows = Session::read('max_rows_'.$action);
1358
                    if (!empty($savedRows)) {
1359
                        $obj->rowNum = $savedRows;
1360
                    }
1361
                }
1362
            }
1363
        }
1364
1365
        if (!empty($extra_params['viewrecords'])) {
1366
            $obj->viewrecords = $extra_params['viewrecords'];
1367
        }
1368
1369
        $beforeSelectRow = null;
1370
        if (isset($extra_params['beforeSelectRow'])) {
1371
            $beforeSelectRow = 'beforeSelectRow: '.$extra_params['beforeSelectRow'].', ';
1372
            unset($extra_params['beforeSelectRow']);
1373
        }
1374
1375
        $beforeProcessing = '';
1376
        if (isset($extra_params['beforeProcessing'])) {
1377
            $beforeProcessing = 'beforeProcessing : function() { '.$extra_params['beforeProcessing'].' },';
1378
            unset($extra_params['beforeProcessing']);
1379
        }
1380
1381
        $beforeRequest = '';
1382
        if (isset($extra_params['beforeRequest'])) {
1383
            $beforeRequest = 'beforeRequest : function() { '.$extra_params['beforeRequest'].' },';
1384
            unset($extra_params['beforeRequest']);
1385
        }
1386
1387
        $gridComplete = '';
1388
        if (isset($extra_params['gridComplete'])) {
1389
            $gridComplete = 'gridComplete : function() { '.$extra_params['gridComplete'].' },';
1390
            unset($extra_params['gridComplete']);
1391
        }
1392
1393
        // Adding extra params
1394
        if (!empty($extra_params)) {
1395
            foreach ($extra_params as $key => $element) {
1396
                // the groupHeaders key gets a special treatment
1397
                if ($key != 'groupHeaders') {
1398
                    $obj->$key = $element;
1399
                }
1400
            }
1401
        }
1402
1403
        // Adding static data.
1404
        if (!empty($data)) {
1405
            $data_var = $div_id.'_data';
1406
            $json .= ' var '.$data_var.' = '.json_encode($data).';';
1407
            $obj->data = $data_var;
1408
            $obj->datatype = 'local';
1409
            $json .= "\n";
1410
        }
1411
1412
        $obj->end = 'end';
1413
1414
        $json_encode = json_encode($obj);
1415
1416
        if (!empty($data)) {
1417
            //Converts the "data":"js_variable" to "data":js_variable,
1418
            // otherwise it will not work
1419
            $json_encode = str_replace('"data":"'.$data_var.'"', '"data":'.$data_var.'', $json_encode);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data_var does not seem to be defined for all execution paths leading up to this point.
Loading history...
1420
        }
1421
1422
        // Fixing true/false js values that doesn't need the ""
1423
        $json_encode = str_replace(':"true"', ':true', $json_encode);
1424
        // wrap_cell is not a valid jqgrid attributes is a hack to wrap a text
1425
        $json_encode = str_replace('"wrap_cell":true', 'cellattr : function(rowId, value, rowObject, colModel, arrData) { return \'class = "jqgrid_whitespace"\'; }', $json_encode);
1426
        $json_encode = str_replace(':"false"', ':false', $json_encode);
1427
        $json_encode = str_replace('"formatter":"action_formatter"', 'formatter:action_formatter', $json_encode);
1428
        $json_encode = str_replace('"formatter":"extra_formatter"', 'formatter:extra_formatter', $json_encode);
1429
        $json_encode = str_replace(['{"first":"first",', '"end":"end"}'], '', $json_encode);
1430
1431
        if (api_get_configuration_value('allow_compilatio_tool') &&
1432
            (strpos($_SERVER['REQUEST_URI'], 'work/work.php') !== false ||
1433
             strpos($_SERVER['REQUEST_URI'], 'work/work_list_all.php') != false
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing strpos($_SERVER['REQUEST...ork/work_list_all.php') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
1434
            )
1435
        ) {
1436
            $json_encode = str_replace('"function () { compilatioInit() }"',
1437
                'function () { compilatioInit() }',
1438
                $json_encode
1439
            );
1440
        }
1441
        // Creating the jqgrid element.
1442
        $json .= '$("#'.$div_id.'").jqGrid({';
1443
        //$json .= $beforeSelectRow;
1444
        $json .= $gridComplete;
1445
        $json .= $beforeProcessing;
1446
        $json .= $beforeRequest;
1447
        $json .= $json_encode;
1448
        $json .= '});';
1449
1450
        // Grouping headers option
1451
        if (isset($extra_params['groupHeaders'])) {
1452
            $groups = '';
1453
            foreach ($extra_params['groupHeaders'] as $group) {
1454
                //{ "startColumnName" : "courses", "numberOfColumns" : 1, "titleText" : "Order Info" },
1455
                $groups .= '{ "startColumnName" : "'.$group['startColumnName'].'", "numberOfColumns" : '.$group['numberOfColumns'].', "titleText" : "'.$group['titleText'].'" },';
1456
            }
1457
            $json .= '$("#'.$div_id.'").jqGrid("setGroupHeaders", {
1458
                "useColSpanStyle" : false,
1459
                "groupHeaders"    : [
1460
                    '.$groups.'
1461
                ]
1462
            });';
1463
        }
1464
1465
        $all_text = addslashes(get_lang('All'));
1466
        $json .= '$("'.$obj->pager.' option[value='.$all_value.']").text("'.$all_text.'");';
1467
        $json .= "\n";
1468
        // Adding edit/delete icons.
1469
        $json .= $formatter;
1470
1471
        return $json;
1472
    }
1473
1474
    /**
1475
     * @param array $headers
1476
     * @param array $rows
1477
     * @param array $attributes
1478
     *
1479
     * @return string
1480
     */
1481
    public static function table($headers, $rows, $attributes = [])
1482
    {
1483
        if (empty($attributes)) {
1484
            $attributes['class'] = 'data_table';
1485
        }
1486
        $table = new HTML_Table($attributes);
1487
        $row = 0;
1488
        $column = 0;
1489
1490
        // Course headers
1491
        if (!empty($headers)) {
1492
            foreach ($headers as $item) {
1493
                $table->setHeaderContents($row, $column, $item);
1494
                $column++;
1495
            }
1496
            $row = 1;
1497
            $column = 0;
1498
        }
1499
1500
        if (!empty($rows)) {
1501
            foreach ($rows as $content) {
1502
                $table->setCellContents($row, $column, $content);
1503
                $row++;
1504
            }
1505
        }
1506
1507
        return $table->toHtml();
1508
    }
1509
1510
    /**
1511
     * Returns the "what's new" icon notifications.
1512
     *
1513
     * The general logic of this function is to track the last time the user
1514
     * entered the course and compare to what has changed inside this course
1515
     * since then, based on the item_property table inside this course. Note that,
1516
     * if the user never entered the course before, he will not see notification
1517
     * icons. This function takes session ID into account (if any) and only shows
1518
     * the corresponding notifications.
1519
     *
1520
     * @param array $courseInfo Course information array, containing at least elements 'db' and 'k'
1521
     * @param bool  $loadAjax
1522
     *
1523
     * @return string The HTML link to be shown next to the course
1524
     */
1525
    public static function show_notification($courseInfo, $loadAjax = true)
1526
    {
1527
        if (empty($courseInfo)) {
1528
            return '';
1529
        }
1530
1531
        $t_track_e_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
1532
        $course_tool_table = Database::get_course_table(TABLE_TOOL_LIST);
1533
        $tool_edit_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1534
        $course_code = Database::escape_string($courseInfo['code']);
1535
1536
        $user_id = api_get_user_id();
1537
        $course_id = (int) $courseInfo['real_id'];
1538
        $sessionId = (int) $courseInfo['id_session'];
1539
        $status = (int) $courseInfo['status'];
1540
1541
        $loadNotificationsByAjax = api_get_configuration_value('user_portal_load_notification_by_ajax');
1542
1543
        if ($loadNotificationsByAjax) {
1544
            if ($loadAjax) {
1545
                $id = 'notification_'.$course_id.'_'.$sessionId.'_'.$status;
1546
                Session::write($id, true);
1547
1548
                return '<span id ="'.$id.'" class="course_notification"></span>';
1549
            }
1550
        }
1551
1552
        // Get the user's last access dates to all tools of this course
1553
        $sql = "SELECT *
1554
                FROM $t_track_e_access
1555
                WHERE
1556
                    c_id = $course_id AND
1557
                    access_user_id = '$user_id' AND
1558
                    access_session_id ='".$sessionId."'
1559
                ORDER BY access_date DESC
1560
                LIMIT 1
1561
                ";
1562
        $result = Database::query($sql);
1563
1564
        // latest date by default is the creation date
1565
        $latestDate = $courseInfo['creation_date'];
1566
        if (Database::num_rows($result)) {
1567
            $row = Database::fetch_array($result, 'ASSOC');
1568
            $latestDate = $row['access_date'];
1569
        }
1570
1571
        $sessionCondition = api_get_session_condition(
1572
            $sessionId,
1573
            true,
1574
            false,
1575
            'session_id'
1576
        );
1577
1578
        $hideTools = [TOOL_NOTEBOOK, TOOL_CHAT];
1579
        // Get current tools in course
1580
        $sql = "SELECT name, link, image
1581
                FROM $course_tool_table
1582
                WHERE
1583
                    c_id = $course_id AND
1584
                    visibility = '1' AND
1585
                    name NOT IN ('".implode("','", $hideTools)."')
1586
                ";
1587
        $result = Database::query($sql);
1588
        $tools = Database::store_result($result);
1589
1590
        $group_ids = GroupManager::get_group_ids($courseInfo['real_id'], $user_id);
1591
        $group_ids[] = 0; //add group 'everyone'
1592
        $notifications = [];
1593
        if ($tools) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tools of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1594
            foreach ($tools as $tool) {
1595
                $toolName = $tool['name'];
1596
                $toolName = Database::escape_string($toolName);
1597
                // Fix to get student publications
1598
                $toolCondition = " tool = '$toolName' AND ";
1599
                if ($toolName == 'student_publication' || $toolName == 'work') {
1600
                    $toolCondition = " (tool = 'work' OR tool = 'student_publication') AND ";
1601
                }
1602
1603
                $toolName = addslashes($toolName);
1604
1605
                $sql = "SELECT * FROM $tool_edit_table
1606
                        WHERE
1607
                            c_id = $course_id AND
1608
                            $toolCondition
1609
                            lastedit_type NOT LIKE '%Deleted%' AND
1610
                            lastedit_type NOT LIKE '%deleted%' AND
1611
                            lastedit_type NOT LIKE '%DocumentInvisible%' AND
1612
                            lastedit_date > '$latestDate' AND
1613
                            lastedit_user_id != $user_id $sessionCondition AND
1614
                            visibility != 2 AND
1615
                            (to_user_id IN ('$user_id', '0') OR to_user_id IS NULL) AND
1616
                            (to_group_id IN ('".implode("','", $group_ids)."') OR to_group_id IS NULL)
1617
                        ORDER BY lastedit_date DESC
1618
                        LIMIT 1";
1619
                $result = Database::query($sql);
1620
1621
                $latestChange = Database::fetch_array($result, 'ASSOC');
1622
1623
                if ($latestChange) {
1624
                    $latestChange['link'] = $tool['link'];
1625
                    $latestChange['image'] = $tool['image'];
1626
                    $latestChange['tool'] = $tool['name'];
1627
                    $notifications[$toolName] = $latestChange;
1628
                }
1629
            }
1630
        }
1631
1632
        // Show all tool icons where there is something new.
1633
        $return = '';
1634
        foreach ($notifications as $notification) {
1635
            $toolName = $notification['tool'];
1636
            if (!(
1637
                    $notification['visibility'] == '1' ||
1638
                    ($status == '1' && $notification['visibility'] == '0') ||
1639
                    !isset($notification['visibility'])
1640
                )
1641
            ) {
1642
                continue;
1643
            }
1644
1645
            if ($toolName == TOOL_SURVEY) {
1646
                $survey_info = SurveyManager::get_survey($notification['ref'], 0, $course_code);
1647
                if (!empty($survey_info)) {
1648
                    $invited_users = SurveyUtil::get_invited_users(
1649
                        $survey_info['code'],
1650
                        $course_code
1651
                    );
1652
                    if (!in_array($user_id, $invited_users['course_users'])) {
1653
                        continue;
1654
                    }
1655
                }
1656
            }
1657
1658
            if ($notification['tool'] == TOOL_LEARNPATH) {
1659
                if (!learnpath::is_lp_visible_for_student($notification['ref'], $user_id, $courseInfo)) {
1660
                    continue;
1661
                }
1662
            }
1663
1664
            if ($notification['tool'] == TOOL_DROPBOX) {
1665
                $notification['link'] = 'dropbox/dropbox_download.php?id='.$notification['ref'];
1666
            }
1667
1668
            if ($notification['tool'] == 'work' &&
1669
                $notification['lastedit_type'] == 'DirectoryCreated'
1670
            ) {
1671
                $notification['lastedit_type'] = 'WorkAdded';
1672
            }
1673
1674
            $lastDate = api_get_local_time($notification['lastedit_date']);
1675
            $type = $notification['lastedit_type'];
1676
            if ($type == 'CalendareventVisible') {
1677
                $type = 'Visible';
1678
            }
1679
            $label = get_lang('TitleNotification').": ".get_lang($type)." ($lastDate)";
1680
1681
            if (strpos($notification['link'], '?') === false) {
1682
                $notification['link'] = $notification['link'].'?notification=1';
1683
            } else {
1684
                $notification['link'] = $notification['link'].'&notification=1';
1685
            }
1686
1687
            $image = substr($notification['image'], 0, -4).'.png';
1688
1689
            $return .= self::url(
1690
                self::return_icon($image, $label),
1691
                api_get_path(WEB_CODE_PATH).
1692
                $notification['link'].'&cidReq='.$course_code.
1693
                '&ref='.$notification['ref'].
1694
                '&gidReq='.$notification['to_group_id'].
1695
                '&id_session='.$sessionId
1696
            ).PHP_EOL;
1697
        }
1698
1699
        return $return;
1700
    }
1701
1702
    /**
1703
     * Get the session box details as an array.
1704
     *
1705
     * @param int       Session ID
1706
     *
1707
     * @return array Empty array or session array
1708
     *               ['title'=>'...','category'=>'','dates'=>'...','coach'=>'...','active'=>true/false,'session_category_id'=>int]
1709
     */
1710
    public static function getSessionTitleBox($session_id)
1711
    {
1712
        global $nosession;
1713
1714
        if (!$nosession) {
1715
            global $now, $date_start, $date_end;
1716
        }
1717
        $output = [];
1718
        if (!$nosession) {
1719
            $session_info = api_get_session_info($session_id);
1720
            $coachInfo = [];
1721
            if (!empty($session['id_coach'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $session does not exist. Did you maybe mean $session_info?
Loading history...
1722
                $coachInfo = api_get_user_info($session['id_coach']);
1723
            }
1724
1725
            $session = [];
1726
            $session['category_id'] = $session_info['session_category_id'];
1727
            $session['title'] = $session_info['name'];
1728
            $session['coach_id'] = $session['id_coach'] = $session_info['id_coach'];
1729
            $session['dates'] = '';
1730
            $session['coach'] = '';
1731
            if (api_get_setting('show_session_coach') === 'true' && isset($coachInfo['complete_name'])) {
1732
                $session['coach'] = get_lang('GeneralCoach').': '.$coachInfo['complete_name'];
1733
            }
1734
1735
            if (($session_info['access_end_date'] == '0000-00-00 00:00:00' &&
1736
                $session_info['access_start_date'] == '0000-00-00 00:00:00') ||
1737
                (empty($session_info['access_end_date']) && empty($session_info['access_start_date']))
1738
            ) {
1739
                if (isset($session_info['duration']) && !empty($session_info['duration'])) {
1740
                    $daysLeft = SessionManager::getDayLeftInSession($session_info, api_get_user_id());
1741
                    $session['duration'] = $daysLeft >= 0
1742
                        ? sprintf(get_lang('SessionDurationXDaysLeft'), $daysLeft)
1743
                        : get_lang('YourSessionTimeHasExpired');
1744
                }
1745
                $active = true;
1746
            } else {
1747
                $dates = SessionManager::parseSessionDates($session_info, true);
1748
                $session['dates'] = $dates['access'];
1749
                if (api_get_setting('show_session_coach') === 'true' && isset($coachInfo['complete_name'])) {
1750
                    $session['coach'] = $coachInfo['complete_name'];
1751
                }
1752
                $active = $date_start <= $now && $date_end >= $now;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $now does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $date_start does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $date_end does not seem to be defined for all execution paths leading up to this point.
Loading history...
1753
            }
1754
            $session['active'] = $active;
1755
            $session['session_category_id'] = $session_info['session_category_id'];
1756
            $session['visibility'] = $session_info['visibility'];
1757
            $session['num_users'] = $session_info['nbr_users'];
1758
            $session['num_courses'] = $session_info['nbr_courses'];
1759
            $session['description'] = $session_info['description'];
1760
            $session['show_description'] = $session_info['show_description'];
1761
1762
            $entityManager = Database::getManager();
1763
            $fieldValuesRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraFieldValues');
1764
            $extraFieldValues = $fieldValuesRepo->getVisibleValues(
1765
                ExtraField::SESSION_FIELD_TYPE,
1766
                $session_id
1767
            );
1768
1769
            $session['extra_fields'] = [];
1770
            foreach ($extraFieldValues as $value) {
1771
                $session['extra_fields'][] = [
1772
                    'field' => [
1773
                        'variable' => $value->getField()->getVariable(),
1774
                        'display_text' => $value->getField()->getDisplayText(),
1775
                    ],
1776
                    'value' => $value->getValue(),
1777
                ];
1778
            }
1779
1780
            $output = $session;
1781
        }
1782
1783
        return $output;
1784
    }
1785
1786
    /**
1787
     * Return the five star HTML.
1788
     *
1789
     * @param string $id              of the rating ul element
1790
     * @param string $url             that will be added (for jquery see hot_courses.tpl)
1791
     * @param array  $point_info      point info array see function CourseManager::get_course_ranking()
1792
     * @param bool   $add_div_wrapper add a div wrapper
1793
     *
1794
     * @return string
1795
     */
1796
    public static function return_rating_system(
1797
        $id,
1798
        $url,
1799
        $point_info = [],
1800
        $add_div_wrapper = true
1801
    ) {
1802
        $number_of_users_who_voted = isset($point_info['users_who_voted']) ? $point_info['users_who_voted'] : null;
1803
        $percentage = isset($point_info['point_average']) ? $point_info['point_average'] : 0;
1804
1805
        if (!empty($percentage)) {
1806
            $percentage = $percentage * 125 / 100;
1807
        }
1808
        $accesses = isset($point_info['accesses']) ? $point_info['accesses'] : 0;
1809
        $star_label = sprintf(get_lang('XStarsOutOf5'), $point_info['point_average_star']);
1810
1811
        $html = '<ul id="'.$id.'" class="star-rating">
1812
                    <li class="current-rating" style="width:'.$percentage.'px;"></li>
1813
                    <li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=1" title="'.$star_label.'" class="one-star">1</a></li>
1814
                    <li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=2" title="'.$star_label.'" class="two-stars">2</a></li>
1815
                    <li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=3" title="'.$star_label.'" class="three-stars">3</a></li>
1816
                    <li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=4" title="'.$star_label.'" class="four-stars">4</a></li>
1817
                    <li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=5" title="'.$star_label.'" class="five-stars">5</a></li>
1818
                </ul>';
1819
1820
        $labels = [];
1821
1822
        $labels[] = $number_of_users_who_voted == 1 ? $number_of_users_who_voted.' '.get_lang('Vote') : $number_of_users_who_voted.' '.get_lang('Votes');
1823
        $labels[] = $accesses == 1 ? $accesses.' '.get_lang('Visit') : $accesses.' '.get_lang('Visits');
1824
        $labels[] = $point_info['user_vote'] ? get_lang('YourVote').' ['.$point_info['user_vote'].']' : get_lang('YourVote').' [?] ';
1825
1826
        if (!$add_div_wrapper && api_is_anonymous()) {
1827
            $labels[] = self::tag('span', get_lang('LoginToVote'), ['class' => 'error']);
1828
        }
1829
1830
        $html .= self::div(implode(' | ', $labels), ['id' => 'vote_label_'.$id, 'class' => 'vote_label_info']);
1831
        $html .= ' '.self::span(' ', ['id' => 'vote_label2_'.$id]);
1832
1833
        if ($add_div_wrapper) {
1834
            $html = self::div($html, ['id' => 'rating_wrapper_'.$id]);
1835
        }
1836
1837
        return $html;
1838
    }
1839
1840
    /**
1841
     * @param string $title
1842
     * @param string $second_title
1843
     * @param string $size
1844
     * @param bool   $filter
1845
     *
1846
     * @return string
1847
     */
1848
    public static function page_header($title, $second_title = null, $size = 'h2', $filter = true)
1849
    {
1850
        if ($filter) {
1851
            $title = Security::remove_XSS($title);
1852
        }
1853
1854
        if (!empty($second_title)) {
1855
            if ($filter) {
1856
                $second_title = Security::remove_XSS($second_title);
1857
            }
1858
            $title .= "<small> $second_title</small>";
1859
        }
1860
1861
        return '<'.$size.' class="page-header">'.$title.'</'.$size.'>';
1862
    }
1863
1864
    public static function page_header_and_translate($title, $second_title = null)
1865
    {
1866
        $title = get_lang($title);
1867
1868
        return self::page_header($title, $second_title);
1869
    }
1870
1871
    public static function page_subheader_and_translate($title, $second_title = null)
1872
    {
1873
        $title = get_lang($title);
1874
1875
        return self::page_subheader($title, $second_title);
1876
    }
1877
1878
    public static function page_subheader($title, $second_title = null, $size = 'h3', $attributes = [])
1879
    {
1880
        if (!empty($second_title)) {
1881
            $second_title = Security::remove_XSS($second_title);
1882
            $title .= "<small> $second_title<small>";
1883
        }
1884
        $subTitle = self::tag($size, Security::remove_XSS($title), $attributes);
1885
1886
        return $subTitle;
1887
    }
1888
1889
    public static function page_subheader2($title, $second_title = null)
1890
    {
1891
        return self::page_header($title, $second_title, 'h4');
1892
    }
1893
1894
    public static function page_subheader3($title, $second_title = null)
1895
    {
1896
        return self::page_header($title, $second_title, 'h5');
1897
    }
1898
1899
    /**
1900
     * @param array $list
1901
     *
1902
     * @return string|null
1903
     */
1904
    public static function description($list)
1905
    {
1906
        $html = null;
1907
        if (!empty($list)) {
1908
            $html = '<dl class="dl-horizontal">';
1909
            foreach ($list as $item) {
1910
                $html .= '<dt>'.$item['title'].'</dt>';
1911
                $html .= '<dd>'.$item['content'].'</dd>';
1912
            }
1913
            $html .= '</dl>';
1914
        }
1915
1916
        return $html;
1917
    }
1918
1919
    /**
1920
     * @param int    $percentage      int value between 0 and 100
1921
     * @param bool   $show_percentage
1922
     * @param string $extra_info
1923
     * @param string $class           danger/success/infowarning
1924
     *
1925
     * @return string
1926
     */
1927
    public static function bar_progress($percentage, $show_percentage = true, $extra_info = '', $class = '')
1928
    {
1929
        $percentage = (int) $percentage;
1930
        $class = empty($class) ? '' : "progress-bar-$class";
1931
1932
        $div = '<div class="progress">
1933
                <div
1934
                    class="progress-bar progress-bar-striped '.$class.'"
1935
                    role="progressbar"
1936
                    aria-valuenow="'.$percentage.'"
1937
                    aria-valuemin="0"
1938
                    aria-valuemax="100"
1939
                    style="width: '.$percentage.'%;"
1940
                >';
1941
        if ($show_percentage) {
1942
            $div .= $percentage.'%';
1943
        } else {
1944
            if (!empty($extra_info)) {
1945
                $div .= $extra_info;
1946
            }
1947
        }
1948
        $div .= '</div></div>';
1949
1950
        return $div;
1951
    }
1952
1953
    /**
1954
     * @param string $count
1955
     * @param string $type
1956
     *
1957
     * @return string|null
1958
     */
1959
    public static function badge($count, $type = "warning")
1960
    {
1961
        $class = '';
1962
1963
        switch ($type) {
1964
            case 'success':
1965
                $class = 'badge-success';
1966
                break;
1967
            case 'warning':
1968
                $class = 'badge-warning';
1969
                break;
1970
            case 'important':
1971
                $class = 'badge-important';
1972
                break;
1973
            case 'info':
1974
                $class = 'badge-info';
1975
                break;
1976
            case 'inverse':
1977
                $class = 'badge-inverse';
1978
                break;
1979
        }
1980
1981
        if (!empty($count)) {
1982
            return ' <span class="badge '.$class.'">'.$count.'</span>';
1983
        }
1984
1985
        return null;
1986
    }
1987
1988
    /**
1989
     * @param array $badge_list
1990
     *
1991
     * @return string
1992
     */
1993
    public static function badge_group($badge_list)
1994
    {
1995
        $html = '<div class="badge-group">';
1996
        foreach ($badge_list as $badge) {
1997
            $html .= $badge;
1998
        }
1999
        $html .= '</div>';
2000
2001
        return $html;
2002
    }
2003
2004
    /**
2005
     * @param string $content
2006
     * @param string $type
2007
     *
2008
     * @return string
2009
     */
2010
    public static function label($content, $type = 'default')
2011
    {
2012
        switch ($type) {
2013
            case 'success':
2014
                $class = 'label-success';
2015
                break;
2016
            case 'warning':
2017
                $class = 'label-warning';
2018
                break;
2019
            case 'important':
2020
            case 'danger':
2021
                $class = 'label-danger';
2022
                break;
2023
            case 'info':
2024
                $class = 'label-info';
2025
                break;
2026
            case 'primary':
2027
                $class = 'label-primary';
2028
                break;
2029
            default:
2030
                $class = 'label-default';
2031
                break;
2032
        }
2033
2034
        $html = '';
2035
        if (!empty($content)) {
2036
            $html = '<span class="label '.$class.'">';
2037
            $html .= $content;
2038
            $html .= '</span>';
2039
        }
2040
2041
        return $html;
2042
    }
2043
2044
    /**
2045
     * @param array  $items
2046
     * @param string $class
2047
     *
2048
     * @return string|null
2049
     */
2050
    public static function actions($items, $class = 'new_actions')
2051
    {
2052
        $html = null;
2053
        if (!empty($items)) {
2054
            $html = '<div class="'.$class.'"><ul class="nav nav-pills">';
2055
            foreach ($items as $value) {
2056
                $class = null;
2057
                if (isset($value['active']) && $value['active']) {
2058
                    $class = 'class ="active"';
2059
                }
2060
2061
                if (basename($_SERVER['REQUEST_URI']) == basename($value['url'])) {
2062
                    $class = 'class ="active"';
2063
                }
2064
                $html .= "<li $class >";
2065
                $attributes = isset($value['url_attributes']) ? $value['url_attributes'] : [];
2066
                $html .= self::url($value['content'], $value['url'], $attributes);
2067
                $html .= '</li>';
2068
            }
2069
            $html .= '</ul></div>';
2070
            $html .= '<br />';
2071
        }
2072
2073
        return $html;
2074
    }
2075
2076
    /**
2077
     * Prints a tooltip.
2078
     *
2079
     * @param string $text
2080
     * @param string $tip
2081
     *
2082
     * @return string
2083
     */
2084
    public static function tip($text, $tip)
2085
    {
2086
        if (empty($tip)) {
2087
            return $text;
2088
        }
2089
2090
        return self::span(
2091
            $text,
2092
            ['class' => 'boot-tooltip', 'title' => strip_tags($tip)]
2093
        );
2094
    }
2095
2096
    /**
2097
     * @param array  $items
2098
     * @param string $type
2099
     * @param null   $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
2100
     *
2101
     * @return string|null
2102
     */
2103
    public static function generate_accordion($items, $type = 'jquery', $id = null)
2104
    {
2105
        $html = null;
2106
        if (!empty($items)) {
2107
            if (empty($id)) {
2108
                $id = api_get_unique_id();
2109
            }
2110
            if ($type == 'jquery') {
2111
                $html = '<div class="accordion_jquery" id="'.$id.'">'; //using jquery
2112
            } else {
2113
                $html = '<div class="accordion" id="'.$id.'">'; //using bootstrap
2114
            }
2115
2116
            $count = 1;
2117
            foreach ($items as $item) {
2118
                $html .= '<div class="accordion-my-group">';
2119
                $html .= '<div class="accordion-heading">
2120
                            <a class="accordion-toggle" data-toggle="collapse" data-parent="#'.$id.'" href="#collapse'.$count.'">
2121
                            '.$item['title'].'
2122
                            </a>
2123
                          </div>';
2124
2125
                $html .= '<div id="collapse'.$count.'" class="accordion-body">';
2126
                $html .= '<div class="accordion-my-inner">
2127
                            '.$item['content'].'
2128
                            </div>
2129
                          </div>';
2130
            }
2131
            $html .= '</div>';
2132
        }
2133
2134
        return $html;
2135
    }
2136
2137
    /**
2138
     * @param array $buttons
2139
     *
2140
     * @return string
2141
     */
2142
    public static function groupButton($buttons)
2143
    {
2144
        $html = '<div class="btn-group" role="group">';
2145
        foreach ($buttons as $button) {
2146
            $html .= $button;
2147
        }
2148
        $html .= '</div>';
2149
2150
        return $html;
2151
    }
2152
2153
    /**
2154
     * @todo use twig
2155
     *
2156
     * @param string $title
2157
     * @param array  $elements
2158
     * @param bool   $alignToRight
2159
     *
2160
     * @return string
2161
     */
2162
    public static function groupButtonWithDropDown($title, $elements, $alignToRight = false)
2163
    {
2164
        $html = '<div class="btn-group">
2165
                <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
2166
                '.$title.'
2167
                <span class="caret"></span></button>
2168
                <ul class="dropdown-menu '.($alignToRight ? 'dropdown-menu-right' : '').'">';
2169
        foreach ($elements as $item) {
2170
            $html .= self::tag('li', self::url($item['title'], $item['href']));
2171
        }
2172
        $html .= '</ul>
2173
            </div>';
2174
2175
        return $html;
2176
    }
2177
2178
    /**
2179
     * @param string $file
2180
     * @param array  $params
2181
     *
2182
     * @return string|null
2183
     */
2184
    public static function getMediaPlayer($file, $params = [])
2185
    {
2186
        $fileInfo = pathinfo($file);
2187
2188
        $autoplay = isset($params['autoplay']) && 'true' === $params['autoplay'] ? 'autoplay' : '';
2189
        $id = isset($params['id']) ? $params['id'] : $fileInfo['basename'];
2190
        $width = isset($params['width']) ? 'width="'.$params['width'].'"' : null;
2191
        $class = isset($params['class']) ? ' class="'.$params['class'].'"' : null;
2192
2193
        switch ($fileInfo['extension']) {
2194
            case 'mp3':
2195
            case 'webm':
2196
                $html = '<audio id="'.$id.'" '.$class.' controls '.$autoplay.' '.$width.' src="'.$params['url'].'" >';
2197
                $html .= '<object width="'.$width.'" height="50" type="application/x-shockwave-flash" data="'.api_get_path(WEB_LIBRARY_PATH).'javascript/mediaelement/flashmediaelement.swf">
2198
                            <param name="movie" value="'.api_get_path(WEB_LIBRARY_PATH).'javascript/mediaelement/flashmediaelement.swf" />
2199
                            <param name="flashvars" value="controls=true&file='.$params['url'].'" />
2200
                          </object>';
2201
                $html .= '</audio>';
2202
2203
                return $html;
2204
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2205
            case 'wav':
2206
            case 'ogg':
2207
                $html = '<audio width="300px" controls id="'.$id.'" '.$autoplay.' src="'.$params['url'].'" >';
2208
2209
                return $html;
2210
                break;
2211
        }
2212
2213
        return null;
2214
    }
2215
2216
    /**
2217
     * @param int    $nextValue
2218
     * @param array  $list
2219
     * @param int    $current
2220
     * @param int    $fixedValue
2221
     * @param array  $conditions
2222
     * @param string $link
2223
     * @param bool   $isMedia
2224
     * @param bool   $addHeaders
2225
     * @param array  $linkAttributes
2226
     *
2227
     * @return string
2228
     */
2229
    public static function progressPaginationBar(
2230
        $nextValue,
2231
        $list,
2232
        $current,
2233
        $fixedValue = null,
2234
        $conditions = [],
2235
        $link = null,
2236
        $isMedia = false,
2237
        $addHeaders = true,
2238
        $linkAttributes = []
2239
    ) {
2240
        if ($addHeaders) {
2241
            $pagination_size = 'pagination-mini';
2242
            $html = '<div class="exercise_pagination pagination '.$pagination_size.'"><ul>';
2243
        } else {
2244
            $html = null;
2245
        }
2246
        $affectAllItems = false;
2247
        if ($isMedia && isset($fixedValue) && ($nextValue + 1 == $current)) {
2248
            $affectAllItems = true;
2249
        }
2250
        $localCounter = 0;
2251
        foreach ($list as $itemId) {
2252
            $isCurrent = false;
2253
            if ($affectAllItems) {
2254
                $isCurrent = true;
2255
            } else {
2256
                if (!$isMedia) {
2257
                    $isCurrent = $current == ($localCounter + $nextValue + 1) ? true : false;
2258
                }
2259
            }
2260
            $html .= self::parsePaginationItem(
2261
                $itemId,
2262
                $isCurrent,
2263
                $conditions,
2264
                $link,
2265
                $nextValue,
2266
                $isMedia,
2267
                $localCounter,
2268
                $fixedValue,
2269
                $linkAttributes
2270
            );
2271
            $localCounter++;
2272
        }
2273
        if ($addHeaders) {
2274
            $html .= '</ul></div>';
2275
        }
2276
2277
        return $html;
2278
    }
2279
2280
    /**
2281
     * @param int    $itemId
2282
     * @param bool   $isCurrent
2283
     * @param array  $conditions
2284
     * @param string $link
2285
     * @param int    $nextValue
2286
     * @param bool   $isMedia
2287
     * @param int    $localCounter
2288
     * @param int    $fixedValue
2289
     * @param array  $linkAttributes
2290
     *
2291
     * @return string
2292
     */
2293
    public static function parsePaginationItem(
2294
        $itemId,
2295
        $isCurrent,
2296
        $conditions,
2297
        $link,
2298
        $nextValue = 0,
2299
        $isMedia = false,
2300
        $localCounter = null,
2301
        $fixedValue = null,
2302
        $linkAttributes = []
2303
    ) {
2304
        $defaultClass = 'before';
2305
        $class = $defaultClass;
2306
        foreach ($conditions as $condition) {
2307
            $array = isset($condition['items']) ? $condition['items'] : [];
2308
            $class_to_applied = $condition['class'];
2309
            $type = isset($condition['type']) ? $condition['type'] : 'positive';
2310
            $mode = isset($condition['mode']) ? $condition['mode'] : 'add';
2311
            switch ($type) {
2312
                case 'positive':
2313
                    if (in_array($itemId, $array)) {
2314
                        if ($mode == 'overwrite') {
2315
                            $class = " $defaultClass $class_to_applied";
2316
                        } else {
2317
                            $class .= " $class_to_applied";
2318
                        }
2319
                    }
2320
                    break;
2321
                case 'negative':
2322
                    if (!in_array($itemId, $array)) {
2323
                        if ($mode == 'overwrite') {
2324
                            $class = " $defaultClass $class_to_applied";
2325
                        } else {
2326
                            $class .= " $class_to_applied";
2327
                        }
2328
                    }
2329
                    break;
2330
            }
2331
        }
2332
        if ($isCurrent) {
2333
            $class = 'before current';
2334
        }
2335
        if ($isMedia && $isCurrent) {
2336
            $class = 'before current';
2337
        }
2338
        if (empty($link)) {
2339
            $link_to_show = '#';
2340
        } else {
2341
            $link_to_show = $link.($nextValue + $localCounter);
2342
        }
2343
        $label = $nextValue + $localCounter + 1;
2344
        if ($isMedia) {
2345
            $label = ($fixedValue + 1).' '.chr(97 + $localCounter);
2346
            $link_to_show = $link.$fixedValue.'#questionanchor'.$itemId;
2347
        }
2348
        $link = self::url($label.' ', $link_to_show, $linkAttributes);
2349
2350
        return  '<li class = "'.$class.'">'.$link.'</li>';
2351
    }
2352
2353
    /**
2354
     * @param int $current
2355
     * @param int $total
2356
     *
2357
     * @return string
2358
     */
2359
    public static function paginationIndicator($current, $total)
2360
    {
2361
        $html = null;
2362
        if (!empty($current) && !empty($total)) {
2363
            $label = sprintf(get_lang('PaginationXofY'), $current, $total);
2364
            $html = self::url($label, '#', ['class' => 'btn disabled']);
2365
        }
2366
2367
        return $html;
2368
    }
2369
2370
    /**
2371
     * @param $url
2372
     * @param $currentPage
2373
     * @param $pagesCount
2374
     * @param $totalItems
2375
     *
2376
     * @return string
2377
     */
2378
    public static function getPagination($url, $currentPage, $pagesCount, $totalItems)
2379
    {
2380
        $pagination = '';
2381
        if ($totalItems > 1 && $pagesCount > 1) {
2382
            $pagination .= '<ul class="pagination">';
2383
            for ($i = 0; $i < $pagesCount; $i++) {
2384
                $newPage = $i + 1;
2385
                if ($currentPage == $newPage) {
2386
                    $pagination .= '<li class="active"><a href="'.$url.'&page='.$newPage.'">'.$newPage.'</a></li>';
2387
                } else {
2388
                    $pagination .= '<li><a href="'.$url.'&page='.$newPage.'">'.$newPage.'</a></li>';
2389
                }
2390
            }
2391
            $pagination .= '</ul>';
2392
        }
2393
2394
        return $pagination;
2395
    }
2396
2397
    /**
2398
     * Adds a message in the queue.
2399
     *
2400
     * @param string $message
2401
     */
2402
    public static function addFlash($message)
2403
    {
2404
        $messages = Session::read('flash_messages');
2405
        if (empty($messages)) {
2406
            $messages[] = $message;
2407
        } else {
2408
            array_push($messages, $message);
2409
        }
2410
        Session::write('flash_messages', $messages);
2411
    }
2412
2413
    /**
2414
     * @return string
2415
     */
2416
    public static function getFlashToString()
2417
    {
2418
        $messages = Session::read('flash_messages');
2419
        $messageToString = '';
2420
        if (!empty($messages)) {
2421
            foreach ($messages as $message) {
2422
                $messageToString .= $message;
2423
            }
2424
        }
2425
2426
        return $messageToString;
2427
    }
2428
2429
    /**
2430
     * Shows the message from the session.
2431
     */
2432
    public static function showFlash()
2433
    {
2434
        echo self::getFlashToString();
2435
    }
2436
2437
    /**
2438
     * Destroys the message session.
2439
     */
2440
    public static function cleanFlashMessages()
2441
    {
2442
        Session::erase('flash_messages');
2443
    }
2444
2445
    /**
2446
     * Get the profile edition link for a user.
2447
     *
2448
     * @param int  $userId  The user id
2449
     * @param bool $asAdmin Optional. Whether get the URL for the platform admin
2450
     *
2451
     * @return string The link
2452
     */
2453
    public static function getProfileEditionLink($userId, $asAdmin = false)
2454
    {
2455
        $editProfileUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
2456
        if ($asAdmin) {
2457
            $editProfileUrl = api_get_path(WEB_CODE_PATH)."admin/user_edit.php?user_id=".intval($userId);
2458
        }
2459
2460
        if (api_get_setting('sso_authentication') === 'true') {
2461
            $subSSOClass = api_get_setting('sso_authentication_subclass');
2462
            $objSSO = null;
2463
2464
            if (!empty($subSSOClass)) {
2465
                $file = api_get_path(SYS_CODE_PATH)."auth/sso/sso.$subSSOClass.class.php";
2466
                if (file_exists($file)) {
2467
                    require_once $file;
2468
                    $subSSOClass = 'sso'.$subSSOClass;
2469
                    $objSSO = new $subSSOClass();
2470
                } else {
2471
                    throw new Exception("$subSSOClass file not set");
2472
                }
2473
            } else {
2474
                $objSSO = new sso();
2475
            }
2476
2477
            $editProfileUrl = $objSSO->generateProfileEditingURL(
2478
                $userId,
2479
                $asAdmin
2480
            );
2481
        }
2482
2483
        return $editProfileUrl;
2484
    }
2485
2486
    /**
2487
     * Get the vCard for a user.
2488
     *
2489
     * @param int $userId The user id
2490
     *
2491
     * @return string *.*vcf file
2492
     */
2493
    public static function getVCardUserLink($userId)
2494
    {
2495
        $vCardUrl = api_get_path(WEB_PATH).'main/social/vcard_export.php?userId='.intval($userId);
2496
2497
        return $vCardUrl;
2498
    }
2499
2500
    /**
2501
     * @param string $content
2502
     * @param string $title
2503
     * @param string $footer
2504
     * @param string $type            primary|success|info|warning|danger
2505
     * @param string $extra
2506
     * @param string $id
2507
     * @param string $backgroundColor
2508
     * @param string $extraClass
2509
     *
2510
     * @return string
2511
     */
2512
    public static function panel(
2513
        $content,
2514
        $title = '',
2515
        $footer = '',
2516
        $type = 'default',
2517
        $extra = '',
2518
        $id = '',
2519
        $backgroundColor = '',
2520
        $extraClass = ''
2521
    ) {
2522
        $headerStyle = '';
2523
        if (!empty($backgroundColor)) {
2524
            $headerStyle = 'style = "color: white; background-color: '.$backgroundColor.'" ';
2525
        }
2526
2527
        $title = !empty($title) ? '<div class="panel-heading" '.$headerStyle.' ><h3 class="panel-title">'.$title.'</h3>'.$extra.'</div>' : '';
2528
        $footer = !empty($footer) ? '<div class="panel-footer">'.$footer.'</div>' : '';
2529
        $typeList = ['primary', 'success', 'info', 'warning', 'danger'];
2530
        $style = !in_array($type, $typeList) ? 'default' : $type;
2531
2532
        if (!empty($id)) {
2533
            $id = " id='$id'";
2534
        }
2535
2536
        return '
2537
            <div '.$id.' class="panel panel-'.$style.' '.$extraClass.' ">
2538
                '.$title.'
2539
                '.self::contentPanel($content).'
2540
                '.$footer.'
2541
            </div>'
2542
        ;
2543
    }
2544
2545
    /**
2546
     * @param string $content
2547
     *
2548
     * @return string
2549
     */
2550
    public static function contentPanel($content)
2551
    {
2552
        if (empty($content)) {
2553
            return '';
2554
        }
2555
2556
        return '<div class="panel-body">'.$content.'</div>';
2557
    }
2558
2559
    /**
2560
     * Get the button HTML with an Awesome Font icon.
2561
     *
2562
     * @param string $text        The button content
2563
     * @param string $url         The url to button
2564
     * @param string $icon        The Awesome Font class for icon
2565
     * @param string $type        Optional. The button Bootstrap class. Default 'default' class
2566
     * @param array  $attributes  The additional attributes
2567
     * @param bool   $includeText
2568
     *
2569
     * @return string The button HTML
2570
     */
2571
    public static function toolbarButton(
2572
        $text,
2573
        $url,
2574
        $icon = 'check',
2575
        $type = 'default',
2576
        array $attributes = [],
2577
        $includeText = true
2578
    ) {
2579
        $buttonClass = "btn btn-$type";
2580
        $icon = self::tag('i', null, ['class' => "fa fa-$icon fa-fw", 'aria-hidden' => 'true']);
2581
        $attributes['class'] = isset($attributes['class']) ? "$buttonClass {$attributes['class']}" : $buttonClass;
2582
        $attributes['title'] = isset($attributes['title']) ? $attributes['title'] : $text;
2583
2584
        if (!$includeText) {
2585
            $text = '<span class="sr-only">'.$text.'</span>';
2586
        }
2587
2588
        return self::url("$icon $text", $url, $attributes);
2589
    }
2590
2591
    /**
2592
     * @param string $id
2593
     * @param array  $content
2594
     * @param array  $colsWidth Optional. Columns width
2595
     *
2596
     * @return string
2597
     */
2598
    public static function toolbarAction($id, $content, $colsWidth = [])
2599
    {
2600
        $col = count($content);
2601
2602
        if (!$colsWidth) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $colsWidth of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2603
            $width = 12 / $col;
2604
            array_walk($content, function () use ($width, &$colsWidth) {
2605
                $colsWidth[] = $width;
2606
            });
2607
        }
2608
2609
        $html = '<div id="'.$id.'" class="actions">';
2610
        $html .= '<div class="row">';
2611
2612
        for ($i = 0; $i < $col; $i++) {
2613
            $class = 'col-sm-'.$colsWidth[$i];
2614
2615
            if ($col > 1) {
2616
                if ($i > 0 && $i < count($content) - 1) {
2617
                    $class .= ' text-center';
2618
                } elseif ($i === count($content) - 1) {
2619
                    $class .= ' text-right';
2620
                }
2621
            }
2622
2623
            $html .= '<div class="'.$class.'">'.$content[$i].'</div>';
2624
        }
2625
2626
        $html .= '</div>';
2627
        $html .= '</div>';
2628
2629
        return $html;
2630
    }
2631
2632
    /**
2633
     * Get a HTML code for a icon by Font Awesome.
2634
     *
2635
     * @param string     $name            The icon name. Example: "mail-reply"
2636
     * @param int|string $size            Optional. The size for the icon. (Example: lg, 2, 3, 4, 5)
2637
     * @param bool       $fixWidth        Optional. Whether add the fw class
2638
     * @param string     $additionalClass Optional. Additional class
2639
     *
2640
     * @return string
2641
     */
2642
    public static function returnFontAwesomeIcon(
2643
        $name,
2644
        $size = '',
2645
        $fixWidth = false,
2646
        $additionalClass = ''
2647
    ) {
2648
        $className = "fa fa-$name";
2649
2650
        if ($fixWidth) {
2651
            $className .= ' fa-fw';
2652
        }
2653
2654
        switch ($size) {
2655
            case 'lg':
2656
                $className .= ' fa-lg';
2657
                break;
2658
            case 2:
2659
            case 3:
2660
            case 4:
2661
            case 5:
2662
                $className .= " fa-{$size}x";
2663
                break;
2664
        }
2665
2666
        if (!empty($additionalClass)) {
2667
            $className .= " $additionalClass";
2668
        }
2669
2670
        $icon = self::tag('em', null, ['class' => $className]);
2671
2672
        return "$icon ";
2673
    }
2674
2675
    /**
2676
     * @param string     $title
2677
     * @param string     $content
2678
     * @param null       $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
2679
     * @param array      $params
2680
     * @param null       $idAccordion
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $idAccordion is correct as it would always require null to be passed?
Loading history...
2681
     * @param null       $idCollapse
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $idCollapse is correct as it would always require null to be passed?
Loading history...
2682
     * @param bool|true  $open
2683
     * @param bool|false $fullClickable
2684
     *
2685
     * @return string|null
2686
     *
2687
     * @todo rework function to easy use
2688
     */
2689
    public static function panelCollapse(
2690
        $title,
2691
        $content,
2692
        $id = null,
2693
        $params = [],
2694
        $idAccordion = null,
2695
        $idCollapse = null,
2696
        $open = true,
2697
        $fullClickable = false
2698
    ) {
2699
        if (!empty($idAccordion)) {
2700
            $headerClass = '';
2701
            $headerClass .= $fullClickable ? 'center-block ' : '';
2702
            $headerClass .= $open ? '' : 'collapsed';
2703
            $contentClass = 'panel-collapse collapse ';
2704
            $contentClass .= $open ? 'in' : '';
2705
            $ariaExpanded = $open ? 'true' : 'false';
2706
2707
            $html = <<<HTML
2708
                <div class="panel-group" id="$idAccordion" role="tablist" aria-multiselectable="true">
2709
                    <div class="panel panel-default" id="$id">
2710
                        <div class="panel-heading" role="tab">
2711
                            <h4 class="panel-title">
2712
                                <a class="$headerClass" role="button" data-toggle="collapse" data-parent="#$idAccordion" href="#$idCollapse" aria-expanded="$ariaExpanded" aria-controls="$idCollapse">$title</a>
2713
                            </h4>
2714
                        </div>
2715
                        <div id="$idCollapse" class="$contentClass" role="tabpanel">
2716
                            <div class="panel-body">$content</div>
2717
                        </div>
2718
                    </div>
2719
                </div>
2720
HTML;
2721
        } else {
2722
            if (!empty($id)) {
2723
                $params['id'] = $id;
2724
            }
2725
            $params['class'] = 'panel panel-default';
2726
            $html = null;
2727
            if (!empty($title)) {
2728
                $html .= '<div class="panel-heading">'.$title.'</div>'.PHP_EOL;
2729
            }
2730
            $html .= '<div class="panel-body">'.$content.'</div>'.PHP_EOL;
2731
            $html = self::div($html, $params);
2732
        }
2733
2734
        return $html;
2735
    }
2736
2737
    /**
2738
     * Returns the string "1 day ago" with a link showing the exact date time.
2739
     *
2740
     * @param string $dateTime in UTC or a DateTime in UTC
2741
     *
2742
     * @return string
2743
     */
2744
    public static function dateToStringAgoAndLongDate($dateTime)
2745
    {
2746
        if (empty($dateTime) || $dateTime === '0000-00-00 00:00:00') {
2747
            return '';
2748
        }
2749
2750
        if ($dateTime instanceof \DateTime) {
0 ignored issues
show
introduced by
$dateTime is never a sub-type of DateTime.
Loading history...
2751
            $dateTime = $dateTime->format('Y-m-d H:i:s');
2752
        }
2753
2754
        return self::tip(
2755
            date_to_str_ago($dateTime),
2756
            api_convert_and_format_date($dateTime, DATE_TIME_FORMAT_LONG)
2757
            //api_get_local_time($dateTime)
2758
        );
2759
    }
2760
2761
    /**
2762
     * @param array  $userInfo
2763
     * @param string $status
2764
     * @param string $toolbar
2765
     *
2766
     * @return string
2767
     */
2768
    public static function getUserCard($userInfo, $status = '', $toolbar = '')
2769
    {
2770
        if (empty($userInfo)) {
2771
            return '';
2772
        }
2773
2774
        if (!empty($status)) {
2775
            $status = '<div class="items-user-status">'.$status.'</div>';
2776
        }
2777
2778
        if (!empty($toolbar)) {
2779
            $toolbar = '<div class="btn-group pull-right">'.$toolbar.'</div>';
2780
        }
2781
2782
        return '<div id="user_card_'.$userInfo['id'].'" class="col-md-12">
2783
                    <div class="row">
2784
                        <div class="col-md-2">
2785
                            <img src="'.$userInfo['avatar'].'" class="img-responsive img-circle">
2786
                        </div>
2787
                        <div class="col-md-10">
2788
                           <p>'.$userInfo['complete_name'].'</p>
2789
                           <div class="row">
2790
                           <div class="col-md-2">
2791
                           '.$status.'
2792
                           </div>
2793
                           <div class="col-md-10">
2794
                           '.$toolbar.'
2795
                           </div>
2796
                           </div>
2797
                        </div>
2798
                    </div>
2799
                    <hr />
2800
              </div>';
2801
    }
2802
2803
    /**
2804
     * @param string $fileName
2805
     * @param string $fileUrl
2806
     *
2807
     * @return string
2808
     */
2809
    public static function fileHtmlGuesser($fileName, $fileUrl)
2810
    {
2811
        $data = pathinfo($fileName);
2812
2813
        //$content = self::url($data['basename'], $fileUrl);
2814
        $content = '';
2815
        switch ($data['extension']) {
2816
            case 'webm':
2817
            case 'mp4':
2818
            case 'ogg':
2819
                $content = '<video style="width: 400px; height:100%;" src="'.$fileUrl.'"></video>';
2820
                // Allows video to play when loading during an ajax call
2821
                $content .= "<script>jQuery('video:not(.skip), audio:not(.skip)').mediaelementplayer();</script>";
2822
                break;
2823
            case 'jpg':
2824
            case 'jpeg':
2825
            case 'gif':
2826
            case 'png':
2827
                $content = '<img class="img-responsive" src="'.$fileUrl.'" />';
2828
                break;
2829
            default:
2830
                //$html = self::url($data['basename'], $fileUrl);
2831
                break;
2832
        }
2833
        //$html = self::url($content, $fileUrl, ['ajax']);
2834
2835
        return $content;
2836
    }
2837
2838
    /**
2839
     * @param string $frameName
2840
     *
2841
     * @return string
2842
     */
2843
    public static function getFrameReadyBlock($frameName)
2844
    {
2845
        $webPublicPath = api_get_path(WEB_PUBLIC_PATH);
2846
        $webJsPath = api_get_path(WEB_LIBRARY_JS_PATH);
2847
2848
        $videoFeatures = [
2849
            'playpause',
2850
            'current',
2851
            'progress',
2852
            'duration',
2853
            'tracks',
2854
            'volume',
2855
            'fullscreen',
2856
            'vrview',
2857
            'markersrolls',
2858
        ];
2859
        $features = api_get_configuration_value('video_features');
2860
        $videoPluginsJS = [];
2861
        $videoPluginCSS = [];
2862
        if (!empty($features) && isset($features['features'])) {
2863
            foreach ($features['features'] as $feature) {
2864
                if ($feature === 'vrview') {
2865
                    continue;
2866
                }
2867
                $defaultFeatures[] = $feature;
2868
                $videoPluginsJS[] = "mediaelement/plugins/$feature/$feature.min.js";
2869
                $videoPluginCSS[] = "mediaelement/plugins/$feature/$feature.min.css";
2870
            }
2871
        }
2872
2873
        $videoPluginFiles = '';
2874
        foreach ($videoPluginsJS as $file) {
2875
            $videoPluginFiles .= '{type: "script", src: "'.$webJsPath.$file.'"},';
2876
        }
2877
2878
        $videoPluginCssFiles = '';
2879
        foreach ($videoPluginCSS as $file) {
2880
            $videoPluginCssFiles .= '{type: "stylesheet", src: "'.$webJsPath.$file.'"},';
2881
        }
2882
2883
        $translateHtml = '';
2884
        $translate = api_get_configuration_value('translate_html');
2885
        if ($translate) {
2886
            $translateHtml = '{type:"script", src:"'.api_get_path(WEB_AJAX_PATH).'lang.ajax.php?a=translate_html&'.api_get_cidreq().'"},';
2887
        }
2888
2889
        $fixLinkSetting = api_get_configuration_value('lp_fix_embed_content');
2890
        $fixLink = '';
2891
        if ($fixLinkSetting) {
2892
            $fixLink = '{type:"script", src:"'.api_get_path(WEB_LIBRARY_PATH).'fixlinks.js"},';
2893
        }
2894
2895
        $videoFeatures = implode("','", $videoFeatures);
2896
        $frameReady = '
2897
        $.frameReady(function() {
2898
             $(function () {
2899
                $("video:not(.skip), audio:not(.skip)").mediaelementplayer({
2900
                    pluginPath: "'.$webJsPath.'mediaelement/plugins/",
2901
                    features: [\''.$videoFeatures.'\'],
2902
                    success: function(mediaElement, originalNode, instance) {
2903
                        '.ChamiloApi::getQuizMarkersRollsJS().'
2904
                    },
2905
                    vrPath: "'.$webPublicPath.'assets/vrview/build/vrview.js"
2906
                });
2907
            });
2908
        },
2909
        "'.$frameName.'",
2910
        [
2911
            {type:"script", src:"'.api_get_jquery_web_path().'", deps: [
2912
2913
                '.$fixLink.'
2914
                {type:"script", src:"'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.highlight.js"},
2915
                {type:"script", src:"'.api_get_path(WEB_CODE_PATH).'glossary/glossary.js.php?'.api_get_cidreq().'"},
2916
                {type:"script", src:"'.$webPublicPath.'assets/jquery-ui/jquery-ui.min.js"},
2917
                {type:"script", src: "'.$webPublicPath.'assets/mediaelement/build/mediaelement-and-player.min.js",
2918
                    deps: [
2919
                    {type:"script", src: "'.$webJsPath.'mediaelement/plugins/vrview/vrview.js"},
2920
                    {type:"script", src: "'.$webJsPath.'mediaelement/plugins/markersrolls/markersrolls.min.js"},
2921
                    '.$videoPluginFiles.'
2922
                ]},
2923
                '.$translateHtml.'
2924
            ]},
2925
            '.$videoPluginCssFiles.'
2926
            {type:"script", src:"'.$webPublicPath.'assets/MathJax/MathJax.js?config=AM_HTMLorMML"},
2927
            {type:"stylesheet", src:"'.$webPublicPath.'assets/jquery-ui/themes/smoothness/jquery-ui.min.css"},
2928
            {type:"stylesheet", src:"'.$webPublicPath.'assets/jquery-ui/themes/smoothness/theme.css"},
2929
            {type:"stylesheet", src:"'.$webPublicPath.'css/dialog.css"},
2930
            {type:"stylesheet", src: "'.$webPublicPath.'assets/mediaelement/build/mediaelementplayer.min.css"},
2931
            {type:"stylesheet", src: "'.$webJsPath.'mediaelement/plugins/vrview/vrview.css"},
2932
        ]);';
2933
2934
        return $frameReady;
2935
    }
2936
2937
    /**
2938
     * @param string $image
2939
     * @param int    $size
2940
     *
2941
     * @return string
2942
     */
2943
    public static function get_icon_path($image, $size = ICON_SIZE_SMALL)
2944
    {
2945
        return self::return_icon($image, '', [], $size, false, true);
2946
    }
2947
2948
    /**
2949
     * @param string $image
2950
     * @param int    $size
2951
     * @param string $name
2952
     *
2953
     * @return string
2954
     */
2955
    public static function get_image($image, $size = ICON_SIZE_SMALL, $name = '')
2956
    {
2957
        return self::return_icon($image, $name, [], $size);
2958
    }
2959
}
2960