Completed
Push — master ( 395485...bbad3a )
by Julito
43:12
created

Display::badge_group()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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

This method has been deprecated.

Loading history...
2354
    }
2355
2356
    /**
2357
     * Destroys the message session
2358
     * @deprecated
2359
     */
2360
    public static function cleanFlashMessages()
2361
    {
2362
        Session::erase('flash_messages');
2363
    }
2364
2365
    /**
2366
     * Get the profile edition link for a user
2367
     * @param int $userId The user id
2368
     * @param boolean $asAdmin Optional. Whether get the URL for the platform admin
2369
     * @return string The link
2370
     */
2371
    public static function getProfileEditionLink($userId, $asAdmin = false)
2372
    {
2373
        $editProfileUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
2374
2375
        if ($asAdmin) {
2376
            $editProfileUrl = api_get_path(WEB_CODE_PATH)."admin/user_edit.php?user_id=".intval($userId);
2377
        }
2378
2379
        if (api_get_setting('sso_authentication') === 'true') {
2380
            $subSSOClass = api_get_setting('sso_authentication_subclass');
2381
2382
            $objSSO = null;
2383
2384
            if (!empty($subSSOClass)) {
2385
                $file = api_get_path(SYS_CODE_PATH)."auth/sso/sso.$subSSOClass.class.php";
2386
                if (file_exists($file)) {
2387
                    require_once $file;
2388
                    $subSSOClass = 'sso'.$subSSOClass;
2389
                    $objSSO = new $subSSOClass();
2390
                } else {
2391
                    throw new Exception("$subSSOClass file not set");
2392
                }
2393
            } else {
2394
                $objSSO = new sso();
2395
            }
2396
2397
            $editProfileUrl = $objSSO->generateProfileEditingURL(
2398
                $userId,
2399
                $asAdmin
2400
            );
2401
        }
2402
2403
        return $editProfileUrl;
2404
    }
2405
2406
    /**
2407
     * Get the vCard for a user
2408
     * @param int $userId The user id
2409
     * @return string *.*vcf file
2410
     */
2411
    public static function getVCardUserLink($userId)
2412
    {
2413
        $vCardUrl = api_get_path(WEB_PATH).'main/social/vcard_export.php?userId='.intval($userId);
2414
2415
        return $vCardUrl;
2416
    }
2417
2418
    /**
2419
     * @param string $content
2420
     * @param string $title
2421
     * @param string $footer
2422
     * @param string $style primary|success|info|warning|danger
2423
     * @param string $extra
2424
     *
2425
     * @return string
2426
     */
2427
    public static function panel($content, $title = '', $footer = '', $style = '', $extra = '')
2428
    {
2429
        $title = !empty($title) ? '<div class="panel-heading"><h3 class="panel-title">'.$title.'</h3>'.$extra.'</div>' : '';
2430
        $footer = !empty($footer) ? '<div class="panel-footer ">'.$footer.'</div>' : '';
2431
        $styles = ['primary', 'success', 'info', 'warning', 'danger'];
2432
        $style = !in_array($style, $styles) ? 'default' : $style;
2433
2434
        return '
2435
            <div class="panel panel-'.$style.'">
2436
                '.$title.'
2437
                '.self::contentPanel($content).'
2438
                '.$footer.'
2439
            </div>'
2440
        ;
2441
    }
2442
2443
    /**
2444
     * @param string $content
2445
     * @return string
2446
     */
2447
    public static function contentPanel($content)
2448
    {
2449
        return '<div class="panel-body">
2450
                '.$content.'
2451
                </div>';
2452
    }
2453
2454
    /**
2455
     * Get the button HTML with an Awesome Font icon
2456
     * @param string $text The button content
2457
     * @param string $url The url to button
2458
     * @param string $icon The Awesome Font class for icon
2459
     * @param string $type Optional. The button Bootstrap class. Default 'default' class
2460
     * @param array $attributes The additional attributes
2461
     * @param bool $includeText
2462
     *
2463
     * @return string The button HTML
2464
     */
2465
    public static function toolbarButton(
2466
        $text,
2467
        $url,
2468
        $icon = 'check',
2469
        $type = 'default',
2470
        array $attributes = [],
2471
        $includeText = true
2472
    ) {
2473
        $buttonClass = "btn btn-$type";
2474
        $icon = self::tag('i', null, ['class' => "fa fa-$icon fa-fw", 'aria-hidden' => 'true']);
2475
        $attributes['class'] = isset($attributes['class']) ? "$buttonClass {$attributes['class']}" : $buttonClass;
2476
        $attributes['title'] = isset($attributes['title']) ? $attributes['title'] : $text;
2477
2478
        if (!$includeText) {
2479
            $text = '<span class="sr-only">' . $text . '</span>';
2480
        }
2481
2482
        return self::url("$icon $text", $url, $attributes);
2483
    }
2484
2485
    /**
2486
     * @param int $id
2487
     * @param array $content
2488
     * @param int $col
2489
     * @param bool|true $right
2490
     * @return string
2491
     */
2492
    public static function toolbarAction($id, $content = array(), $col = 2, $right = true)
