Completed
Push — master ( 81a867...33ec7a )
by Julito
33:04
created

Display::page_header_and_translate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

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 Chamilo\CoreBundle\Framework\Container;
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::display_normal_message($message)
19
 *
20
 * @package chamilo.library
21
 *
22
 */
23
class Display
24
{
25
    /** @var Template */
26
    public static $global_template;
27
    public static $preview_style = null;
28
29
    /**
30
     * Constructor
31
     */
32
    public function __construct()
33
    {
34
    }
35
36
    /**
37
     * @return array
38
     */
39
    public static function toolList()
40
    {
41
        return array(
42
            'group',
43
            'work',
44
            'glossary',
45
            'forum',
46
            'course_description',
47
            'gradebook',
48
            'attendance',
49
            'course_progress',
50
            'notebook'
51
        );
52
    }
53
54
    /**
55
     * Displays the page header
56
     *
57
     * @deprecated See template.lib.php class documentation
58
     *
59
     * @param string The name of the page (will be showed in the page title)
60
     * @param string Optional help file name
61
     * @param string $page_header
62
     */
63
    public static function display_header($tool_name ='', $help = null, $page_header = null)
64
    {
65
        return '';
66
        $origin = api_get_origin();
0 ignored issues
show
Unused Code introduced by
$origin = api_get_origin(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
67
        $showHeader = true;
68
        if (isset($origin) && $origin == 'learnpath') {
69
            $showHeader = false;
70
        }
71
72
        self::$global_template = new Template($tool_name, $showHeader, $showHeader);
73
74
75
        // Fixing tools with any help it takes xxx part of main/xxx/index.php
76
        if (empty($help)) {
77
            $currentURL = api_get_self();
78
            preg_match('/main\/([^*\/]+)/', $currentURL, $matches);
79
            $toolList = self::toolList();
80
            if (!empty($matches)) {
81
                foreach ($matches as $match) {
82
                    if (in_array($match, $toolList)) {
83
                        $help = explode('_', $match);
84
                        $help = array_map('ucfirst', $help);
85
                        $help = implode('', $help);
86
                        break;
87
                    }
88
                }
89
            }
90
        }
91
92
        self::$global_template->setHelp($help);
93
        if (!empty(self::$preview_style)) {
94
            self::$global_template->preview_theme = self::$preview_style;
95
            self::$global_template->setCssFiles();
96
            self::$global_template->set_js_files();
97
            self::$global_template->setCssCustomFiles();
98
        }
99
100
        if (!empty($page_header)) {
101
            self::$global_template->assign('header', $page_header);
102
        }
103
104
        echo self::$global_template->show_header_template();
105
    }
106
107
    /**
108
     * Displays the reduced page header (without banner)
109
     * @deprecated See template.lib.php class documentation
110
     */
111 View Code Duplication
    public static function display_reduced_header()
112
    {
113
        return '';
114
        global $show_learnpath, $tool_name;
0 ignored issues
show
Unused Code introduced by
global $show_learnpath, $tool_name; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
115
        self::$global_template = new Template($tool_name, false, false, $show_learnpath);
116
        echo self::$global_template->show_header_template();
117
    }
118
119
    /**
120
     * Display no header
121
     * @deprecated
122
     */
123 View Code Duplication
    public static function display_no_header()
124
    {
125
        return '';
126
        global $tool_name, $show_learnpath;
0 ignored issues
show
Unused Code introduced by
global $tool_name, $show_learnpath; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
127
        $disable_js_and_css_files = true;
128
        self::$global_template = new Template($tool_name, false, false, $show_learnpath);
129
    }
130
131
    /**
132
     * Displays the reduced page header (without banner)
133
     * @deprecated See template.lib.php class documentation
134
     */
135
    public static function set_header()
136
    {
137
        return '';
138
        global $show_learnpath, $tool_name;
0 ignored issues
show
Unused Code introduced by
global $show_learnpath, $tool_name; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
139
        self::$global_template = new Template($tool_name, false, false, $show_learnpath);
140
    }
141
142
    /**
143
     * Display the page footer
144
     * @deprecated  See template.lib.php class documentation
145
     */
146
    public static function display_footer()
147
    {
148
        return '';
149
        echo self::$global_template->show_footer_template();
0 ignored issues
show
Unused Code introduced by
echo self::$global_templ...show_footer_template(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
150
    }
151
152
    /**
153
     * Display the page footer
154
     * @deprecated See template.lib.php class documentation
155
     */
156
    public static function display_reduced_footer()
157
    {
158
        return '';
159
        echo self::$global_template->show_footer_js_template();
0 ignored issues
show
Unused Code introduced by
echo self::$global_templ...w_footer_js_template(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
160
        echo '</body></html>';
161
    }
162
163
    /**
164
     * Displays the tool introduction of a tool.
165
     *
166
     * @author Patrick Cool <[email protected]>, Ghent University
167
     * @param string $tool These are the constants that are used for indicating the tools.
168
     * @param array $editor_config Optional configuration settings for the online editor.
169
     * return: $tool return a string array list with the "define" in main_api.lib
170
     * @return html code for adding an introduction
171
     */
172
    public static function display_introduction_section($tool, $editor_config = null)
173
    {
174
        echo self::return_introduction_section($tool, $editor_config);
175
    }
176
177
    /**
178
     * @param string $tool
179
     * @param array $editor_config
180
     * @return null
181
     */
182
    public static function return_introduction_section($tool, $editor_config = null)
183
    {
184
        $is_allowed_to_edit = api_is_allowed_to_edit();
185
        $moduleId = $tool;
186
        if (api_get_setting('enable_tool_introduction') == 'true' || $tool == TOOL_COURSE_HOMEPAGE) {
187
            $introduction_section = null;
188
            require api_get_path(SYS_INC_PATH).'introductionSection.inc.php';
189
            return $introduction_section;
190
        }
191
    }
192
193
    /**
194
     *	Displays a localised html file
195
     *	tries to show the file "$full_file_name"."_".$language_interface.".html"
196
     *	and if this does not exist, shows the file "$full_file_name".".html"
197
     *	warning this public function defines a global
198
     *	@param $full_file_name, the (path) name of the file, without .html
199
     *	@return return a string with the path
200
     */
201
    public static function display_localised_html_file($full_file_name)
202
    {
203
        global $language_interface;
204
        $localised_file_name = $full_file_name.'_'.$language_interface.'.html';
205
        $default_file_name = $full_file_name.'.html';
206
        if (file_exists($localised_file_name)) {
207
            include $localised_file_name;
208
        } else {
209
            include $default_file_name;
210
        }
211
    }
212
213
    /**
214
     * Displays a table
215
     * @param array $header Titles for the table header
216
     * 						each item in this array can contain 3 values
217
     * 						- 1st element: the column title
218
     * 						- 2nd element: true or false (column sortable?)
219
     * 						- 3th element: additional attributes for
220
     *  						th-tag (eg for column-width)
221
     * 						- 4the element: additional attributes for the td-tags
222
     * @param array $content 2D-array with the tables content
223
     * @param array $sorting_options Keys are:
224
     * 					'column' = The column to use as sort-key
225
     * 					'direction' = SORT_ASC or SORT_DESC
226
     * @param array $paging_options Keys are:
227
     * 					'per_page_default' = items per page when switching from
228
     * 										 full-	list to per-page-view
229
     * 					'per_page' = number of items to show per page
230
     * 					'page_nr' = The page to display
231
     * @param array $query_vars Additional variables to add in the query-string
232
     * @param string The style that the table will show. You can set 'table' or 'grid'
233
     * @author [email protected]
234
     */
235
    public static function display_sortable_table(
236
        $header,
237
        $content,
238
        $sorting_options = array(),
239
        $paging_options = array(),
240
        $query_vars = null,
241
        $form_actions = array(),
242
        $style = 'table'
243
    ) {
244
        global $origin;
245
        $column = isset($sorting_options['column']) ? $sorting_options['column'] : 0;
246
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
247
        $table = new SortableTableFromArray($content, $column, $default_items_per_page);
248
        if (is_array($query_vars)) {
249
            $table->set_additional_parameters($query_vars);
250
        }
251
        if ($style == 'table') {
252
            if (is_array($header) && count($header) > 0) {
253
                foreach ($header as $index => $header_item) {
254
                    $table->set_header(
255
                        $index,
256
                        isset($header_item[0]) ? $header_item[0] : null,
257
                        isset($header_item[1]) ? $header_item[1] : null,
258
                        isset($header_item[2]) ? $header_item[2] : null,
259
                        isset($header_item[3]) ? $header_item[3] : null
260
                    );
261
                }
262
            }
263
            $table->set_form_actions($form_actions);
264
            $table->display();
265
        } else {
266
            $table->display_grid();
267
        }
268
    }
269
270
    public static function return_sortable_table(
271
        $header,
272
        $content,
273
        $sorting_options = array(),
274
        $paging_options = array(),
275
        $query_vars = null,
276
        $form_actions = array(),
277
        $style = 'table'
278
    ) {
279
        ob_start();
280
        self::display_sortable_table(
281
            $header,
282
            $content,
283
            $sorting_options,
284
            $paging_options,
285
            $query_vars,
286
            $form_actions,
287
            $style
288
        );
289
        $content = ob_get_contents();
290
        ob_end_clean();
291
        return $content;
292
    }
293
294
    /**
295
     * Shows a nice grid
296
     * @param string grid name (important to create css)
297
     * @param array header content
298
     * @param array array with the information to show
299
     * @param array $paging_options Keys are:
300
     * 					'per_page_default' = items per page when switching from
301
     * 										 full-	list to per-page-view
302
     * 					'per_page' = number of items to show per page
303
     * 					'page_nr' = The page to display
304
     * 					'hide_navigation' =  true to hide the navigation
305
     * @param array $query_vars Additional variables to add in the query-string
306
     * @param array $form actions Additional variables to add in the query-string
0 ignored issues
show
Bug introduced by
There is no parameter named $form. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
307
     * @param mixed An array with bool values to know which columns show.
308
     * i.e: $visibility_options= array(true, false) we will only show the first column
309
     * 				Can be also only a bool value. TRUE: show all columns, FALSE: show nothing
310
     */
311
    public static function display_sortable_grid(
312
        $name,
313
        $header,
314
        $content,
315
        $paging_options = array(),
316
        $query_vars = null,
317
        $form_actions = array(),
318
        $visibility_options = true,
319
        $sort_data = true,
320
        $grid_class = array()
321
    ) {
322
        echo self::return_sortable_grid(
323
            $name,
324
            $header,
325
            $content,
326
            $paging_options,
327
            $query_vars,
328
            $form_actions,
329
            $visibility_options,
330
            $sort_data,
331
            $grid_class
332
        );
333
    }
334
335
    /**
336
     * Gets a nice grid in html string
337
     * @param string grid name (important to create css)
338
     * @param array header content
339
     * @param array array with the information to show
340
     * @param array $paging_options Keys are:
341
     * 					'per_page_default' = items per page when switching from
342
     * 										 full-	list to per-page-view
343
     * 					'per_page' = number of items to show per page
344
     * 					'page_nr' = The page to display
345
     * 					'hide_navigation' =  true to hide the navigation
346
     * @param array $query_vars Additional variables to add in the query-string
347
     * @param array $form actions Additional variables to add in the query-string
0 ignored issues
show
Bug introduced by
There is no parameter named $form. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
348
     * @param mixed An array with bool values to know which columns show. i.e:
349
     *  $visibility_options= array(true, false) we will only show the first column
350
     * 	Can be also only a bool value. TRUE: show all columns, FALSE: show nothing
351
     * @param bool  true for sorting data or false otherwise
352
     * @param array grid classes
353
     * @return 	string   html grid
354
     */
355
    public static function return_sortable_grid(
356
        $name,
357
        $header,
358
        $content,
359
        $paging_options = array(),
360
        $query_vars = null,
361
        $form_actions = array(),
362
        $visibility_options = true,
363
        $sort_data = true,
364
        $grid_class = array(),
365
        $elementCount = 0
366
    ) {
367
        $column =  0;
368
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
369
370
        $table = new SortableTableFromArray($content, $column, $default_items_per_page, $name);
371
        $table->total_number_of_items = intval($elementCount);
372
        if (is_array($query_vars)) {
373
            $table->set_additional_parameters($query_vars);
374
        }
375
376
        return $table->display_simple_grid(
377
            $visibility_options,
378
            $paging_options['hide_navigation'],
379
            $default_items_per_page,
380
            $sort_data,
381
            $grid_class
382
        );
383
    }
384
385
    /**
386
     * Displays a table with a special configuration
387
     * @param array $header Titles for the table header
388
     * 						each item in this array can contain 3 values
389
     * 						- 1st element: the column title
390
     * 						- 2nd element: true or false (column sortable?)
391
     * 						- 3th element: additional attributes for
392
     *  						th-tag (eg for column-width)
393
     * 						- 4the element: additional attributes for the td-tags
394
     * @param array $content 2D-array with the tables content
395
     * @param array $sorting_options Keys are:
396
     * 					'column' = The column to use as sort-key
397
     * 					'direction' = SORT_ASC or SORT_DESC
398
     * @param array $paging_options Keys are:
399
     * 					'per_page_default' = items per page when switching from
400
     * 										 full-	list to per-page-view
401
     * 					'per_page' = number of items to show per page
402
     * 					'page_nr' = The page to display
403
     * @param array $query_vars Additional variables to add in the query-string
404
     * @param array $column_show Array of binaries 1= show columns 0. hide a column
405
     * @param array $column_order An array of integers that let us decide how the columns are going to be sort.
406
     * 						      i.e:  $column_order=array('1''4','3','4'); The 2nd column will be order like the 4th column
407
     * @param array $form_actions Set optional forms actions
408
     *
409
     * @author Julio Montoya
410
     */
411
    public static function display_sortable_config_table(
412
        $table_name,
413
        $header,
414
        $content,
415
        $sorting_options = array(),
416
        $paging_options = array(),
417
        $query_vars = null,
418
        $column_show = array(),
419
        $column_order = array(),
420
        $form_actions = array()
421
    ) {
422
        $column = isset($sorting_options['column']) ? $sorting_options['column'] : 0;
423
        $default_items_per_page = isset($paging_options['per_page']) ? $paging_options['per_page'] : 20;
424
425
        $table = new SortableTableFromArrayConfig(
426
            $content,
427
            $column,
428
            $default_items_per_page,
429
            $table_name,
430
            $column_show,
431
            $column_order
432
        );
433
434
        if (is_array($query_vars)) {
435
            $table->set_additional_parameters($query_vars);
436
        }
437
        // Show or hide the columns header
438
        if (is_array($column_show)) {
439
            for ($i = 0; $i < count($column_show); $i++) {
440
                if (!empty($column_show[$i])) {
441
                    $val0 = isset($header[$i][0]) ? $header[$i][0] : null;
442
                    $val1 = isset($header[$i][1]) ? $header[$i][1] : null;
443
                    $val2 = isset($header[$i][2]) ? $header[$i][2] : null;
444
                    $val3 = isset($header[$i][3]) ? $header[$i][3] : null;
445
                    $table->set_header($i, $val0, $val1, $val2, $val3);
446
                }
447
            }
448
        }
449
        $table->set_form_actions($form_actions);
450
        $table->display();
451
    }
452
453
    /**
454
     * Displays a normal message. It is recommended to use this public function
455
     * to display any normal information messages.
456
     * @param string $message
457
     * @param bool	$filter (true) or not (false)
458
     * @param bool $returnValue
459
     *
460
     * @deprecated use Display::addFlash with Display::return_message($message, 'normal');
461
     *
462
     * @return void
463
     */
464 View Code Duplication
    public static function display_normal_message($message, $filter = true, $returnValue = false)
465
    {
466
    	$message = self::return_message($message, 'normal', $filter);
467
        if ($returnValue) {
468
            return $message;
469
        } else {
470
            echo $message;
471
        }
472
    }
473
474
    /**
475
     * Displays an warning message. Use this if you want to draw attention to something
476
     * This can also be used for instance with the hint in the exercises
477
     *
478
     * @deprecated use Display::addFlash with Display::return_message
479
     */
480 View Code Duplication
    public static function display_warning_message($message, $filter = true, $returnValue = false)
481
    {
482
        $message = self::return_message($message, 'warning', $filter);
483
        if ($returnValue) {
484
            return $message;
485
        } else {
486
            echo $message;
487
        }
488
    }
489
490
    /**
491
     * Displays an confirmation message. Use this if something has been done successfully
492
     * @param bool	Filter (true) or not (false)
493
     * @deprecated use Display::addFlash with Display::return_message
494
     * @return void
495
     */
496 View Code Duplication
    public static function display_confirmation_message ($message, $filter = true, $returnValue = false)
497
    {
498
        $message = self::return_message($message, 'confirm', $filter);
499
        if ($returnValue) {
500
            return $message;
501
        } else {
502
            echo $message;
503
        }
504
    }
505
506
    /**
507
     * Displays an error message. It is recommended to use this public function if an error occurs
508
     * @param string $message - include any additional html
509
     *                          tags if you need them
510
     * @param bool	Filter (true) or not (false)
511
     * @deprecated use Display::addFlash with Display::return_message
512
     *
513
     * @return void
514
     */
515 View Code Duplication
    public static function display_error_message ($message, $filter = true, $returnValue = false)
516
    {
517
        $message = self::return_message($message, 'error', $filter);
518
        if ($returnValue) {
519
            return $message;
520
        } else {
521
            echo $message;
522
        }
523
    }
524
525
    /**
526
     * @param string $message
527
     * @param string $type
528
     * @param bool $filter
529
     */
530
    public static function return_message_and_translate($message, $type='normal', $filter = true)
531
    {
532
        $message = get_lang($message);
533
        echo self::return_message($message, $type, $filter);
534
    }
535
536
    /**
537
     * Returns a div html string with
538
     * @param   string  $message
539
     * @param   string  $type Example: confirm, normal, warning, error
540
     * @param   bool    $filter Whether to XSS-filter or not
541
     * @return  string  Message wrapped into an HTML div
542
     */
543
    public static function return_message($message, $type = 'normal', $filter = true)
544
    {
545
        if (empty($message)) {
546
            return '';
547
        }
548
549
        if ($filter) {
550
        	$message = api_htmlentities($message, ENT_QUOTES, api_is_xml_http_request() ? 'UTF-8' : api_get_system_encoding());
551
        }
552
553
        $class = '';
554
        switch ($type) {
555
            case 'warning':
556
               $class .= 'alert alert-warning';
557
               break;
558
            case 'error':
559
               $class .= 'alert alert-danger';
560
               break;
561
            case 'confirmation':
562
            case 'confirm':
563
            case 'success':
564
                $class .= 'alert alert-success';
565
               break;
566
            case 'normal':
567
            default:
568
                $class .= 'alert alert-info';
569
        }
570
571
        return self::div($message, array('class'=> $class));
572
    }
573
574
    /**
575
     * Returns an encrypted mailto hyperlink
576
     *
577
     * @param string  e-mail
578
     * @param string  clickable text
579
     * @param string  optional, class from stylesheet
580
     * @return string encrypted mailto hyperlink
581
     */
582
    public static function encrypted_mailto_link($email, $clickable_text = null, $style_class = '')
583
    {
584
        if (is_null($clickable_text)) {
585
            $clickable_text = $email;
586
        }
587
        // "mailto:" already present?
588
        if (substr($email, 0, 7) != 'mailto:') {
589
            $email = 'mailto:'.$email;
590
        }
591
        // Class (stylesheet) defined?
592
        if ($style_class != '') {
593
            $style_class = ' class="'.$style_class.'"';
594
        }
595
        // Encrypt email
596
        $hmail = '';
597 View Code Duplication
        for ($i = 0; $i < strlen($email); $i ++) {
598
            $hmail .= '&#'.ord($email {
599
            $i }).';';
600
        }
601
        $hclickable_text = null;
602
        // Encrypt clickable text if @ is present
603
        if (strpos($clickable_text, '@')) {
604
            for ($i = 0; $i < strlen($clickable_text); $i ++) {
605
                $hclickable_text .= '&#'.ord($clickable_text {
606
                $i }).';';
607
            }
608
        } else {
609
            $hclickable_text = @htmlspecialchars($clickable_text, ENT_QUOTES, api_get_system_encoding());
610
        }
611
        // Return encrypted mailto hyperlink
612
        return '<a href="'.$hmail.'"'.$style_class.' class="clickable_email_link">'.$hclickable_text.'</a>';
613
    }
614
615
    /**
616
     * Returns an mailto icon hyperlink
617
     *
618
     * @param string  e-mail
619
     * @param string  icon source file from the icon lib
620
     * @param integer  icon size from icon lib
621
     * @param string  optional, class from stylesheet
622
     * @return string encrypted mailto hyperlink
623
     */
624
    public static function icon_mailto_link($email, $icon_file = "mail.png", $icon_size = 22, $style_class = '')
625
    {
626
        // "mailto:" already present?
627
        if (substr($email, 0, 7) != 'mailto:') {
628
            $email = 'mailto:'.$email;
629
        }
630
        // Class (stylesheet) defined?
631
        if ($style_class != '') {
632
            $style_class = ' class="'.$style_class.'"';
633
        }
634
        // Encrypt email
635
        $hmail = '';
636 View Code Duplication
        for ($i = 0; $i < strlen($email); $i ++) {
637
            $hmail .= '&#'.ord($email {
638
            $i }).';';
639
        }
640
        // icon html code
641
        $icon_html_source = self::return_icon($icon_file, $hmail, '', $icon_size);
642
        // Return encrypted mailto hyperlink
643
644
        return '<a href="'.$hmail.'"'.$style_class.' class="clickable_email_link">'.$icon_html_source.'</a>';
645
    }
646
647
    /**
648
     * Prints an <option>-list with all letters (A-Z).
649
     * @param char $selected_letter The letter that should be selected
650
     * @todo This is English language specific implementation.
651
     * It should be adapted for the other languages.
652
     */
653 View Code Duplication
    public static function get_alphabet_options($selected_letter = '')
654
    {
655
        $result = '';
656
        for ($i = 65; $i <= 90; $i ++) {
657
            $letter = chr($i);
658
            $result .= '<option value="'.$letter.'"';
659
            if ($selected_letter == $letter) {
660
                $result .= ' selected="selected"';
661
            }
662
            $result .= '>'.$letter.'</option>';
663
        }
664
        return $result;
665
    }
666
667
    /**
668
     * Get the options withing a select box within the given values
669
     * @param int   Min value
670
     * @param int   Max value
671
     * @param int   Default value
672
     * @return string HTML select options
673
     */
674 View Code Duplication
    public static function get_numeric_options($min, $max, $selected_num = 0)
675
    {
676
        $result = '';
677
        for ($i = $min; $i <= $max; $i ++) {
678
            $result .= '<option value="'.$i.'"';
679
            if (is_int($selected_num))
680
                if ($selected_num == $i) {
681
                    $result .= ' selected="selected"';
682
                }
683
            $result .= '>'.$i.'</option>';
684
        }
685
        return $result;
686
    }
687
688
    /**
689
     * This public function displays an icon
690
     * @param string   The filename of the file (in the main/img/ folder
691
     * @param string   The alt text (probably a language variable)
692
     * @param array    additional attributes (for instance height, width, onclick, ...)
693
     * @param integer  The wanted width of the icon (to be looked for in the corresponding img/icons/ folder)
694
     * @return void
695
    */
696
    public static function display_icon(
697
        $image,
698
        $alt_text = '',
699
        $additional_attributes = array(),
700
        $size = ICON_SIZE_SMALL
701
    ) {
702
        echo self::return_icon($image, $alt_text, $additional_attributes, $size);
703
    }
704
705
    /**
706
     * Gets the path of an icon
707
     *
708
     * @param string $icon
709
     * @param int $size
710
     *
711
     * @return string
712
     */
713
    public static function returnIconPath($icon, $size = ICON_SIZE_SMALL)
714
    {
715
        return Display::return_icon($icon, null, null, $size, null, true, false);
716
    }
717
718
    /**
719
     * This public function returns the htmlcode for an icon
720
     *
721
     * @param string   The filename of the file (in the main/img/ folder
722
     * @param string   The alt text (probably a language variable)
723
     * @param array    Additional attributes (for instance height, width, onclick, ...)
724
     * @param integer  The wanted width of the icon (to be looked for in the corresponding img/icons/ folder)
725
     * @return string  An HTML string of the right <img> tag
726
     *
727
     * @author Patrick Cool <[email protected]>, Ghent University 2006
728
     * @author Julio Montoya 2010 Function improved, adding image constants
729
     * @author Yannick Warnier 2011 Added size handler
730
     * @version Feb 2011
731
    */
732
    public static function return_icon(
733
        $image,
734
        $alt_text = '',
735
        $additional_attributes = array(),
736
        $size = ICON_SIZE_SMALL,
737
        $show_text = true,
738
        $return_only_path = false,
739
        $loadThemeIcon = true
740
    ) {
741
        $image = trim($image);
742
        $size_extra = '';
743
        if (isset($size)) {
744
            $size_extra = $size . '/';
745
        }
746
747
        $icon = 'img/icons/'.$size_extra.$image;
748
        $icon = Container::getAsset()->getUrl($icon);
749
750
        if ($return_only_path) {
751
            return $icon;
752
        }
753
754
        $img = self::img($icon, $alt_text, $additional_attributes);
755
        if (SHOW_TEXT_NEAR_ICONS == true && !empty($alt_text)) {
756
            if ($show_text) {
757
                $img = "$img $alt_text";
758
            }
759
        }
760
761
        return $img;
762
    }
763
764
    /**
765
     * Returns the htmlcode for an image
766
     *
767
     * @param string $image_path the filename of the file (in the main/img/ folder
768
     * @param string $alt_text the alt text (probably a language variable)
769
     * @param array  $additional_attributes (for instance height, width, onclick, ...)
770
     * @param boolean $filterPath Optional. Whether filter the image path. Default is true
771
     * @author Julio Montoya 2010
772
     */
773
    public static function img($image_path, $alt_text = '', $additional_attributes = array(), $filterPath = true)
774
    {
775
        // Sanitizing the parameter $image_path
776
        if ($filterPath) {
777
            $image_path = Security::filter_img_path($image_path);
778
        }
779
780
        // alt text = the image name if there is none provided (for XHTML compliance)
781
        if ($alt_text == '') {
782
            $alt_text = basename($image_path);
783
        }
784
785
        $additional_attributes['src'] = $image_path;
786
787
        if (empty($additional_attributes['alt'])) {
788
            $additional_attributes['alt'] = $alt_text;
789
        }
790
        if (empty($additional_attributes['title'])) {
791
            $additional_attributes['title'] = $alt_text;
792
        }
793
794
        return self::tag('img', '', $additional_attributes);
795
    }
796
797
    /**
798
     * Returns the htmlcode for a tag (h3, h1, div, a, button), etc
799
     *
800
     * @param string $tag the tag name
801
     * @param string $content the tag's content
802
     * @param array $additional_attributes (for instance height, width, onclick, ...)
803
     * @author Julio Montoya 2010
804
     */
805
    public static function tag($tag, $content, $additional_attributes = array())
806
    {
807
        $attribute_list = '';
808
        // Managing the additional attributes
809
        if (!empty($additional_attributes) && is_array($additional_attributes)) {
810
            $attribute_list = '';
811
            foreach ($additional_attributes as $key => & $value) {
812
                $attribute_list .= $key.'="'.$value.'" ';
813
            }
814
        }
815
        //some tags don't have this </XXX>
816
        if (in_array($tag, array('img','input','br'))) {
817
            $return_value = '<'.$tag.' '.$attribute_list.' />';
818
        } else {
819
            $return_value = '<'.$tag.' '.$attribute_list.' >'.$content.'</'.$tag.'>';
820
        }
821
        return $return_value;
822
    }
823
824
    /**
825
     * Creates a URL anchor
826
     * @param string $name
827
     * @param string $url
828
     * @param array $attributes
829
     *
830
     * @return string
831
     */
832
    public static function url($name, $url, $attributes = array())
833
    {
834
        if (!empty($url)) {
835
            $url = preg_replace('#&amp;#', '&', $url);
836
            $url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
837
            $attributes['href'] = $url;
838
        }
839
        return self::tag('a', $name, $attributes);
840
    }
841
842
    /**
843
     * Creates a div tag
844
     *
845
     * @param string $content
846
     * @param array $attributes
847
     * @return string
848
     */
849
    public static function div($content, $attributes = array())
850
    {
851
        return self::tag('div', $content, $attributes);
852
    }
853
854
    /**
855
     * Creates a span tag
856
     */
857
    public static function span($content, $attributes = array())
858
    {
859
        return self::tag('span', $content, $attributes);
860
    }
861
862
    /**
863
     * Displays an HTML input tag
864
     *
865
     */
866
    public static function input($type, $name, $value, $attributes = array())
867
    {
868
         if (isset($type)) {
869
             $attributes['type']= $type;
870
         }
871
         if (isset($name)) {
872
             $attributes['name']= $name;
873
         }
874
         if (isset($value)) {
875
             $attributes['value']= $value;
876
        }
877
        return self::tag('input', '', $attributes);
878
    }
879
880
    /**
881
     * @param $name
882
     * @param $value
883
     * @param array $attributes
884
     * @return string
885
     */
886
    public static function button($name, $value, $attributes = array())
887
    {
888
    	if (!empty($name)) {
889
            $attributes['name'] = $name;
890
    	}
891
    	return self::tag('button', $value, $attributes);
892
    }
893
894
    /**
895
     * Displays an HTML select tag
896
     *
897
     */
898
    public static function select(
899
        $name,
900
        $values,
901
        $default = -1,
902
        $extra_attributes = array(),
903
        $show_blank_item = true,
904
        $blank_item_text = null
905
    ) {
906
        $html = '';
907
        $extra = '';
908
        $default_id = 'id="' . $name . '" ';
909
        foreach ($extra_attributes as $key => $parameter) {
910
            if ($key == 'id') {
911
                $default_id = '';
912
            }
913
            $extra .= $key . '="' . $parameter . '" ';
914
        }
915
        $html .= '<select name="' . $name . '" ' . $default_id . ' ' . $extra . '>';
916
917
        if ($show_blank_item) {
918
            if (empty($blank_item_text)) {
919
                $blank_item_text = get_lang('Select');
920
            } else {
921
                $blank_item_text = Security::remove_XSS($blank_item_text);
922
            }
923
            $html .= self::tag('option', '-- ' . $blank_item_text . ' --', array('value' => '-1'));
924
        }
925
        if ($values) {
926
            foreach ($values as $key => $value) {
927
                if (is_array($value) && isset($value['name'])) {
928
                    $value = $value['name'];
929
                }
930
                $html .= '<option value="' . $key . '"';
931
932
                if (is_array($default)) {
933
                    foreach ($default as $item) {
934
                        if ($item == $key) {
935
                            $html .= ' selected="selected"';
936
                            break;
937
                        }
938
                    }
939
                } else {
940
                    if ($default == $key) {
941
                        $html .= ' selected="selected"';
942
                    }
943
                }
944
945
                $html .= '>' . $value . '</option>';
946
            }
947
        }
948
        $html .= '</select>';
949
        return $html;
950
    }
951
952
    /**
953
     * Creates a tab menu
954
     * Requirements: declare the jquery, jquery-ui libraries + the jquery-ui.css
955
     * in the $htmlHeadXtra variable before the display_header
956
     * Add this script
957
     * @example
958
             * <script>
959
                    $(function() {
960
                        $( "#tabs" ).tabs();
961
                    });
962
                </script>
963
     * @param   array   $headers list of the tab titles
964
     * @param   array   $items
965
     * @param   string  $id id of the container of the tab in the example "tabs"
966
     * @param   array   $attributes for the ul
967
     * @param array $ul_attributes
968
     *
969
     * @return string
970
     */
971
    public static function tabs($headers, $items, $id = 'tabs', $attributes = array(), $ul_attributes = array())
972
    {
973
        if (empty($headers) || count($headers) == 0 ) {
974
            return '';
975
        }
976
977
        $lis = '';
978
        $i = 1;
979
        foreach ($headers as $item) {
980
            $active = '';
981
            if ($i == 1) {
982
                $active = ' active';
983
            }
984
            $item = self::tag('a', $item, array('href'=>'#'.$id.'-'.$i, 'role'=> 'tab', 'data-toggle' => 'tab', 'id' => $id . $i));
985
            $ul_attributes['role'] = 'presentation';
986
            $ul_attributes['class'] = $active;
987
            $lis .= self::tag('li', $item, $ul_attributes);
988
            $i++;
989
        }
990
        $ul = self::tag('ul', $lis, ['class' => 'nav nav-tabs', 'role'=> 'tablist', 'id' => 'ul_'.$id]);
991
992
        $i = 1;
993
        $divs = '';
994
        foreach ($items as $content) {
995
            $active = '';
996
            if ($i == 1) {
997
                $active = ' active';
998
            }
999
            $divs .= self::tag(
1000
                'div',
1001
                $content,
1002
                array('id' => $id.'-'.$i, 'class' => 'tab-pane '.$active, 'role' => 'tabpanel')
1003
            );
1004
            $i++;
1005
        }
1006
1007
        $attributes['id'] = $id;
1008
        $attributes['role'] = 'tabpanel';
1009
        $attributes['class'] = 'tab-wrapper';
1010
1011
        $main_div = self::tag('div', $ul.self::tag('div', $divs, ['class' => 'tab-content']), $attributes);
1012
1013
        return $main_div ;
1014
    }
1015
1016
    /**
1017
     * @param $headers
1018
     * @param null $selected
1019
     *
1020
     * @return string
1021
     */
1022
    public static function tabsOnlyLink($headers, $selected = null)
1023
    {
1024
         $id = uniqid();
1025
         $i = 1;
1026
         $lis = null;
1027
         foreach ($headers as $item) {
1028
            $class = null;
1029
            if ($i == $selected) {
1030
                $class = 'active';
1031
            }
1032
             $item = self::tag(
1033
                 'a',
1034
                 $item['content'],
1035
                 array('id' => $id.'-'.$i, 'href' => $item['url'])
1036
             );
1037
             $lis .= self::tag('li', $item, array('class' => $class));
1038
            $i++;
1039
        }
1040
        return self::tag('ul', $lis, array('class' => 'nav nav-tabs tabs-margin'));
1041
    }
1042
1043
    /**
1044
     * In order to display a grid using jqgrid you have to:
1045
     * @example
1046
     * After your Display::display_header function you have to add the nex javascript code:     *
1047
     * <script>
1048
     *   echo Display::grid_js('my_grid_name', $url,$columns, $column_model, $extra_params,array());
1049
     *   // for more information of this function check the grid_js() function
1050
     * </script>
1051
     * //Then you have to call the grid_html
1052
     * echo Display::grid_html('my_grid_name');
1053
     * As you can see both function use the same "my_grid_name" this is very important otherwise nothing will work
1054
     *
1055
     * @param   string  the div id, this value must be the same with the first parameter of Display::grid_js()
1056
     * @return  string  html
1057
     *
1058
     */
1059
    public static function grid_html($div_id)
1060
    {
1061
        $table = self::tag('table','', array('id' => $div_id));
1062
        $table .= self::tag('div','', array('id' => $div_id.'_pager'));
1063
        return $table;
1064
    }
1065
1066
    /**
1067
     * @param string $label
1068
     * @param string $form_item
1069
     * @return string
1070
     */
1071
    public static function form_row($label, $form_item)
1072
    {
1073
        $label = self::span($label, array('class' =>'control-label'));
1074
        $form_item = self::div($form_item, array('class' =>'controls'));
1075
        return self::div($label.$form_item, array('class'=>'control-group'));
1076
    }
1077
1078
    /**
1079
     * This is a wrapper to use the jqgrid in Chamilo.
1080
     * For the other jqgrid options visit http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options
1081
     * This function need to be in the ready jquery function
1082
     * example --> $(function() { <?php echo Display::grid_js('grid' ...); ?> }
1083
     * In order to work this function needs the Display::grid_html function with the same div id
1084
     *
1085
     * @param   string  $div_id div id
1086
     * @param   string  $url url where the jqgrid will ask for data (if datatype = json)
1087
     * @param   array   $column_names Visible columns (you should use get_lang). An array in which we place the names of the columns.
1088
     * 					This is the text that appears in the head of the grid (Header layer).
1089
     * 					Example: colname   {name:'date',     index:'date',   width:120, align:'right'},
1090
     * @param   array   $column_model the column model :  Array which describes the parameters of the columns.This is the most important part of the grid.
1091
     * 					For a full description of all valid values see colModel API. See the url above.
1092
     * @param   array   $extra_params extra parameters
1093
     * @param   array   $data data that will be loaded
1094
     * @param	string	$formatter A string that will be appended to the JSON returned
1095
     * @param	bool	$fixed_width not implemented yet
1096
     * @return  string  the js code
1097
     *
1098
     */
1099
    public static function grid_js(
1100
        $div_id,
1101
        $url,
1102
        $column_names,
1103
        $column_model,
1104
        $extra_params,
1105
        $data = array(),
1106
        $formatter = '',
1107
        $fixed_width = false
1108
    ) {
1109
        $obj = new stdClass();
1110
        $obj->first = 'first';
1111
1112
        if (!empty($url)) {
1113
            $obj->url = $url;
1114
        }
1115
1116
        //This line should only be used/modified in case of having characters
1117
        // encoding problems - see #6159
1118
        //$column_names = array_map("utf8_encode", $column_names);
1119
1120
        $obj->colNames      = $column_names;
1121
        $obj->colModel      = $column_model;
1122
        $obj->pager         = '#'.$div_id.'_pager';
1123
        $obj->datatype  = 'json';
1124
        $obj->viewrecords = 'true';
1125
1126
        $all_value = 10000000;
1127
1128
        // Default row quantity
1129
        if (!isset($extra_params['rowList'])) {
1130
            $extra_params['rowList'] = array(20, 50, 100, 500, 1000, $all_value);
1131
        }
1132
1133
        $json = '';
1134
        if (!empty($extra_params['datatype'])) {
1135
            $obj->datatype = $extra_params['datatype'];
1136
        }
1137
1138
        // Row even odd style.
1139
        $obj->altRows = true;
1140
        if (!empty($extra_params['altRows'])) {
1141
            $obj->altRows = $extra_params['altRows'];
1142
        }
1143
1144
        if (!empty($extra_params['sortname'])) {
1145
            $obj->sortname = $extra_params['sortname'];
1146
        }
1147
1148
        if (!empty($extra_params['sortorder'])) {
1149
            $obj->sortorder = $extra_params['sortorder'];
1150
        }
1151
1152
        if (!empty($extra_params['rowList'])) {
1153
            $obj->rowList = $extra_params['rowList'];
1154
        }
1155
        //Sets how many records we want to view in the grid
1156
        $obj->rowNum = 20;
1157
        if (!empty($extra_params['rowNum'])) {
1158
            $obj->rowNum = $extra_params['rowNum'];
1159
        }
1160
1161
        if (!empty($extra_params['viewrecords'])) {
1162
            $obj->viewrecords = $extra_params['viewrecords'];
1163
        }
1164
1165
        $beforeSelectRow = null;
1166
        if (isset($extra_params['beforeSelectRow'])) {
1167
            $beforeSelectRow = "beforeSelectRow: ".$extra_params['beforeSelectRow'].", ";
1168
            unset($extra_params['beforeSelectRow']);
1169
        }
1170
1171
        // Adding extra params
1172
        if (!empty($extra_params)) {
1173
            foreach ($extra_params as $key => $element) {
1174
                // the groupHeaders key gets a special treatment
1175
                if ($key != 'groupHeaders') {
1176
                    $obj->$key = $element;
1177
                }
1178
            }
1179
        }
1180
1181
        // Adding static data.
1182
        if (!empty($data)) {
1183
            $data_var = $div_id.'_data';
1184
            $json.=' var '.$data_var.' = '.json_encode($data).';';
1185
            $obj->data = $data_var;
1186
            $obj->datatype = 'local';
1187
            $json.="\n";
1188
        }
1189
1190
        $obj->end = 'end';
1191
1192
        $json_encode = json_encode($obj);
1193
1194
        if (!empty($data)) {
1195
            //Converts the "data":"js_variable" to "data":js_variable,
1196
            // otherwise it will not work
1197
            $json_encode = str_replace('"data":"'.$data_var.'"', '"data":'.$data_var.'', $json_encode);
1198
        }
1199
1200
        // Fixing true/false js values that doesn't need the ""
1201
        $json_encode = str_replace(':"true"',':true',$json_encode);
1202
        // wrap_cell is not a valid jqgrid attributes is a hack to wrap a text
1203
        $json_encode = str_replace('"wrap_cell":true', 'cellattr : function(rowId, value, rowObject, colModel, arrData) { return \'class = "jqgrid_whitespace"\'; }', $json_encode);
1204
        $json_encode = str_replace(':"false"',':false',$json_encode);
1205
        $json_encode = str_replace('"formatter":"action_formatter"', 'formatter:action_formatter', $json_encode);
1206
        $json_encode = str_replace(array('{"first":"first",','"end":"end"}'), '', $json_encode);
1207
1208
        // Creating the jqgrid element.
1209
        $json .= '$("#'.$div_id.'").jqGrid({';
1210
        //$json .= $beforeSelectRow;
1211
1212
        $json .= $json_encode;
1213
1214
        $json .= '});';
1215
1216
        // Grouping headers option
1217
        if (isset($extra_params['groupHeaders'])) {
1218
            $groups = '';
1219
            foreach ($extra_params['groupHeaders'] as $group) {
1220
                //{ "startColumnName" : "courses", "numberOfColumns" : 1, "titleText" : "Order Info" },
1221
                $groups .= '{ "startColumnName" : "' . $group['startColumnName'] . '", "numberOfColumns" : ' . $group['numberOfColumns'] . ', "titleText" : "' . $group['titleText']  . '" },';
1222
1223
            }
1224
            $json .= '$("#'.$div_id.'").jqGrid("setGroupHeaders", {
1225
                "useColSpanStyle" : false,
1226
                "groupHeaders"    : [
1227
                    ' . $groups . '
1228
                ]
1229
            });';
1230
        }
1231
1232
        $all_text = addslashes(get_lang('All'));
1233
        $json .= '$("'.$obj->pager.' option[value='.$all_value.']").text("'.$all_text.'");';
1234
        $json.= "\n";
1235
        // Adding edit/delete icons.
1236
        $json.= $formatter;
1237
1238
        return $json;
1239
    }
1240
1241
    /**
1242
     * @param array $headers
1243
     * @param array $rows
1244
     * @param array $attributes
1245
     * @return string
1246
     */
1247
    public static function table($headers, $rows, $attributes = array())
1248
    {
1249
    	if (empty($attributes)) {
1250
    		$attributes['class'] = 'data_table';
1251
        }
1252
        $table = new HTML_Table($attributes);
1253
        $row = 0;
1254
        $column = 0;
1255
1256
        // Course headers
1257
        if (!empty($headers)) {
1258
	        foreach ($headers as $item) {
1259
	            $table->setHeaderContents($row, $column, $item);
1260
	            $column++;
1261
	        }
1262
	        $row = 1;
1263
	        $column = 0;
1264
        }
1265
1266
        if (!empty($rows)) {
1267
	        foreach($rows as $content) {
1268
	            $table->setCellContents($row, $column, $content);
1269
                $row++;
1270
            }
1271
        }
1272
        return $table->toHtml();
1273
    }
1274
1275
    /**
1276
     * Returns the "what's new" icon notifications
1277
     *
1278
     * The general logic of this function is to track the last time the user
1279
     * entered the course and compare to what has changed inside this course
1280
     * since then, based on the item_property table inside this course. Note that,
1281
     * if the user never entered the course before, he will not see notification
1282
     * icons. This function takes session ID into account (if any) and only shows
1283
     * the corresponding notifications.
1284
     * @param array $course_info Course information array, containing at least elements 'db' and 'k'
1285
     * @param bool $loadAjax
1286
     * @return string   The HTML link to be shown next to the course
1287
     */
1288
    public static function show_notification($course_info, $loadAjax = true)
1289
    {
1290
        if (empty($course_info)) {
1291
            return '';
1292
        }
1293
1294
        $t_track_e_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
1295
        $course_tool_table = Database::get_course_table(TABLE_TOOL_LIST);
1296
        $tool_edit_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1297
        $course_code = Database::escape_string($course_info['code']);
1298
1299
        $user_id = api_get_user_id();
1300
        $course_id = (int) $course_info['real_id'];
1301
        $sessionId = (int) $course_info['id_session'];
1302
        $status = (int) $course_info['status'];
1303
1304
        $loadNotificationsByAjax = api_get_configuration_value('user_portal_load_notification_by_ajax');
1305
1306
        if ($loadNotificationsByAjax) {
1307
            if ($loadAjax) {
1308
                $id = 'notification_'.$course_id.'_'.$sessionId.'_'.$status;
1309
                Session::write($id, true);
1310
1311
                return '<span id ="'.$id.'" class="course_notification"></span>';
1312
            }
1313
        }
1314
1315
        // Get the user's last access dates to all tools of this course
1316
        $sql = "SELECT *
1317
                FROM $t_track_e_access
1318
                WHERE
1319
                    c_id = $course_id AND
1320
                    access_user_id = '$user_id' AND
1321
                    access_session_id ='".$sessionId."'";
1322
        $resLastTrackInCourse = Database::query($sql);
1323
1324
        $oldestTrackDate = $oldestTrackDateOrig = '3000-01-01 00:00:00';
1325
        while ($lastTrackInCourse = Database::fetch_array($resLastTrackInCourse)) {
1326
            $lastTrackInCourseDate[$lastTrackInCourse['access_tool']] = $lastTrackInCourse['access_date'];
1327
            if ($oldestTrackDate > $lastTrackInCourse['access_date']) {
1328
                $oldestTrackDate = $lastTrackInCourse['access_date'];
1329
            }
1330
        }
1331
1332
        if ($oldestTrackDate == $oldestTrackDateOrig) {
1333
            //if there was no connexion to the course ever, then take the
1334
            // course creation date as a reference
1335
            $oldestTrackDate = $course_info['creation_date'];
1336
        }
1337
1338
        $sessionCondition = api_get_session_condition(
1339
            $sessionId,
1340
            true,
1341
            false,
1342
            'tet.session_id'
1343
        );
1344
1345
        // Get the last edits of all tools of this course.
1346
        $sql = "SELECT
1347
                    tet.*,
1348
                    tet.lastedit_date last_date,
1349
                    tet.tool tool,
1350
                    tet.ref ref,
1351
                    tet.lastedit_type type,
1352
                    tet.to_group_id group_id,
1353
                    ctt.image image,
1354
                    ctt.link link
1355
                FROM $tool_edit_table tet
1356
                INNER JOIN $course_tool_table ctt
1357
                ON tet.c_id = ctt.c_id
1358
                WHERE
1359
                    tet.c_id = $course_id AND
1360
                    tet.lastedit_date > '$oldestTrackDate' ".
1361
                    // Special hack for work tool, which is called student_publication in c_tool and work in c_item_property :-/ BT#7104
1362
                    " AND (ctt.name = tet.tool OR (ctt.name = 'student_publication' AND tet.tool = 'work'))
1363
                    AND ctt.visibility = '1'
1364
                    AND tet.lastedit_user_id != $user_id $sessionCondition
1365
                 ORDER BY tet.lastedit_date";
1366
1367
        $res = Database::query($sql);
1368
        // Get the group_id's with user membership.
1369
        $group_ids = GroupManager::get_group_ids($course_info['real_id'], $user_id);
1370
        $group_ids[] = 0; //add group 'everyone'
1371
        $notifications = array();
1372
        // Filter all last edits of all tools of the course
1373
        while ($res && ($item_property = Database::fetch_array($res, 'ASSOC'))) {
1374
            // First thing to check is if the user never entered the tool
1375
            // or if his last visit was earlier than the last modification.
1376
            if ((!isset($lastTrackInCourseDate[$item_property['tool']])
1377
                 || $lastTrackInCourseDate[$item_property['tool']] < $item_property['lastedit_date'])
1378
                // Drop the tool elements that are part of a group that the
1379
                // user is not part of.
1380
                && ((in_array($item_property['to_group_id'], $group_ids)
1381
                // Drop the dropbox, notebook and chat tools (we don't care)
1382
                && (
1383
                        //$item_property['tool'] != TOOL_DROPBOX &&
1384
                        $item_property['tool'] != TOOL_NOTEBOOK &&
1385
                        $item_property['tool'] != TOOL_CHAT)
1386
                   )
1387
                )
1388
                // Take only what's visible or "invisible but where the user is a teacher" or where the visibility is unset.
1389
                && ($item_property['visibility'] == '1'
1390
                    || ($status == '1' && $item_property['visibility'] == '0')
1391
                    || !isset($item_property['visibility']))
1392
            ) {
1393
                // Also drop announcements and events that are not for the user or his group.
1394
                if ((
1395
                        $item_property['tool'] == TOOL_ANNOUNCEMENT ||
1396
                        $item_property['tool'] == TOOL_CALENDAR_EVENT
1397
                    ) &&
1398
                    (
1399
                        ($item_property['to_user_id'] != $user_id) &&
1400
                        (!isset($item_property['to_group_id']) || !in_array($item_property['to_group_id'], $group_ids)))
1401
                ) {
1402
                   continue;
1403
                }
1404
1405
                // If it's a survey, make sure the user's invited. Otherwise drop it.
1406
                if ($item_property['tool'] == TOOL_SURVEY) {
1407
                    $survey_info = SurveyManager::get_survey($item_property['ref'], 0, $course_code);
1408
                    if (!empty($survey_info)) {
1409
                        $invited_users = SurveyUtil::get_invited_users(
1410
                            $survey_info['code'],
1411
                            $course_code
1412
                        );
1413
                        if (!in_array($user_id, $invited_users['course_users'])) {
1414
                            continue;
1415
                        }
1416
                    }
1417
                }
1418
1419
                // If it's a learning path, ensure it is currently visible to the user
1420
                if ($item_property['tool'] == TOOL_LEARNPATH) {
1421
                    if (!learnpath::is_lp_visible_for_student($item_property['ref'], $user_id, $course_code)) {
1422
                        continue;
1423
                    }
1424
                }
1425
1426
                if ($item_property['tool'] == TOOL_DROPBOX) {
1427
                    $item_property['link'] = 'dropbox/dropbox_download.php?id='.$item_property['ref'];
1428
                }
1429
1430
                if ($item_property['tool'] == 'work' &&
1431
                    $item_property['type'] == 'DirectoryCreated'
1432
                ) {
1433
                    $item_property['lastedit_type'] = 'WorkAdded';
1434
                }
1435
                $notifications[$item_property['tool']] = $item_property;
1436
            }
1437
        }
1438
1439
        // Show all tool icons where there is something new.
1440
        $return = '&nbsp;';
1441
        foreach($notifications as $notification) {
1442
            $lastDate = date('d/m/Y H:i', convert_sql_date($notification['lastedit_date']));
1443
            $type = $notification['lastedit_type'];
1444
            $label = get_lang('TitleNotification').": ".get_lang($type)." ($lastDate)";
1445
1446
            if (strpos($notification['link'], '?') === false) {
1447
                $notification['link'] = $notification['link'].'?notification=1';
1448
            } else {
1449
                $notification['link'] = $notification['link'].'&notification=1';
1450
            }
1451
            $imagen = substr($notification['image'], 0, -4).'.png';
1452
            $return .= Display::url(
1453
                Display::return_icon($imagen, $label),
1454
                api_get_path(WEB_CODE_PATH).
1455
                $notification['link'].'&cidReq='.$course_code.
1456
                '&ref='.$notification['ref'].
1457
                '&gidReq='.$notification['to_group_id'].
1458
                '&id_session='.$sessionId
1459
            ).'&nbsp;';
1460
        }
1461
1462
        return $return;
1463
    }
1464
1465
    /**
1466
     * Get the session box details as an array
1467
     * @param int       Session ID
1468
     * @return array    Empty array or session array
1469
     * ['title'=>'...','category'=>'','dates'=>'...','coach'=>'...','active'=>true/false,'session_category_id'=>int]
1470
     */
1471
    public static function get_session_title_box($session_id)
1472
    {
1473
        global $nosession;
1474
1475
        if (!$nosession) {
1476
            global $now, $date_start, $date_end;
1477
        }
1478
        $output = array();
1479
        $active = false;
1480
        if (!$nosession) {
1481
            $main_user_table = Database :: get_main_table(TABLE_MAIN_USER);
1482
            $tbl_session = Database :: get_main_table(TABLE_MAIN_SESSION);
1483
            // Request for the name of the general coach
1484
            $sql ='SELECT tu.lastname, tu.firstname, ts.*
1485
                    FROM '.$tbl_session.' ts
1486
                    LEFT JOIN '.$main_user_table .' tu
1487
                    ON ts.id_coach = tu.user_id
1488
                    WHERE ts.id = '.intval($session_id);
1489
            $rs = Database::query($sql);
1490
            $session_info = Database::store_result($rs, 'ASSOC');
1491
            $session_info = $session_info[0];
1492
1493
            $session = array();
1494
            $session['category_id'] = $session_info['session_category_id'];
1495
            $session['title'] = $session_info['name'];
1496
            $session['id_coach'] = $session_info['id_coach'];
1497
            $session['coach'] = '';
1498
            $session['dates'] =  '';
1499
1500
            if (($session_info['access_end_date'] == '0000-00-00 00:00:00' && $session_info['access_start_date'] == '0000-00-00 00:00:00') ||
1501
                ($session_info['access_end_date'] == '0000-00-00 00:00:00' && $session_info['access_start_date'] == '0000-00-00 00:00:00') ||
1502
                (empty($session_info['access_end_date']) && empty($session_info['access_start_date']))
1503
            ) {
1504 View Code Duplication
                if (api_get_setting('show_session_coach') === 'true') {
1505
                    $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($session_info['firstname'], $session_info['lastname']);
1506
                }
1507
1508
                if (isset($session_info['duration']) && !empty($session_info['duration'])) {
1509
                    $userDurationData = SessionManager::getUserSession(
1510
                        api_get_user_id(),
1511
                        $session_id
1512
                    );
1513
1514
                    $userDuration = isset($userDurationData['duration']) ? (int) $userDurationData['duration'] : 0;
1515
                    $totalDuration = $session_info['duration'] + $userDuration;
1516
1517
                    $daysLeft = SessionManager::getDayLeftInSession(
1518
                        $session_id,
1519
                        api_get_user_id(),
1520
                        $totalDuration
1521
                    );
1522
                    $session['duration'] = sprintf(get_lang('SessionDurationXDaysLeft'), $daysLeft);
1523
                }
1524
                $active = true;
1525
            } else {
1526
                /*$start = $stop = false;
1527
                $start_buffer = $stop_buffer = '';
1528
                if ($session_info['access_start_date'] === '0000-00-00 00:00:00' || empty($session_info['access_start_date'])) {
1529
                    $session_info['access_start_date'] = '';
1530
                } else {
1531
                    $start = true;
1532
                    $start_buffer = $session_info['access_start_date'];
1533
                    $session_info['access_start_date'] = $session_info['access_start_date'];
1534
                }
1535
                if ($session_info['access_end_date'] === '0000-00-00 00:00:00' || empty($session_info['access_end_date'])) {
1536
                    $session_info['access_end_date'] = '';
1537
                } else {
1538
                    $stop = true;
1539
                    $stop_buffer = $session_info['access_end_date'];
1540
                    $session_info['access_end_date'] = $session_info['access_end_date'];
1541
                }
1542
                if ($start && $stop) {
1543
                    $session['dates'] = sprintf(
1544
                        get_lang('FromDateXToDateY'),
1545
                        api_format_date($start_buffer),
1546
                        api_format_date($stop_buffer)
1547
                    );
1548
                } else {
1549
                    $start_buffer = $stop_buffer = null;
1550
                    if (!empty($session_info['access_start_date'])) {
1551
                        $start_buffer = sprintf(
1552
                            get_lang('FromDateX'),
1553
                            api_format_date(api_get_local_time($session_info['access_start_date']))
1554
                        );
1555
                    }
1556
1557
                    if (!empty($session_info['access_end_date'])) {
1558
                        $stop_buffer = sprintf(
1559
                            get_lang('UntilDateX'),
1560
                            api_format_date(api_get_local_time($session_info['access_end_date']))
1561
                        );
1562
                    }*/
1563
1564
                $dates = SessionManager::parseSessionDates($session_info, true);
1565
1566
                //$session['dates'] = $start_buffer . ' ' . $stop_buffer.'- julio '.$dates['access'];
1567
                $session['dates'] = $dates['access'];
1568
1569
1570
                if (api_get_setting('show_session_coach') === 'true' ) {
1571
                    $session['coach'] = api_get_person_name(
1572
                        $session_info['firstname'],
1573
                        $session_info['lastname']
1574
                    );
1575
                }
1576
                $active = $date_start <= $now && $date_end >= $now;
1577
            }
1578
            $session['active'] = $active;
1579
            $session['session_category_id'] = $session_info['session_category_id'];
1580
            $session['visibility'] = $session_info['visibility'];
1581
            $session['num_users'] = $session_info['nbr_users'];
1582
            $session['num_courses'] = $session_info['nbr_courses'];
1583
            $session['description'] = $session_info['description'];
1584
            $session['show_description'] = $session_info['show_description'];
1585
1586
            $entityManager = Database::getManager();
1587
            $fieldValuesRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraFieldValues');
1588
            $extraFieldValues = $fieldValuesRepo->getVisibleValues(
1589
                ExtraField::SESSION_FIELD_TYPE,
1590
                $session_id
1591
            );
1592
1593
            $session['extra_fields'] = [];
1594
            foreach ($extraFieldValues as $value) {
1595
                $session['extra_fields'][] = [
1596
                    'field' => [
1597
                        'variable' => $value->getField()->getVariable(),
1598
                        'display_text' => $value->getField()->getDisplayText()
1599
                    ],
1600
                    'value' => $value->getValue()
1601
                ];
1602
            }
1603
1604
            $output = $session;
1605
        }
1606
        return $output;
1607
    }
1608
1609
    /**
1610
     * Return the five star HTML
1611
     *
1612
     * @param  string  id of the rating ul element
1613
     * @param  string  url that will be added (for jquery see hot_courses.tpl)
1614
	 * @param	string	point info array see function CourseManager::get_course_ranking()
1615
	 * @param	bool	add a div wrapper
1616
	 * @todo	use     templates
1617
     **/
1618
    public static function return_rating_system($id, $url, $point_info = array(), $add_div_wrapper = true)
1619
    {
1620
		$number_of_users_who_voted = isset($point_info['users_who_voted']) ? $point_info['users_who_voted'] : null;
1621
		$percentage = isset($point_info['point_average']) ? $point_info['point_average'] : 0;
1622
1623
		if (!empty($percentage)) {
1624
            $percentage = $percentage*125/100;
1625
        }
1626
		$accesses =  isset($point_info['accesses']) ? $point_info['accesses'] : 0;
1627
1628
		$star_label = sprintf(get_lang('XStarsOutOf5'), $point_info['point_average_star']);
1629
1630
        $html = '<ul id="'.$id.'" class="star-rating">
1631
					<li class="current-rating" style="width:'.$percentage.'px;"></li>
1632
					<li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=1" title="'.$star_label.'" class="one-star">1</a></li>
1633
					<li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=2" title="'.$star_label.'" class="two-stars">2</a></li>
1634
					<li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=3" title="'.$star_label.'" class="three-stars">3</a></li>
1635
					<li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=4" title="'.$star_label.'" class="four-stars">4</a></li>
1636
					<li><a href="javascript:void(0);" data-link="'.$url.'&amp;star=5" title="'.$star_label.'" class="five-stars">5</a></li>
1637
				</ul>';
1638
1639
		$labels = array();
1640
1641
		$labels[]= $number_of_users_who_voted == 1 ? $number_of_users_who_voted.' '.get_lang('Vote') : $number_of_users_who_voted.' '.get_lang('Votes');
1642
		$labels[]= $accesses == 1 ? $accesses.' '.get_lang('Visit') : $accesses.' '.get_lang('Visits');
1643
		/* if (!empty($number_of_users_who_voted)) {
1644
			$labels[]= get_lang('Average').' '.$point_info['point_average_star'].'/5';
1645
		} */
1646
1647
		$labels[]= $point_info['user_vote']  ? get_lang('YourVote').' ['.$point_info['user_vote'].']' : get_lang('YourVote'). ' [?] ';
1648
1649
		if (!$add_div_wrapper && api_is_anonymous()) {
1650
			$labels[]= Display::tag('span', get_lang('LoginToVote'), array('class' => 'error'));
1651
		}
1652
1653
        $html .= Display::div(implode(' | ', $labels) , array('id' =>  'vote_label_'.$id, 'class' => 'vote_label_info'));
1654
        $html .= ' '.Display::span(' ', array('id' =>  'vote_label2_'.$id));
1655
1656
        if ($add_div_wrapper) {
1657
			$html = Display::div($html, array('id' => 'rating_wrapper_'.$id));
1658
		}
1659
1660
        return $html;
1661
    }
1662
1663
    /**
1664
     * @param string $title
1665
     * @param string $second_title
1666
     * @param string $size
1667
     * @param bool $filter
1668
     * @return string
1669
     */
1670
    public static function page_header($title, $second_title = null, $size = 'h2', $filter = true)
1671
    {
1672
        if ($filter) {
1673
            $title = Security::remove_XSS($title);
1674
        }
1675
1676
        if (!empty($second_title)) {
1677
            if ($filter) {
1678
                $second_title = Security::remove_XSS($second_title);
1679
            }
1680
            $title .= "<small> $second_title<small>";
1681
        }
1682
        return '<div class="page-header"><'.$size.'>'.$title.'</'.$size.'></div>';
1683
    }
1684
1685
    public static function page_header_and_translate($title, $second_title = null)
1686
    {
1687
        $title = get_lang($title);
1688
        return self::page_header($title, $second_title);
1689
    }
1690
1691
     public static function page_subheader_and_translate($title, $second_title = null)
1692
     {
1693
        $title = get_lang($title);
1694
        return self::page_subheader($title, $second_title);
1695
    }
1696
1697
    public static function page_subheader($title, $second_title = null, $size = 'h3')
1698
    {
1699
        if (!empty($second_title)) {
1700
            $second_title = Security::remove_XSS($second_title);
1701
            $title .= "<small> $second_title<small>";
1702
        }
1703
        return '<'.$size.'>'.Security::remove_XSS($title).'</'.$size.'>';
1704
    }
1705
1706
    public static function page_subheader2($title, $second_title = null)
1707
    {
1708
        return self::page_header($title, $second_title, 'h4');
1709
    }
1710
1711
    public static function page_subheader3($title, $second_title = null)
1712
    {
1713
        return self::page_header($title, $second_title, 'h5');
1714
    }
1715
1716
    /**
1717
     * @param array $list
1718
     * @return null|string
1719
     */
1720
    public static function description($list)
1721
    {
1722
        $html = null;
1723
        if (!empty($list)) {
1724
            $html = '<dl class="dl-horizontal">';
1725
            foreach ($list as $item) {
1726
                $html .= '<dt>' . $item['title'] . '</dt>';
1727
                $html .= '<dd>' . $item['content'] . '</dd>';
1728
            }
1729
            $html .= '</dl>';
1730
        }
1731
        return $html;
1732
    }
1733
1734
    /**
1735
     * @param $percentage
1736
     * @param bool $show_percentage
1737
     * @param null $extra_info
1738
     * @return string
1739
     */
1740
    public static function bar_progress($percentage, $show_percentage = true, $extra_info = null)
1741
    {
1742
        $percentage = intval($percentage);
1743
        $div = '<div class="progress">
1744
                <div
1745
                    class="progress-bar progress-bar-striped"
1746
                    role="progressbar"
1747
                    aria-valuenow="'.$percentage.'"
1748
                    aria-valuemin="0"
1749
                    aria-valuemax="100"
1750
                    style="width: '.$percentage.'%;"
1751
                >';
1752
        if ($show_percentage) {
1753
            $div .= $percentage.'%';
1754
        } else {
1755
            if (!empty($extra_info)) {
1756
                $div .= $extra_info;
1757
            }
1758
        }
1759
        $div .= '</div>';
1760
1761
        return $div;
1762
    }
1763
1764
    /**
1765
     * @param string $count
1766
     * @param string $type
1767
     * @return null|string
1768
     */
1769
    public static function badge($count, $type ="warning")
1770
    {
1771
        $class = '';
1772
1773
        switch ($type) {
1774
            case 'success':
1775
                $class = 'badge-success';
1776
                break;
1777
            case 'warning':
1778
                $class = 'badge-warning';
1779
                break;
1780
            case 'important':
1781
                $class = 'badge-important';
1782
                break;
1783
            case 'info':
1784
                $class = 'badge-info';
1785
                break;
1786
            case 'inverse':
1787
                $class = 'badge-inverse';
1788
                break;
1789
        }
1790
1791
        if (!empty($count)) {
1792
            return ' <span class="badge '.$class.'">'.$count.'</span>';
1793
        }
1794
        return null;
1795
    }
1796
1797
    /**
1798
     * @param array $badge_list
1799
     * @return string
1800
     */
1801
    public static function badge_group($badge_list)
1802
    {
1803
        $html = '<div class="badge-group">';
1804
        foreach ($badge_list as $badge) {
1805
            $html .= $badge;
1806
        }
1807
        $html .= '</div>';
1808
        return $html;
1809
    }
1810
1811
    /**
1812
     * @param string $content
1813
     * @param string $type
1814
     * @return string
1815
     */
1816
    public static function label($content, $type = 'default')
1817
    {
1818
        switch ($type) {
1819
            case 'success':
1820
                $class = 'label-success';
1821
                break;
1822
            case 'warning':
1823
                $class = 'label-warning';
1824
                break;
1825
            case 'important':
1826
                //no break
1827
            case 'danger':
1828
                $class = 'label-danger';
1829
                break;
1830
            case 'info':
1831
                $class = 'label-info';
1832
                break;
1833
            case 'primary':
1834
                $class = 'label-primary';
1835
                break;
1836
            default:
1837
                $class = 'label-default';
1838
                break;
1839
        }
1840
1841
        $html = '';
1842
        if (!empty($content)) {
1843
            $html = '<span class="label '.$class.'">';
1844
            $html .= $content;
1845
            $html .='</span>';
1846
        }
1847
1848
        return $html;
1849
    }
1850
1851
    /**
1852
     * @param array $items
1853
     * @return null|string
1854
     */
1855
    public static function actions($items, $class = 'new_actions')
1856
    {
1857
        $html = null;
1858
        if (!empty($items)) {
1859
            $html = '<div class="'.$class.'"><ul class="nav nav-pills">';
1860
            foreach ($items as $value) {
1861
                $class = null;
1862
                if (isset($value['active']) && $value['active']) {
1863
                    $class = 'class ="active"';
1864
                }
1865
1866
                if (basename($_SERVER['REQUEST_URI']) == basename($value['url']) ) {
1867
                    $class = 'class ="active"';
1868
                }
1869
                $html .= "<li $class >";
1870
                $attributes = isset($value['url_attributes']) ? $value['url_attributes'] : array();
1871
                $html .= self::url($value['content'], $value['url'], $attributes);
1872
                $html .= '</li>';
1873
            }
1874
            $html .= '</ul></div>';
1875
            $html .= '<br />';
1876
        }
1877
1878
        return $html;
1879
    }
1880
1881
    /**
1882
     * Prints a tooltip
1883
     * @param string $text
1884
     * @param string $tip
1885
     *
1886
     * @return string
1887
     */
1888
    public static function tip($text, $tip)
1889
    {
1890
        if (empty($tip)) {
1891
            return $text;
1892
        }
1893
        return self::span($text, array('class' => 'boot-tooltip', 'title' => strip_tags($tip)));
1894
    }
1895
1896
    /**
1897
     * @param array $items
1898
     * @param string $type
1899
     * @param null $id
1900
     * @return null|string
1901
     */
1902
    public static function generate_accordion($items, $type = 'jquery', $id = null)
1903
    {
1904
        $html = null;
1905
        if (!empty($items)) {
1906
            if (empty($id)) {
1907
                $id = api_get_unique_id();
1908
            }
1909
            if ($type == 'jquery') {
1910
                $html = '<div class="accordion_jquery" id="'.$id.'">'; //using jquery
1911
            } else {
1912
                $html = '<div class="accordion" id="'.$id.'">'; //using bootstrap
1913
            }
1914
1915
            $count = 1;
1916
            foreach ($items as $item) {
1917
                $html .= '<div class="accordion-my-group">';
1918
                $html .= '<div class="accordion-heading">
1919
                            <a class="accordion-toggle" data-toggle="collapse" data-parent="#'.$id.'" href="#collapse'.$count.'">
1920
                            '.$item['title'].'
1921
                            </a>
1922
                          </div>';
1923
1924
                $html .= '<div id="collapse'.$count.'" class="accordion-body">';
1925
                $html .= '<div class="accordion-my-inner">
1926
                            '.$item['content'].'
1927
                            </div>
1928
                          </div>';
1929
            }
1930
            $html .= '</div>';
1931
        }
1932
1933
        return $html;
1934
    }
1935
1936
    /**
1937
     * @todo use twig
1938
     */
1939
    public static function group_button($title, $elements)
1940
    {
1941
        $html = '<div class="btn-group">
1942
                <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
1943
                '.$title.'
1944
                <span class="caret"></span></button>
1945
                <ul class="dropdown-menu">';
1946
        foreach ($elements as $item) {
1947
            $html .= Display::tag('li', Display::url($item['title'], $item['href']));
1948
        }
1949
        $html .= '</ul>
1950
            </div>';
1951
        return $html;
1952
    }
1953
1954
    /**
1955
     * @param string $file
1956
     * @param array $params
1957
     * @return null|string
1958
     */
1959
    public static function getMediaPlayer($file, $params = array())
1960
    {
1961
        $fileInfo = pathinfo($file);
1962
1963
        switch ($fileInfo['extension']) {
1964
            case 'mp3':
1965
            case 'webm':
1966
                $autoplay = null;
1967
                if (isset($params['autoplay']) && $params['autoplay'] == 'true') {
1968
                    $autoplay = 'autoplay';
1969
                }
1970
                $width = isset($params['width']) ? 'width="'.$params['width'].'"' : null;
1971
                $id = isset($params['id']) ? $params['id'] : $fileInfo['basename'];
1972
                $class = isset($params['class']) ? ' class="'.$params['class'].'"' : null;
1973
1974
                $html = '<audio id="'.$id.'" '.$class.' controls '.$autoplay.' '.$width.' src="'.$params['url'].'" >';
1975
                $html .= '<object width="'.$width.'" height="50" type="application/x-shockwave-flash" data="'.api_get_path(WEB_LIBRARY_JS_PATH).'mediaelement/flashmediaelement.swf">
1976
                            <param name="movie" value="'.api_get_path(WEB_LIBRARY_JS_PATH).'mediaelement/flashmediaelement.swf" />
1977
                            <param name="flashvars" value="controls=true&file='.$params['url'].'" />
1978
                          </object>';
1979
                $html .= '</audio>';
1980
1981
                return $html;
1982
                break;
1983
            case 'wav':
1984
                //no break;
1985
            case 'ogg':
1986
                $html = '<audio width="300px" controls src="'.$params['url'].'" >';
1987
1988
                return $html;
1989
                break;
1990
        }
1991
1992
        return null;
1993
    }
1994
1995
    /**
1996
     *
1997
     * @param int $nextValue
1998
     * @param array $list
1999
     * @param int $current
2000
     * @param int $fixedValue
2001
     * @param array $conditions
2002
     * @param string $link
2003
     * @param bool $isMedia
2004
     * @param bool $addHeaders
2005
     * @return string
2006
     */
2007
    public static function progressPaginationBar(
2008
        $nextValue,
2009
        $list,
2010
        $current,
2011
        $fixedValue = null,
2012
        $conditions = array(),
2013
        $link = null,
2014
        $isMedia = false,
2015
        $addHeaders = true,
2016
        $linkAttributes = array()
2017
    ) {
2018
        if ($addHeaders) {
2019
            $pagination_size = 'pagination-mini';
2020
            $html = '<div class="exercise_pagination pagination '.$pagination_size.'"><ul>';
2021
        } else {
2022
            $html = null;
2023
        }
2024
        $affectAllItems = false;
2025
        if ($isMedia && isset($fixedValue) && ($nextValue + 1 == $current)) {
2026
            $affectAllItems = true;
2027
        }
2028
        $localCounter = 0;
2029
        foreach ($list as $itemId) {
2030
            $isCurrent = false;
2031
            if ($affectAllItems) {
2032
                $isCurrent = true;
2033
            } else {
2034
                if (!$isMedia) {
2035
                    $isCurrent = $current == ($localCounter + $nextValue + 1) ? true : false;
2036
                }
2037
            }
2038
            $html .= self::parsePaginationItem(
2039
                $itemId,
2040
                $isCurrent,
2041
                $conditions,
2042
                $link,
2043
                $nextValue,
2044
                $isMedia,
2045
                $localCounter,
2046
                $fixedValue,
2047
                $linkAttributes
2048
            );
2049
            $localCounter++;
2050
        }
2051
        if ($addHeaders) {
2052
            $html .= '</ul></div>';
2053
        }
2054
        return $html;
2055
    }
2056
    /**
2057
     *
2058
     * @param int $itemId
2059
     * @param bool $isCurrent
2060
     * @param array $conditions
2061
     * @param string $link
2062
     * @param int $nextValue
2063
     * @param bool $isMedia
2064
     * @param int $localCounter
2065
     * @param int $fixedValue
2066
     * @return string
2067
     */
2068
    public static function parsePaginationItem(
2069
        $itemId,
2070
        $isCurrent,
2071
        $conditions,
2072
        $link,
2073
        $nextValue = 0,
2074
        $isMedia = false,
2075
        $localCounter = null,
2076
        $fixedValue = null,
2077
        $linkAttributes = array())
2078
    {
2079
        $defaultClass = "before";
2080
        $class = $defaultClass;
2081
        foreach ($conditions as $condition) {
2082
            $array = isset($condition['items']) ? $condition['items'] : array();
2083
            $class_to_applied = $condition['class'];
2084
            $type = isset($condition['type']) ? $condition['type'] : 'positive';
2085
            $mode = isset($condition['mode']) ? $condition['mode'] : 'add';
2086
            switch ($type) {
2087 View Code Duplication
                case 'positive':
2088
                    if (in_array($itemId, $array)) {
2089
                        if ($mode == 'overwrite') {
2090
                            $class = " $defaultClass $class_to_applied";
2091
                        } else {
2092
                            $class .= " $class_to_applied";
2093
                        }
2094
                    }
2095
                    break;
2096 View Code Duplication
                case 'negative':
2097
                    if (!in_array($itemId, $array)) {
2098
                        if ($mode == 'overwrite') {
2099
                            $class = " $defaultClass $class_to_applied";
2100
                        } else {
2101
                            $class .= " $class_to_applied";
2102
                        }
2103
                    }
2104
                    break;
2105
            }
2106
        }
2107
        if ($isCurrent) {
2108
            $class = "before current";
2109
        }
2110
        if ($isMedia && $isCurrent) {
2111
            $class = "before current";
2112
        }
2113
        if (empty($link)) {
2114
            $link_to_show = "#";
2115
        } else {
2116
            $link_to_show = $link.($nextValue + $localCounter);
2117
        }
2118
        $label = $nextValue + $localCounter + 1;
2119
        if ($isMedia) {
2120
            $label = ($fixedValue + 1) .' '.chr(97 + $localCounter);
2121
            $link_to_show = $link.$fixedValue.'#questionanchor'.$itemId;
2122
        }
2123
        $link = Display::url($label.' ', $link_to_show, $linkAttributes);
2124
        return  '<li class = "'.$class.'">'.$link.'</li>';
2125
    }
2126
2127
    /**
2128
     * @param int $current
2129
     * @param int $total
2130
     * @return string
2131
     */
2132
    public static function paginationIndicator($current, $total)
2133
    {
2134
        $html = null;
2135
        if (!empty($current) && !empty($total)) {
2136
            $label = sprintf(get_lang('PaginationXofY'), $current, $total);
2137
            $html = self::url($label, '#', array('class' => 'btn disabled'));
2138
        }
2139
        return $html;
2140
    }
2141
2142
    /**
2143
     * Adds a message in the queue
2144
     * @param string $message
2145
     */
2146
    public static function addFlash($message)
2147
    {
2148
        $messages = Session::read('flash_messages');
2149
        if (empty($messages)) {
2150
            $messages[] = $message;
2151
        } else {
2152
            array_push($messages, $message);
2153
        }
2154
        Session::write('flash_messages', $messages);
2155
    }
2156
2157
    /**
2158
     * @return string
2159
     */
2160
    public static function getFlashToString()
2161
    {
2162
        $messages = Session::read('flash_messages');
2163
        $messageToString = '';
2164
        if (!empty($messages)) {
2165
            foreach ($messages as $message) {
2166
                $messageToString .= $message;
2167
            }
2168
        }
2169
2170
        return $messageToString;
2171
    }
2172
2173
    /**
2174
     * Shows the message from the session
2175
     */
2176
    public static function showFlash()
2177
    {
2178
        echo self::getFlashToString();
2179
    }
2180
2181
    /**
2182
     * Destroys the message session
2183
     */
2184
    public static function cleanFlashMessages()
2185
    {
2186
        Session::erase('flash_messages');
2187
    }
2188
2189
    /**
2190
     * Get the profile edition link for a user
2191
     * @param int $userId The user id
2192
     * @param boolean $asAdmin Optional. Whether get the URL for the platform admin
2193
     * @return string The link
2194
     */
2195
    public static function getProfileEditionLink($userId, $asAdmin = false)
2196
    {
2197
        $editProfileUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
2198
2199
        if ($asAdmin) {
2200
            $editProfileUrl = api_get_path(WEB_CODE_PATH)."admin/user_edit.php?user_id=".intval($userId);
2201
        }
2202
2203
        if (api_get_setting('sso_authentication') === 'true') {
2204
            $subSSOClass = api_get_setting('sso_authentication_subclass');
2205
2206
            $objSSO = null;
2207
2208
            if (!empty($subSSOClass)) {
2209
                $file = api_get_path(SYS_CODE_PATH)."auth/sso/sso.$subSSOClass.class.php";
2210
                if (file_exists($file)) {
2211
                    require_once $file;
2212
                    $subSSOClass = 'sso'.$subSSOClass;
2213
                    $objSSO = new $subSSOClass();
2214
                } else {
2215
                    throw new Exception("$subSSOClass file not set");
2216
                }
2217
            } else {
2218
                $objSSO = new sso();
2219
            }
2220
2221
            $editProfileUrl = $objSSO->generateProfileEditingURL(
2222
                $userId,
2223
                $asAdmin
2224
            );
2225
        }
2226
2227
        return $editProfileUrl;
2228
    }
2229
2230
    /**
2231
     * Get the vCard for a user
2232
     * @param int $userId The user id
2233
     * @return string *.*vcf file
2234
     */
2235
    public static function getVCardUserLink($userId)
2236
    {
2237
        $vCardUrl = api_get_path(WEB_PATH).'main/social/vcard_export.php?userId='.intval($userId);
2238
2239
        return $vCardUrl;
2240
    }
2241
2242
    /**
2243
     * @param string $content
2244
     * @param string $title
2245
     * @param string $footer
2246
     * @param string $style primary|success|info|warning|danger
2247
     * @param string $extra
2248
     *
2249
     * @return string
2250
     */
2251
    public static function panel($content, $title = '', $footer = '', $style = '', $extra = '')
2252
    {
2253
        $title = !empty($title) ? '<div class="panel-heading"><h3 class="panel-title">'.$title.'</h3>'.$extra.'</div>' : '';
2254
        $footer = !empty($footer) ? '<div class="panel-footer ">'.$footer.'</div>' : '';
2255
        $styles = ['primary', 'success', 'info', 'warning', 'danger'];
2256
        $style = !in_array($style, $styles) ? 'default' : $style;
2257
2258
        return '
2259
            <div class="panel panel-'.$style.'">
2260
                '.$title.'
2261
                '.self::contentPanel($content).'
2262
                '.$footer.'
2263
            </div>'
2264
        ;
2265
    }
2266
2267
    /**
2268
     * @param string $content
2269
     * @return string
2270
     */
2271
    public static function contentPanel($content)
2272
    {
2273
        return '<div class="panel-body">
2274
                '.$content.'
2275
                </div>';
2276
    }
2277
2278
    /**
2279
     * Get the button HTML with an Awesome Font icon
2280
     * @param string $text The button content
2281
     * @param string $url The url to button
2282
     * @param string $icon The Awesome Font class for icon
2283
     * @param string $type Optional. The button Bootstrap class. Default 'default' class
2284
     * @param array $attributes The additional attributes
2285
     * @return string The button HTML
2286
     */
2287
    public static function toolbarButton(
2288
        $text,
2289
        $url,
2290
        $icon = 'check',
2291
        $type = 'default',
2292
        array $attributes = [],
2293
        $includeText = true
2294
    ) {
2295
        $buttonClass = "btn btn-$type";
2296
        $icon = self::tag('i', null, ['class' => "fa fa-$icon fa-fw", 'aria-hidden' => 'true']);
2297
        $attributes['class'] = isset($attributes['class']) ? "$buttonClass {$attributes['class']}" : $buttonClass;
2298
        $attributes['title'] = isset($attributes['title']) ? $attributes['title'] : $text;
2299
2300
        if (!$includeText) {
2301
            $text = '<span class="sr-only">' . $text . '</span>';
2302
        }
2303
2304
        return self::url("$icon $text", $url, $attributes);
2305
    }
2306
2307
    /**
2308
     * @param int $id
2309
     * @param array $content
2310
     * @param int $col
2311
     * @param bool|true $right
2312
     * @return string
2313
     */
2314
    public static function toolbarAction($id, $content = array(), $col = 2, $right = true)
2315
    {
2316
        $columns = 12/$col;
2317
        $html = '';
2318
        $html .= '<div id="' . $id . '" class="actions">';
2319
        $html .= '<div class="row">';
2320
        if ($col > 4) {
2321
            $html = '<div class="alert alert-warning" role="alert">
2322
                Action toolbar design does not work when exceeding four columns - check Display::toolbarAction()
2323
            </div>';
2324
        } else {
2325
            for ($i = 0; $i < $col; $i++) {
2326
                $html .= '<div class="col-md-' . $columns . '">';
2327
                if ($col == 2 && $i == 1) {
2328
                    if ($right === true) {
2329
                        $html .= '<div class="pull-right">';
2330
                        $html .= (isset($content[$i]) ? $content[$i] : '');
2331
                        $html .= '</div>';
2332
                    } else {
2333
                        $html .= $content[$i];
2334
                    }
2335
                } else {
2336
                    $html .= $content[$i];
2337
                }
2338
                $html .= '</div>';
2339
            }
2340
        }
2341
        $html .= '</div>';
2342
        $html .= '</div>';
2343
2344
        return $html;
2345
    }
2346
2347
    /**
2348
     * Get a HTML code for a icon by Font Awesome
2349
     * @param string $name The icon name
2350
     * @param int|string $size Optional. The size for the icon. (Example: lg, 2, 3, 4, 5)
2351
     * @param boolean $fixWidth Optional. Whether add the fw class
2352
     * @param string $additionalClass Optional. Additional class
2353
     *
2354
     * @return string
2355
     */
2356
    public static function returnFontAwesomeIcon(
2357
        $name,
2358
        $size = '',
2359
        $fixWidth = false,
2360
        $additionalClass = ''
2361
    ) {
2362
        $className = "fa fa-$name";
2363
2364
        if ($fixWidth) {
2365
            $className .= ' fa-fw';
2366
        }
2367
2368
        switch ($size) {
2369
            case 'lg':
2370
                $className .= ' fa-lg';
2371
                break;
2372
            case 2:
2373
                //no break
2374
            case 3:
2375
                //no break
2376
            case 4:
2377
                //no break
2378
            case 5:
2379
                $className .= " fa-{$size}x";
2380
                break;
2381
        }
2382
2383
        if (!empty($additionalClass)) {
2384
            $className .= " $additionalClass";
2385
        }
2386
2387
        $icon = self::tag('em', null, ['class' => $className]);
2388
2389
        return "$icon ";
2390
    }
2391
2392
    /**
2393
     * @param string $title
2394
     * @param string $content
2395
     * @param null $id
2396
     * @param array $params
2397
     * @param null $idAccordion
2398
     * @param null $idCollapse
2399
     * @param bool|true $open
2400
     * @param bool|false $fullClickable
2401
     * @return null|string
2402
     */
2403
    public static function panelCollapse(
2404
        $title,
2405
        $content,
2406
        $id = null,
2407
        $params = array(),
2408
        $idAccordion = null,
2409
        $idCollapse = null,
2410
        $open = true,
2411
        $fullClickable = false
2412
    ) {
2413
        if (!empty($idAccordion)) {
2414
            $headerClass = '';
2415
            $headerClass .= $fullClickable ? 'center-block ' : '';
2416
            $headerClass .= $open ? '' : 'collapsed';
2417
            $contentClass = 'panel-collapse collapse ';
2418
            $contentClass .= $open ? 'in' : '';
2419
            $ariaExpanded = $open ? 'true' : 'false';
2420
2421
            $html = <<<HTML
2422
                <div class="panel-group" id="$idAccordion" role="tablist" aria-multiselectable="true">
2423
                    <div class="panel panel-default" id="$id">
2424
                        <div class="panel-heading" role="tab">
2425
                            <h4 class="panel-title">
2426
                                <a class="$headerClass" role="button" data-toggle="collapse" data-parent="#$idAccordion" href="#$idCollapse" aria-expanded="$ariaExpanded" aria-controls="$idCollapse">$title</a>
2427
                            </h4>
2428
                        </div>
2429
                        <div id="$idCollapse" class="$contentClass" role="tabpanel">
2430
                            <div class="panel-body">$content</div>
2431
                        </div>
2432
                    </div>
2433
                </div>
2434
HTML;
2435
        } else {
2436
            if (!empty($id)) {
2437
                $params['id'] = $id;
2438
            }
2439
            $params['class'] = 'panel panel-default';
2440
            $html = null;
2441
            if (!empty($title)) {
2442
                $html .= '<div class="panel-heading">'.$title.'</div>' . PHP_EOL;
2443
            }
2444
            $html.= '<div class="panel-body">'.$content.'</div>' . PHP_EOL;
2445
            $html = Display::div($html, $params);
2446
        }
2447
        return $html;
2448
    }
2449
2450
    /**
2451
     * Returns the string "1 day ago" with a link showing the exact date time.
2452
     * @param string $dateTime in UTC
2453
     *
2454
     * @return string
2455
     */
2456
    public static function dateToStringAgoAndLongDate($dateTime)
2457
    {
2458
        if (empty($dateTime) || $dateTime === '0000-00-00 00:00:00') {
2459
            return '';
2460
        }
2461
2462
        return self::tip(
2463
            date_to_str_ago($dateTime),
2464
            api_get_local_time($dateTime)
2465
        );
2466
    }
2467
}
2468