2493
    {
2494
        $columns = 12/$col;
2495
        $html = '';
2496
        $html .= '<div id="' . $id . '" class="actions">';
2497
        $html .= '<div class="row">';
2498
        if ($col > 4) {
2499
            $html = '<div class="alert alert-warning" role="alert">
2500
                Action toolbar design does not work when exceeding four columns - check Display::toolbarAction()
2501
            </div>';
2502
        } else {
2503
            for ($i = 0; $i < $col; $i++) {
2504
                $html .= '<div class="col-md-' . $columns . '">';
2505
                if ($col == 2 && $i == 1) {
2506
                    if ($right === true) {
2507
                        $html .= '<div class="pull-right">';
2508
                        $html .= (isset($content[$i]) ? $content[$i] : '');
2509
                        $html .= '</div>';
2510
                    } else {
2511
                        $html .= $content[$i];
2512
                    }
2513
                } else {
2514
                    $html .= $content[$i];
2515
                }
2516
                $html .= '</div>';
2517
            }
2518
        }
2519
        $html .= '</div>';
2520
        $html .= '</div>';
2521
2522
        return $html;
2523
    }
2524
2525
    /**
2526
     * Get a HTML code for a icon by Font Awesome
2527
     * @param string $name The icon name
2528
     * @param int|string $size Optional. The size for the icon. (Example: lg, 2, 3, 4, 5)
2529
     * @param boolean $fixWidth Optional. Whether add the fw class
2530
     * @param string $additionalClass Optional. Additional class
2531
     *
2532
     * @return string
2533
     */
2534
    public static function returnFontAwesomeIcon(
2535
        $name,
2536
        $size = '',
2537
        $fixWidth = false,
2538
        $additionalClass = ''
2539
    ) {
2540
        $className = "fa fa-$name";
2541
2542
        if ($fixWidth) {
2543
            $className .= ' fa-fw';
2544
        }
2545
2546
        switch ($size) {
2547
            case 'lg':
2548
                $className .= ' fa-lg';
2549
                break;
2550
            case 2:
2551
                //no break
2552
            case 3:
2553
                //no break
2554
            case 4:
2555
                //no break
2556
            case 5:
2557
                $className .= " fa-{$size}x";
2558
                break;
2559
        }
2560
2561
        if (!empty($additionalClass)) {
2562
            $className .= " $additionalClass";
2563
        }
2564
2565
        $icon = self::tag('em', null, ['class' => $className]);
2566
2567
        return "$icon ";
2568
    }
2569
2570
    /**
2571
     * @param string $title
2572
     * @param string $content
2573
     * @param null $id
2574
     * @param array $params
2575
     * @param null $idAccordion
2576
     * @param null $idCollapse
2577
     * @param bool|true $open
2578
     * @param bool|false $fullClickable
2579
     * @return null|string
2580
     */
2581
    public static function panelCollapse(
2582
        $title,
2583
        $content,
2584
        $id = null,
2585
        $params = array(),
2586
        $idAccordion = null,
2587
        $idCollapse = null,
2588
        $open = true,
2589
        $fullClickable = false
2590
    ) {
2591
        if (!empty($idAccordion)) {
2592
            $headerClass = '';
2593
            $headerClass .= $fullClickable ? 'center-block ' : '';
2594
            $headerClass .= $open ? '' : 'collapsed';
2595
            $contentClass = 'panel-collapse collapse ';
2596
            $contentClass .= $open ? 'in' : '';
2597
            $ariaExpanded = $open ? 'true' : 'false';
2598
2599
            $html = <<<HTML
2600
                <div class="panel-group" id="$idAccordion" role="tablist" aria-multiselectable="true">
2601
                    <div class="panel panel-default" id="$id">
2602
                        <div class="panel-heading" role="tab">
2603
                            <h4 class="panel-title">
2604
                                <a class="$headerClass" role="button" data-toggle="collapse" data-parent="#$idAccordion" href="#$idCollapse" aria-expanded="$ariaExpanded" aria-controls="$idCollapse">$title</a>
2605
                            </h4>
2606
                        </div>
2607
                        <div id="$idCollapse" class="$contentClass" role="tabpanel">
2608
                            <div class="panel-body">$content</div>
2609
                        </div>
2610
                    </div>
2611
                </div>
2612
HTML;
2613
        } else {
2614
            if (!empty($id)) {
2615
                $params['id'] = $id;
2616
            }
2617
            $params['class'] = 'panel panel-default';
2618
            $html = null;
2619
            if (!empty($title)) {
2620
                $html .= '<div class="panel-heading">'.$title.'</div>' . PHP_EOL;
2621
            }
2622
            $html.= '<div class="panel-body">'.$content.'</div>' . PHP_EOL;
2623
            $html = Display::div($html, $params);
2624
        }
2625
        return $html;
2626
    }
2627
2628
    /**
2629
     * Returns the string "1 day ago" with a link showing the exact date time.
2630
     * @param string $dateTime in UTC or a DateTime in UTC
2631
     *
2632
     * @return string
2633
     */
2634
    public static function dateToStringAgoAndLongDate($dateTime)
2635
    {
2636
       if (empty($dateTime) || $dateTime === '0000-00-00 00:00:00') {
2637
            return '';
2638
        }
2639
2640
        if ($dateTime instanceof \DateTime) {
2641
            $dateTime = $dateTime->format('Y-m-d H:i:s');
2642
        }
2643
2644
        return self::tip(
2645
            date_to_str_ago($dateTime),
2646
            api_get_local_time($dateTime)
2647
        );
2648
    }
2649
}
2650