Completed
Push — 1.10.x ( a26f23...c6c321 )
by Julito
59:04
created

DocumentManager::purgeDocuments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 *  Class DocumentManager
6
 * 	This is the document library for Chamilo.
7
 * 	It is / will be used to provide a service layer to all document-using tools.
8
 * 	and eliminate code duplication fro group documents, scorm documents, main documents.
9
 * 	Include/require it in your code to use its functionality.
10
 *
11
 * 	@package chamilo.library
12
 */
13
class DocumentManager
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
14
{
15
    /**
16
     * Construct
17
     */
18
    private function __construct()
19
    {
20
    }
21
22
    /**
23
     * @param string $course_code
24
     *
25
     * @return int the document folder quota for the current course in bytes
26
     * or the default quota
27
     */
28
    public static function get_course_quota($course_code = null)
29
    {
30
        if (empty($course_code)) {
31
            $course_info = api_get_course_info();
32
        } else {
33
            $course_info = api_get_course_info($course_code);
34
        }
35
36
        $course_quota = null;
37
        if (empty($course_info)) {
38
            return DEFAULT_DOCUMENT_QUOTA;
39
        } else {
40
            $course_quota = $course_info['disk_quota'];
41
        }
42
        if (is_null($course_quota) || empty($course_quota)) {
43
            // Course table entry for quota was null, then use default value
44
            $course_quota = DEFAULT_DOCUMENT_QUOTA;
45
        }
46
        return $course_quota;
47
    }
48
49
    /**
50
     * 	Get the content type of a file by checking the extension
51
     * 	We could use mime_content_type() with php-versions > 4.3,
52
     * 	but this doesn't work as it should on Windows installations
53
     *
54
     * 	@param string $filename or boolean TRUE to return complete array
55
     * 	@author ? first version
56
     * 	@author Bert Vanderkimpen
57
     *  @return string
58
     *
59
     */
60
    public static function file_get_mime_type($filename)
61
    {
62
        // All MIME types in an array (from 1.6, this is the authorative source)
63
        // Please, keep this alphabetical if you add something to this list!
64
        $mime_types = array(
65
            'ai' => 'application/postscript',
66
            'aif' => 'audio/x-aiff',
67
            'aifc' => 'audio/x-aiff',
68
            'aiff' => 'audio/x-aiff',
69
            'asf' => 'video/x-ms-asf',
70
            'asc' => 'text/plain',
71
            'au' => 'audio/basic',
72
            'avi' => 'video/x-msvideo',
73
            'bcpio' => 'application/x-bcpio',
74
            'bin' => 'application/octet-stream',
75
            'bmp' => 'image/bmp',
76
            'cdf' => 'application/x-netcdf',
77
            'class' => 'application/octet-stream',
78
            'cpio' => 'application/x-cpio',
79
            'cpt' => 'application/mac-compactpro',
80
            'csh' => 'application/x-csh',
81
            'css' => 'text/css',
82
            'dcr' => 'application/x-director',
83
            'dir' => 'application/x-director',
84
            'djv' => 'image/vnd.djvu',
85
            'djvu' => 'image/vnd.djvu',
86
            'dll' => 'application/octet-stream',
87
            'dmg' => 'application/x-diskcopy',
88
            'dms' => 'application/octet-stream',
89
            'doc' => 'application/msword',
90
            'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
91
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
92
            'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
93
            'dvi' => 'application/x-dvi',
94
            'dwg' => 'application/vnd.dwg',
95
            'dwf' => 'application/vnd.dwf',
96
            'dxf' => 'application/vnd.dxf',
97
            'dxr' => 'application/x-director',
98
            'eps' => 'application/postscript',
99
            'epub' => 'application/epub+zip',
100
            'etx' => 'text/x-setext',
101
            'exe' => 'application/octet-stream',
102
            'ez' => 'application/andrew-inset',
103
            'gif' => 'image/gif',
104
            'gtar' => 'application/x-gtar',
105
            'gz' => 'application/x-gzip',
106
            'hdf' => 'application/x-hdf',
107
            'hqx' => 'application/mac-binhex40',
108
            'htm' => 'text/html',
109
            'html' => 'text/html',
110
            'ice' => 'x-conference-xcooltalk',
111
            'ief' => 'image/ief',
112
            'iges' => 'model/iges',
113
            'igs' => 'model/iges',
114
            'jar' => 'application/java-archiver',
115
            'jpe' => 'image/jpeg',
116
            'jpeg' => 'image/jpeg',
117
            'jpg' => 'image/jpeg',
118
            'js' => 'application/x-javascript',
119
            'kar' => 'audio/midi',
120
            'lam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
121
            'latex' => 'application/x-latex',
122
            'lha' => 'application/octet-stream',
123
            'log' => 'text/plain',
124
            'lzh' => 'application/octet-stream',
125
            'm1a' => 'audio/mpeg',
126
            'm2a' => 'audio/mpeg',
127
            'm3u' => 'audio/x-mpegurl',
128
            'man' => 'application/x-troff-man',
129
            'me' => 'application/x-troff-me',
130
            'mesh' => 'model/mesh',
131
            'mid' => 'audio/midi',
132
            'midi' => 'audio/midi',
133
            'mov' => 'video/quicktime',
134
            'movie' => 'video/x-sgi-movie',
135
            'mp2' => 'audio/mpeg',
136
            'mp3' => 'audio/mpeg',
137
            'mp4' => 'video/mpeg4-generic',
138
            'mpa' => 'audio/mpeg',
139
            'mpe' => 'video/mpeg',
140
            'mpeg' => 'video/mpeg',
141
            'mpg' => 'video/mpeg',
142
            'mpga' => 'audio/mpeg',
143
            'ms' => 'application/x-troff-ms',
144
            'msh' => 'model/mesh',
145
            'mxu' => 'video/vnd.mpegurl',
146
            'nc' => 'application/x-netcdf',
147
            'oda' => 'application/oda',
148
            'oga' => 'audio/ogg',
149
            'ogg' => 'application/ogg',
150
            'ogx' => 'application/ogg',
151
            'ogv' => 'video/ogg',
152
            'pbm' => 'image/x-portable-bitmap',
153
            'pct' => 'image/pict',
154
            'pdb' => 'chemical/x-pdb',
155
            'pdf' => 'application/pdf',
156
            'pgm' => 'image/x-portable-graymap',
157
            'pgn' => 'application/x-chess-pgn',
158
            'pict' => 'image/pict',
159
            'png' => 'image/png',
160
            'pnm' => 'image/x-portable-anymap',
161
            'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
162
            'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
163
            'pps' => 'application/vnd.ms-powerpoint',
164
            'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
165
            'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
166
            'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
167
            'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
168
            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
169
            'ppm' => 'image/x-portable-pixmap',
170
            'ppt' => 'application/vnd.ms-powerpoint',
171
            'pps' => 'application/vnd.ms-powerpoint',
172
            'ps' => 'application/postscript',
173
            'qt' => 'video/quicktime',
174
            'ra' => 'audio/x-realaudio',
175
            'ram' => 'audio/x-pn-realaudio',
176
            'rar' => 'image/x-rar-compressed',
177
            'ras' => 'image/x-cmu-raster',
178
            'rgb' => 'image/x-rgb',
179
            'rm' => 'audio/x-pn-realaudio',
180
            'roff' => 'application/x-troff',
181
            'rpm' => 'audio/x-pn-realaudio-plugin',
182
            'rtf' => 'text/rtf',
183
            'rtx' => 'text/richtext',
184
            'sgm' => 'text/sgml',
185
            'sgml' => 'text/sgml',
186
            'sh' => 'application/x-sh',
187
            'shar' => 'application/x-shar',
188
            'silo' => 'model/mesh',
189
            'sib' => 'application/X-Sibelius-Score',
190
            'sit' => 'application/x-stuffit',
191
            'skd' => 'application/x-koan',
192
            'skm' => 'application/x-koan',
193
            'skp' => 'application/x-koan',
194
            'skt' => 'application/x-koan',
195
            'smi' => 'application/smil',
196
            'smil' => 'application/smil',
197
            'snd' => 'audio/basic',
198
            'so' => 'application/octet-stream',
199
            'spl' => 'application/x-futuresplash',
200
            'src' => 'application/x-wais-source',
201
            'sv4cpio' => 'application/x-sv4cpio',
202
            'sv4crc' => 'application/x-sv4crc',
203
            'svf' => 'application/vnd.svf',
204
            'svg' => 'image/svg+xml',
205
            //'svgz' => 'image/svg+xml',
206
            'swf' => 'application/x-shockwave-flash',
207
            'sxc' => 'application/vnd.sun.xml.calc',
208
            'sxi' => 'application/vnd.sun.xml.impress',
209
            'sxw' => 'application/vnd.sun.xml.writer',
210
            't' => 'application/x-troff',
211
            'tar' => 'application/x-tar',
212
            'tcl' => 'application/x-tcl',
213
            'tex' => 'application/x-tex',
214
            'texi' => 'application/x-texinfo',
215
            'texinfo' => 'application/x-texinfo',
216
            'tga' => 'image/x-targa',
217
            'tif' => 'image/tif',
218
            'tiff' => 'image/tiff',
219
            'tr' => 'application/x-troff',
220
            'tsv' => 'text/tab-seperated-values',
221
            'txt' => 'text/plain',
222
            'ustar' => 'application/x-ustar',
223
            'vcd' => 'application/x-cdlink',
224
            'vrml' => 'model/vrml',
225
            'wav' => 'audio/x-wav',
226
            'wbmp' => 'image/vnd.wap.wbmp',
227
            'wbxml' => 'application/vnd.wap.wbxml',
228
            'wml' => 'text/vnd.wap.wml',
229
            'wmlc' => 'application/vnd.wap.wmlc',
230
            'wmls' => 'text/vnd.wap.wmlscript',
231
            'wmlsc' => 'application/vnd.wap.wmlscriptc',
232
            'wma' => 'audio/x-ms-wma',
233
            'wmv' => 'video/x-ms-wmv',
234
            'wrl' => 'model/vrml',
235
            'xbm' => 'image/x-xbitmap',
236
            'xht' => 'application/xhtml+xml',
237
            'xhtml' => 'application/xhtml+xml',
238
            'xls' => 'application/vnd.ms-excel',
239
            'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
240
            'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
241
            'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
242
            'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
243
            'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
244
            'xml' => 'text/xml',
245
            'xpm' => 'image/x-xpixmap',
246
            'xsl' => 'text/xml',
247
            'xwd' => 'image/x-windowdump',
248
            'xyz' => 'chemical/x-xyz',
249
            'zip' => 'application/zip'
250
        );
251
252
        if ($filename === true) {
253
254
            return $mime_types;
255
        }
256
257
        //get the extension of the file
258
        $extension = explode('.', $filename);
259
260
        //$filename will be an array if a . was found
261
        if (is_array($extension)) {
262
            $extension = strtolower($extension[sizeof($extension) - 1]);
263
        } else {
264
            //file without extension
265
            $extension = 'empty';
266
        }
267
268
        //if the extension is found, return the content type
269
        if (isset($mime_types[$extension])) {
270
271
            return $mime_types[$extension];
272
        }
273
        //else return octet-stream
274
        return 'application/octet-stream';
275
    }
276
277
    /**
278
     *  @param string
279
     *  @param string
280
     * 	@return true if the user is allowed to see the document, false otherwise
281
     * 	@author Sergio A Kessler, first version
282
     * 	@author Roan Embrechts, bugfix
283
     *  @todo not only check if a file is visible, but also check if the user is allowed to see the file??
284
     */
285
    public static function file_visible_to_user($this_course, $doc_url)
286
    {
287
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
288
289
        if ($is_allowed_to_edit) {
290
            return true;
291
        } else {
292
            $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
293
            $tbl_item_property = $this_course . 'item_property';
294
            $doc_url = Database::escape_string($doc_url);
295
            $query = "SELECT 1 FROM $tbl_document AS docs,$tbl_item_property AS props
296
                      WHERE
297
                            props.tool = 'document' AND
298
                            docs.id=props.ref AND
299
                            props.visibility <> '1' AND
300
                            docs.path = '$doc_url'";
301
            $result = Database::query($query);
302
303
            return (Database::num_rows($result) == 0);
304
        }
305
    }
306
307
    /**
308
     * This function streams a file to the client
309
     *
310
     * @param string $full_file_name
311
     * @param boolean $forced
312
     * @param string $name
313
     * @param string $fixLinksHttpToHttps change file content from http to https
314
     *
315
     * @return false if file doesn't exist, true if stream succeeded
316
     */
317
    public static function file_send_for_download(
318
        $full_file_name,
319
        $forced = false,
320
        $name = '',
321
        $fixLinksHttpToHttps = false
322
    ) {
323
        session_write_close(); //we do not need write access to session anymore
324
        if (!is_file($full_file_name)) {
325
            return false;
326
        }
327
        $filename = ($name == '') ? basename($full_file_name) : api_replace_dangerous_char($name);
328
        $len = filesize($full_file_name);
329
        // Fixing error when file name contains a ","
330
        $filename = str_replace(',', '', $filename);
331
332
        $sendFileHeaders = api_get_configuration_value('enable_x_sendfile_headers');
333
334
        if ($forced) {
335
            // Force the browser to save the file instead of opening it
336
337
            if (isset($sendFileHeaders) &&
338
                !empty($sendFileHeaders)) {
339
                header("X-Sendfile: $filename");
340
            }
341
342
            header('Content-type: application/octet-stream');
343
            header('Content-length: ' . $len);
344 View Code Duplication
            if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
345
                header('Content-Disposition: filename= ' . $filename);
346
            } else {
347
                header('Content-Disposition: attachment; filename= ' . $filename);
348
            }
349
            if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
350
                header('Pragma: ');
351
                header('Cache-Control: ');
352
                header('Cache-Control: public'); // IE cannot download from sessions without a cache
353
            }
354
            header('Content-Description: ' . $filename);
355
            header('Content-Transfer-Encoding: binary');
356
357
            $res = fopen($full_file_name, 'r');
358
            fpassthru($res);
359
360
            return true;
361
        } else {
362
            //no forced download, just let the browser decide what to do according to the mimetype
363
364
            $content_type = self::file_get_mime_type($filename);
365
            $lpFixedEncoding = api_get_configuration_value('lp_fixed_encoding');
366
367
            header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
368
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
369
            // Commented to avoid double caching declaration when playing with IE and HTTPS
370
            //header('Cache-Control: no-cache, must-revalidate');
371
            //header('Pragma: no-cache');
372
            switch ($content_type) {
373 View Code Duplication
                case 'text/html':
374
                    if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
375
                        $content_type .= '; charset=UTF-8';
376
                    } else {
377
                        $encoding = @api_detect_encoding_html(file_get_contents($full_file_name));
378
                        if (!empty($encoding)) {
379
                            $content_type .= '; charset=' . $encoding;
380
                        }
381
                    }
382
                    break;
383 View Code Duplication
                case 'text/plain':
384
                    if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
385
                        $content_type .= '; charset=UTF-8';
386
                    } else {
387
                        $encoding = @api_detect_encoding(strip_tags(file_get_contents($full_file_name)));
388
                        if (!empty($encoding)) {
389
                            $content_type .= '; charset=' . $encoding;
390
                        }
391
                    }
392
                    break;
393
                case 'application/vnd.dwg':
394
                case 'application/vnd.dwf':
395
                    header('Content-type: application/octet-stream');
396
                    break;
397
            }
398
            header('Content-type: ' . $content_type);
399
            header('Content-Length: ' . $len);
400
            $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
401 View Code Duplication
            if (strpos($user_agent, 'msie')) {
402
                header('Content-Disposition: ; filename= ' . $filename);
403
            } else {
404
                header('Content-Disposition: inline; filename= ' . $filename);
405
            }
406
407
            if ($fixLinksHttpToHttps) {
408
                $content = file_get_contents($full_file_name);
409
                $content = str_replace(
410
                    array('http%3A%2F%2F', 'http://'),
411
                    array('https%3A%2F%2F', 'https://'),
412
                    $content
413
                );
414
                echo $content;
415
            } else {
416
                readfile($full_file_name);
417
            }
418
419
            return true;
420
        }
421
    }
422
423
    /**
424
     * This function streams a string to the client for download.
425
     * You have to ensure that the calling script then stops processing (exit();)
426
     * otherwise it may cause subsequent use of the page to want to download
427
     * other pages in php rather than interpreting them.
428
     *
429
     * @param string $full_string The string contents
430
     * @param boolean $forced Whether "save" mode is forced (or opening directly authorized)
431
     * @param string $name The name of the file in the end (including extension)
432
     *
433
     * @return false if file doesn't exist, true if stream succeeded
434
     */
435
    public static function string_send_for_download($full_string, $forced = false, $name = '')
436
    {
437
        $filename = $name;
438
        $len = strlen($full_string);
439
440
        if ($forced) {
441
            //force the browser to save the file instead of opening it
442
443
            header('Content-type: application/octet-stream');
444
            //header('Content-Type: application/force-download');
445
            header('Content-length: ' . $len);
446 View Code Duplication
            if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
447
                header('Content-Disposition: filename= ' . $filename);
448
            } else {
449
                header('Content-Disposition: attachment; filename= ' . $filename);
450
            }
451
            if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
452
                header('Pragma: ');
453
                header('Cache-Control: ');
454
                header('Cache-Control: public'); // IE cannot download from sessions without a cache
455
            }
456
            header('Content-Description: ' . $filename);
457
            header('Content-transfer-encoding: binary');
458
            echo $full_string;
459
460
            return true;
461
            //You have to ensure that the calling script then stops processing (exit();)
462
            //otherwise it may cause subsequent use of the page to want to download
463
            //other pages in php rather than interpreting them.
464
        } else {
465
            //no forced download, just let the browser decide what to do according to the mimetype
466
467
            $content_type = self::file_get_mime_type($filename);
468
            header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
469
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
470
            header('Cache-Control: no-cache, must-revalidate');
471
            header('Pragma: no-cache');
472
            switch ($content_type) {
473
                case 'text/html':
474
                    $encoding = @api_detect_encoding_html($full_string);
475
                    if (!empty($encoding)) {
476
                        $content_type .= '; charset=' . $encoding;
477
                    }
478
                    break;
479
                case 'text/plain':
480
                    $encoding = @api_detect_encoding(strip_tags($full_string));
481
                    if (!empty($encoding)) {
482
                        $content_type .= '; charset=' . $encoding;
483
                    }
484
                    break;
485
            }
486
            header('Content-type: ' . $content_type);
487
            header('Content-Length: ' . $len);
488
            $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
489 View Code Duplication
            if (strpos($user_agent, 'msie')) {
490
                header('Content-Disposition: ; filename= ' . $filename);
491
            } else {
492
                header('Content-Disposition: inline; filename= ' . $filename);
493
            }
494
            echo($full_string);
495
            //You have to ensure that the calling script then stops processing (exit();)
496
            //otherwise it may cause subsequent use of the page to want to download
497
            //other pages in php rather than interpreting them.
498
            return true;
499
        }
500
    }
501
502
    /**
503
     * Session folder filters
504
     *
505
     * @param string $path
506
     * @param int    $sessionId
507
     *
508
     * @return null|string
509
     */
510
    public static function getSessionFolderFilters($path, $sessionId)
511
    {
512
        $sessionId = intval($sessionId);
513
        $condition = null;
514
515
        if (!empty($sessionId)) {
516
            // Chat folder filter
517
            if ($path == '/chat_files') {
518
                $condition .= " AND (docs.session_id = '$sessionId') ";
519
            }
520
            // share_folder filter
521
            $condition .= " AND docs.path != '/shared_folder' ";
522
        }
523
524
        return $condition;
525
    }
526
527
    /**
528
     * Fetches all document data for the given user/group
529
     *
530
     * @param array $_course
531
     * @param string $path
532
     * @param int $to_group_id
533
     * @param int $to_user_id
534
     * @param boolean $can_see_invisible
535
     * @param boolean $search
536
     * @return array with all document data
537
     */
538
    public static function get_all_document_data(
539
        $_course,
540
        $path = '/',
541
        $to_group_id = 0,
542
        $to_user_id = null,
543
        $can_see_invisible = false,
544
        $search = false
545
    ) {
546
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
547
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
548
549
        $userGroupFilter = '';
550
        if (!is_null($to_user_id)) {
551
            $to_user_id = intval($to_user_id);
552
            $userGroupFilter = "last.to_user_id = $to_user_id";
553
            if (empty($to_user_id)) {
554
                $userGroupFilter = " (last.to_user_id = 0 OR last.to_user_id IS NULL) ";
555
            }
556
        } else {
557
            $to_group_id = intval($to_group_id);
558
            $userGroupFilter = "last.to_group_id = $to_group_id";
559
            if (empty($to_group_id)) {
560
                $userGroupFilter = "( last.to_group_id = 0 OR last.to_group_id IS NULL) ";
561
            }
562
        }
563
564
        // Escape underscores in the path so they don't act as a wildcard
565
        $originalPath = $path;
566
        $path = str_replace('_', '\_', $path);
567
568
        $visibility_bit = ' <> 2';
569
570
        // The given path will not end with a slash, unless it's the root '/'
571
        // so no root -> add slash
572
        $added_slash = $path == '/' ? '' : '/';
573
574
        // Condition for the session
575
        $sessionId = api_get_session_id();
576
        $condition_session = " AND (last.session_id = '$sessionId' OR (last.session_id = '0' OR last.session_id IS NULL) )";
577
        $condition_session .= self::getSessionFolderFilters($originalPath, $sessionId);
578
579
        $sharedCondition = null;
580 View Code Duplication
        if ($originalPath == '/shared_folder') {
581
            $students = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
582
            if (!empty($students)) {
583
                $conditionList = array();
584
                foreach ($students as $studentId => $studentInfo) {
0 ignored issues
show
Bug introduced by
The expression $students of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
585
                    $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
586
                }
587
                $sharedCondition .= ' AND docs.path IN ("' . implode('","', $conditionList) . '")';
588
            }
589
        }
590
591
        $sql = "SELECT
592
                    docs.id,
593
                    docs.filetype,
594
                    docs.path,
595
                    docs.title,
596
                    docs.comment,
597
                    docs.size,
598
                    docs.readonly,
599
                    docs.session_id,
600
                    last.session_id item_property_session_id,
601
                    last.lastedit_date,
602
                    last.visibility,
603
                    last.insert_user_id
604
                FROM $TABLE_ITEMPROPERTY AS last
605
                INNER JOIN $TABLE_DOCUMENT AS docs
606
                ON (
607
                    docs.id = last.ref AND
608
                    last.tool = '".TOOL_DOCUMENT."' AND
609
                    docs.c_id = {$_course['real_id']} AND
610
                    last.c_id = {$_course['real_id']}
611
                )
612
                WHERE
613
                    docs.path LIKE '" . Database::escape_string($path . $added_slash.'%'). "' AND
614
                    docs.path NOT LIKE '" . Database::escape_string($path . $added_slash.'%/%')."' AND
615
                    docs.path NOT LIKE '%_DELETED_%' AND
616
                    $userGroupFilter AND
617
                    last.visibility $visibility_bit
618
                    $condition_session
619
                    $sharedCondition
620
                ";
621
        $result = Database::query($sql);
622
623
        $doc_list = array();
624
        $document_data = array();
625
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
626
        $isCoach = api_is_coach();
627
        if ($result !== false && Database::num_rows($result) != 0) {
628
            while ($row = Database::fetch_array($result, 'ASSOC')) {
629
                if ($isCoach) {
630
                    // Looking for course items that are invisible to hide it in the session
631
                    if (in_array($row['id'], array_keys($doc_list))) {
632
                        if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
633
                            $doc_list[$row['id']]['session_id'] == 0
634
                        ) {
635
                            if ($doc_list[$row['id']]['visibility'] == 0) {
636
                                unset($document_data[$row['id']]);
637
                                continue;
638
                            }
639
                        }
640
                    }
641
                    $doc_list[$row['id']] = $row;
642
                }
643
644
                if (!$isCoach && !$is_allowed_to_edit) {
645
                    $doc_list[] = $row;
646
                }
647
648
                if ($row['filetype'] == 'file' &&
649
                    pathinfo($row['path'], PATHINFO_EXTENSION) == 'html'
650
                ) {
651
                    // Templates management
652
                    $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
653
                    $sql = "SELECT id FROM $table_template
654
                            WHERE
655
                                course_code = '" . $_course['code'] . "' AND
656
                                user_id = '".api_get_user_id()."' AND
657
                                ref_doc = '".$row['id']."'";
658
                    $template_result = Database::query($sql);
659
                    $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
660
                }
661
                // Just filling $document_data.
662
                $document_data[$row['id']] = $row;
663
            }
664
665
            // Only for the student we filter the results see BT#1652
666
            if (!$isCoach && !$is_allowed_to_edit) {
667
                $ids_to_remove = array();
668
                $my_repeat_ids = $temp = array();
669
670
                // Selecting repeated ids
671
                foreach ($doc_list as $row) {
672
                    if (in_array($row['id'], array_keys($temp))) {
673
                        $my_repeat_ids[] = $row['id'];
674
                    }
675
                    $temp[$row['id']] = $row;
676
                }
677
678
                //@todo use the DocumentManager::is_visible function
679
                // Checking visibility in a session
680
                foreach ($my_repeat_ids as $id) {
681
                    foreach ($doc_list as $row) {
682
                        if ($id == $row['id']) {
683 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
684
                                $delete_repeated[$id] = true;
685
                            }
686 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
687
                                $delete_repeated[$id] = true;
688
                            }
689
                        }
690
                    }
691
                }
692
693
                foreach ($doc_list as $key => $row) {
694
                    if (in_array($row['visibility'], array('0', '2')) &&
695
                        !in_array($row['id'], $my_repeat_ids)
696
                    ) {
697
                        $ids_to_remove[] = $row['id'];
698
                        unset($doc_list[$key]);
699
                    }
700
                }
701
702
                foreach ($document_data as $row) {
703
                    if (in_array($row['id'], $ids_to_remove)) {
704
                        unset($document_data[$row['id']]);
705
                    }
706
                    if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
707
                        unset($document_data[$row['id']]);
708
                    }
709
                }
710
711
                // Checking parents visibility.
712
                $final_document_data = array();
713
                foreach ($document_data as $row) {
714
                    $is_visible = DocumentManager::check_visibility_tree(
715
                        $row['id'],
716
                        $_course['code'],
717
                        $sessionId,
718
                        api_get_user_id(),
719
                        $to_group_id
720
                    );
721
                    if ($is_visible) {
722
                        $final_document_data[$row['id']] = $row;
723
                    }
724
                }
725
            } else {
726
                $final_document_data = $document_data;
727
            }
728
729
            return $final_document_data;
730
        } else {
731
            return false;
732
        }
733
    }
734
735
    /**
736
     * Gets the paths of all folders in a course
737
     * can show all folders (except for the deleted ones) or only visible ones
738
     *
739
     * @param array $_course
740
     * @param int $to_group_id
741
     * @param boolean $can_see_invisible
742
     *
743
     * @return array with paths
744
     */
745
    public static function get_all_document_folders(
746
        $_course,
747
        $to_group_id = 0,
748
        $can_see_invisible = false,
749
        $getInvisibleList = false
750
    ) {
751
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
752
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
753
        $to_group_id = intval($to_group_id);
754
        $document_folders = array();
755
756
        $students = CourseManager::get_user_list_from_course_code(
757
            $_course['code'],
758
            api_get_session_id()
759
        );
760
761
        $sharedCondition = null;
762
763
        if (!empty($students)) {
764
            $conditionList = array();
765
            foreach ($students as $studentId => $studentInfo) {
0 ignored issues
show
Bug introduced by
The expression $students of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
766
                $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
767
            }
768
        }
769
770
        $groupCondition = " last.to_group_id = $to_group_id";
771
        if (empty($to_group_id)) {
772
            $groupCondition = " (last.to_group_id = 0 OR last.to_group_id IS NULL)";
773
        }
774
775
        if ($can_see_invisible) {
776
            // condition for the session
777
            $session_id = api_get_session_id();
778
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
779
            $show_users_condition = "";
780
            if (api_get_setting('show_users_folders') === 'false') {
781
                $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
782
            }
783
784
            if ($to_group_id <> 0) {
785
                $sql = "SELECT DISTINCT docs.id, path
786
                       FROM $TABLE_ITEMPROPERTY  AS last
787
                       INNER JOIN $TABLE_DOCUMENT  AS docs
788
                       ON (
789
                            docs.id = last.ref AND
790
                            last.tool = '" . TOOL_DOCUMENT . "' AND
791
                            last.c_id = {$_course['real_id']} AND
792
                            docs.c_id = {$_course['real_id']}
793
                       )
794
                       WHERE
795
                            docs.filetype 		= 'folder' AND
796
                            $groupCondition AND
797
                            docs.path NOT LIKE '%shared_folder%' AND
798
                            docs.path NOT LIKE '%_DELETED_%' AND
799
                            last.visibility <> 2
800
                            $condition_session ";
801
            } else {
802
                $sql = "SELECT DISTINCT docs.id, path
803
                        FROM $TABLE_ITEMPROPERTY  AS last
804
                        INNER JOIN $TABLE_DOCUMENT  AS docs
805
                        ON (
806
                            docs.id = last.ref AND
807
                            last.tool = '" . TOOL_DOCUMENT . "' AND
808
                            last.c_id = {$_course['real_id']} AND
809
                            docs.c_id = {$_course['real_id']}
810
                        )
811
                        WHERE
812
                            docs.filetype = 'folder' AND
813
                            docs.path NOT LIKE '%_DELETED_%' AND
814
                            $groupCondition AND
815
                            last.visibility <> 2
816
                            $show_users_condition $condition_session ";
817
            }
818
            $result = Database::query($sql);
819
820
            if ($result && Database::num_rows($result) != 0) {
821
                while ($row = Database::fetch_array($result, 'ASSOC')) {
822
                    if (DocumentManager::is_folder_to_avoid($row['path'])) {
823
                        continue;
824
                    }
825
826
                    if (strpos($row['path'], '/shared_folder/') !== false) {
827
                        if (!in_array($row['path'], $conditionList)) {
828
                            continue;
829
                        }
830
                    }
831
832
                    $document_folders[$row['id']] = $row['path'];
833
                }
834
835
                if (!empty($document_folders)) {
836
                    natsort($document_folders);
837
                }
838
                return $document_folders;
839
            } else {
840
                return false;
841
            }
842
        } else {
843
844
            // No invisible folders
845
            // Condition for the session
846
            $session_id = api_get_session_id();
847
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
848
849
            $visibilityCondition = 'last.visibility = 1';
850
            $fileType = "docs.filetype = 'folder' AND";
851
            if ($getInvisibleList) {
852
                $visibilityCondition = 'last.visibility = 0';
853
                $fileType = '';
854
            }
855
856
            //get visible folders
857
            $sql = "SELECT DISTINCT docs.id, path
858
                    FROM
859
                        $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
860
                    WHERE
861
                        docs.id = last.ref AND
862
                        $fileType
863
                        last.tool = '" . TOOL_DOCUMENT . "' AND
864
                        $groupCondition AND
865
                        $visibilityCondition
866
                        $condition_session AND
867
                        last.c_id = {$_course['real_id']}  AND
868
                        docs.c_id = {$_course['real_id']} ";
869
            $result = Database::query($sql);
870
871
            $visibleFolders = array();
872
            while ($row = Database::fetch_array($result, 'ASSOC')) {
873
                $visibleFolders[$row['id']] = $row['path'];
874
            }
875
876
            if ($getInvisibleList) {
877
878
                return $visibleFolders;
879
            }
880
881
            // Condition for the session
882
            $session_id = api_get_session_id();
883
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
884
            //get invisible folders
885
            $sql = "SELECT DISTINCT docs.id, path
886
                    FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
887
                    WHERE
888
                        docs.id = last.ref AND
889
                        docs.filetype = 'folder' AND
890
                        last.tool = '" . TOOL_DOCUMENT . "' AND
891
                        $groupCondition AND
892
                        last.visibility = 0 $condition_session AND
893
                        last.c_id = {$_course['real_id']} AND
894
                        docs.c_id = {$_course['real_id']} ";
895
            $result = Database::query($sql);
896
            $invisibleFolders = array();
897
            while ($row = Database::fetch_array($result, 'ASSOC')) {
898
                //condition for the session
899
                $session_id = api_get_session_id();
900
                $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
901
                //get visible folders in the invisible ones -> they are invisible too
902
                $sql = "SELECT DISTINCT docs.id, path
903
                        FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
904
                        WHERE
905
                            docs.id = last.ref AND
906
                            docs.path LIKE '" . Database::escape_string($row['path'].'/%') . "' AND
907
                            docs.filetype = 'folder' AND
908
                            last.tool = '" . TOOL_DOCUMENT . "' AND
909
                            $groupCondition AND
910
                            last.visibility = 1 $condition_session AND
911
                            last.c_id = {$_course['real_id']} AND
912
                            docs.c_id = {$_course['real_id']}  ";
913
                $folder_in_invisible_result = Database::query($sql);
914
                while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
915
                    $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
916
                }
917
            }
918
919
920
            //if both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
921
            if (is_array($visibleFolders) && is_array($invisibleFolders)) {
922
                $document_folders = array_diff($visibleFolders, $invisibleFolders);
923
                natsort($document_folders);
924
                return $document_folders;
925
            } elseif (is_array($visibleFolders)) {
926
                natsort($visibleFolders);
927
                return $visibleFolders;
928
            } else {
929
                //no visible folders found
930
                return false;
931
            }
932
        }
933
    }
934
935
    /**
936
     * This check if a document has the readonly property checked, then see if the user
937
     * is the owner of this file, if all this is true then return true.
938
     *
939
     * @param array  $_course
940
     * @param int    $user_id id of the current user
941
     * @param string $file path stored in the database (if not defined, $documentId must be used)
942
     * @param int    $document_id in case you dont have the file path ,
943
     *                insert the id of the file here and leave $file in blank ''
944
     * @param bool $to_delete
945
     * @param int $sessionId
946
     * @return boolean true/false
947
     * */
948
    public static function check_readonly(
949
        $_course,
950
        $user_id,
951
        $file = null,
952
        $document_id = '',
953
        $to_delete = false,
954
        $sessionId = null,
955
        $documentId = null
956
    ) {
957
958
        if (empty($sessionId)) {
959
            $sessionId = api_get_session_id();
960
        } else {
961
            $sessionId = intval($sessionId);
962
        }
963
964
        if (empty($document_id) || !is_numeric($document_id)) {
965
            $document_id = self::get_document_id($_course, $file, $sessionId);
966
        } else {
967
            $document_id = intval($document_id);
968
        }
969
970
        $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
971
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
972
        $course_id = $_course['real_id'];
973
974
        if ($to_delete) {
975
            if (self::is_folder($_course, $document_id)) {
0 ignored issues
show
Security Bug introduced by
It seems like $document_id defined by self::get_document_id($_course, $file, $sessionId) on line 965 can also be of type false; however, DocumentManager::is_folder() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
976
                if (!empty($file)) {
977
                    $path = Database::escape_string($file);
978
                    // Check
979
                    $sql = "SELECT td.id, readonly, tp.insert_user_id
980
                            FROM $TABLE_DOCUMENT td, $TABLE_PROPERTY tp
981
                            WHERE
982
                                td.c_id = $course_id AND
983
                                tp.c_id = $course_id AND
984
                                td.session_id = $sessionId AND
985
                                tp.ref= td.id AND
986
                                (path='" . $path . "' OR path LIKE BINARY '" . $path . "/%' ) ";
987
                    // Get all id's of documents that are deleted
988
                    $what_to_check_result = Database::query($sql);
989
990
                    if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
991
                        // file with readonly set to 1 exist?
992
                        $readonly_set = false;
993
                        while ($row = Database::fetch_array($what_to_check_result)) {
994
                            //query to delete from item_property table
995
                            if ($row['readonly'] == 1) {
996
                                if (!($row['insert_user_id'] == $user_id)) {
997
                                    $readonly_set = true;
998
                                    break;
999
                                }
1000
                            }
1001
                        }
1002
1003
                        if ($readonly_set) {
1004
                            return true;
1005
                        }
1006
                    }
1007
                }
1008
                return false;
1009
            }
1010
        }
1011
1012
        if (!empty($document_id)) {
1013
            $sql = "SELECT a.insert_user_id, b.readonly
1014
                   FROM $TABLE_PROPERTY a, $TABLE_DOCUMENT b
1015
                   WHERE
1016
            			a.c_id = $course_id AND
1017
                        b.c_id = $course_id AND
1018
            			a.ref = b.id and a.ref = $document_id LIMIT 1";
1019
            $result = Database::query($sql);
1020
            $doc_details = Database ::fetch_array($result, 'ASSOC');
1021
1022
            if ($doc_details['readonly'] == 1) {
1023
                return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
1024
            }
1025
        }
1026
        return false;
1027
    }
1028
1029
    /**
1030
     * This check if a document is a folder or not
1031
     * @param array  $_course
1032
     * @param int    $document_id of the item
1033
     * @return boolean true/false
1034
     * */
1035
    public static function is_folder($_course, $document_id)
1036
    {
1037
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1038
        $course_id = $_course['real_id'];
1039
        $document_id = intval($document_id);
1040
        $sql = "SELECT filetype FROM $TABLE_DOCUMENT
1041
                WHERE c_id = $course_id AND id= $document_id";
1042
        $result = Database::fetch_array(Database::query($sql), 'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1043
        return $result['filetype'] == 'folder';
1044
    }
1045
1046
    /**
1047
     * @param int $document_id
1048
     * @param array $course_info
1049
     * @param int $session_id
1050
     * @param bool $remove_content_from_db
1051
     */
1052
    public static function deleteDocumentFromDb(
1053
        $document_id,
1054
        $course_info = array(),
1055
        $session_id = 0,
1056
        $remove_content_from_db = false
1057
    ) {
1058
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1059
        $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
1060
1061
        // Deleting from the DB
1062
        $user_id = api_get_user_id();
1063
        $document_id = intval($document_id);
1064
1065
        if (empty($course_info)) {
1066
            $course_info = api_get_course_info();
1067
        }
1068
1069
        if (empty($session_id)) {
1070
            $session_id = api_get_session_id();
1071
        }
1072
1073
        // Soft DB delete
1074
        api_item_property_update(
1075
            $course_info,
1076
            TOOL_DOCUMENT,
1077
            $document_id,
1078
            'delete',
1079
            $user_id,
1080
            null,
1081
            null,
1082
            null,
1083
            null,
1084
            $session_id
1085
        );
1086
        self::delete_document_from_search_engine($course_info['code'], $document_id);
1087
        self::unset_document_as_template($document_id, $course_info['code'], $user_id);
1088
1089
        //Hard DB delete
1090
        if ($remove_content_from_db) {
1091
            $sql = "DELETE FROM $TABLE_ITEMPROPERTY
1092
                    WHERE
1093
                        c_id = {$course_info['real_id']} AND
1094
                        ref = ".$document_id." AND
1095
                        tool='".TOOL_DOCUMENT."'";
1096
            Database::query($sql);
1097
1098
            $sql = "DELETE FROM $TABLE_DOCUMENT
1099
                    WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
1100
            Database::query($sql);
1101
        }
1102
    }
1103
1104
    /**
1105
     * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
1106
     * Files/folders that are inside a deleted folder get visibility 2
1107
     *
1108
     * @param array $_course
1109
     * @param string $path, path stored in the database
0 ignored issues
show
Bug introduced by
There is no parameter named $path,. 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...
1110
     * @param string $base_work_dir, path to the documents folder (if not defined, $documentId must be used)
0 ignored issues
show
Documentation introduced by
There is no parameter named $base_work_dir,. Did you maybe mean $base_work_dir?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
1111
     * @param int   $sessionId The ID of the session, if any
1112
     * @param int   $documentId The document id, if available
1113
     * @param int $groupId
1114
     * @return boolean true/false
1115
     * @todo now only files/folders in a folder get visibility 2, we should rename them too.
1116
     * @todo We should be able to get rid of this later when using only documentId (check further usage)
1117
     */
1118
    public static function delete_document(
1119
        $_course,
1120
        $path = null,
1121
        $base_work_dir = null,
1122
        $sessionId = null,
1123
        $documentId = null,
1124
        $groupId = null
1125
    ) {
1126
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1127
1128
        if (empty($groupId)) {
1129
            $groupId = api_get_group_id();
1130
        } else {
1131
            $groupId = intval($groupId);
1132
        }
1133
1134
        if (empty($sessionId)) {
1135
            $sessionId = api_get_session_id();
1136
        } else {
1137
            $sessionId = intval($sessionId);
1138
        }
1139
1140
        $course_id = $_course['real_id'];
1141
1142
        if (empty($course_id)) {
1143
            return false;
1144
        }
1145
1146
        if (empty($base_work_dir)) {
1147
            return false;
1148
        }
1149
        if (empty($documentId)) {
1150
            $documentId = self::get_document_id($_course, $path, $sessionId);
1151
            $docInfo = self::get_document_data_by_id(
1152
                $documentId,
0 ignored issues
show
Security Bug introduced by
It seems like $documentId defined by self::get_document_id($_course, $path, $sessionId) on line 1150 can also be of type false; however, DocumentManager::get_document_data_by_id() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1153
                $_course['code'],
1154
                false,
1155
                $sessionId
1156
            );
1157
            $path = $docInfo['path'];
1158 View Code Duplication
        } else {
1159
            $docInfo = self::get_document_data_by_id(
1160
                $documentId,
1161
                $_course['code'],
1162
                false,
1163
                $sessionId
1164
            );
1165
            if (empty($docInfo)) {
1166
                return false;
1167
            }
1168
            $path = $docInfo['path'];
1169
        }
1170
1171
        $documentId = intval($documentId);
1172
1173
        if (empty($path) || empty($docInfo) || empty($documentId)) {
1174
            return false;
1175
        }
1176
        $itemInfo = api_get_item_property_info(
1177
            $_course['real_id'],
1178
            TOOL_DOCUMENT,
1179
            $documentId,
1180
            $sessionId
1181
        );
1182
1183
        if (empty($itemInfo)) {
1184
            return false;
1185
        }
1186
1187
        // File was already deleted.
1188
        if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
1189
            $itemInfo['lastedit_type'] == 'delete' ||
1190
            $itemInfo['visibility'] == 2
1191
        ) {
1192
            return false;
1193
        }
1194
1195
        // Filtering by group.
1196
        if ($itemInfo['to_group_id'] != $groupId) {
1197
            return false;
1198
        }
1199
1200
        $document_exists_in_disk = file_exists($base_work_dir.$path);
1201
        $new_path = $path.'_DELETED_'.$documentId;
1202
1203
        $file_deleted_from_db = false;
1204
        $file_deleted_from_disk = false;
1205
        $file_renamed_from_disk = false;
1206
1207
        if ($documentId) {
1208
            // Deleting doc from the DB.
1209
            self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1210
            // Checking
1211
            // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
1212
            $file_deleted_from_db = true;
1213
        }
1214
1215
        // Looking for children.
1216
        if ($docInfo['filetype'] == 'folder') {
1217
            $cleanPath = Database::escape_string($path);
1218
1219
            // Deleted files inside this folder.
1220
            $sql = "SELECT id FROM $TABLE_DOCUMENT
1221
                    WHERE
1222
                        c_id = $course_id AND
1223
                        session_id = $sessionId AND
1224
                        path LIKE BINARY '".$cleanPath."/%'";
1225
1226
            // Get all id's of documents that are deleted.
1227
            $result = Database::query($sql);
1228
1229
            if ($result && Database::num_rows($result) != 0) {
1230
                // Recursive delete.
1231
                while ($row = Database::fetch_array($result)) {
1232
                    self::delete_document(
1233
                        $_course,
1234
                        null,
1235
                        $base_work_dir,
1236
                        $sessionId,
1237
                        $row['id']
1238
                    );
1239
                }
1240
            }
1241
        }
1242
1243
        if ($document_exists_in_disk) {
1244
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
1245
                // Delete documents, do it like this so metadata gets deleted too
1246
                my_delete($base_work_dir.$path);
1247
                // Hard delete.
1248
                self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
1249
                $file_deleted_from_disk = true;
1250
            } else {
1251
                // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
1252
1253
                if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
1254
                    if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
1255
                        $new_path = Database::escape_string($new_path);
1256
1257
                        $sql = "UPDATE $TABLE_DOCUMENT
1258
                                SET path = '".$new_path."'
1259
                                WHERE
1260
                                    c_id = $course_id AND
1261
                                    session_id = $sessionId AND
1262
                                    id = ".$documentId;
1263
                        Database::query($sql);
1264
1265
                        // Soft delete.
1266
                        self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1267
1268
                        // Change path of sub folders and documents in database.
1269
                        $old_item_path = $docInfo['path'];
1270
                        $new_item_path = $new_path.substr($old_item_path, strlen($path));
1271
                        $new_item_path = Database::escape_string($new_item_path);
1272
1273
                        $sql = "UPDATE $TABLE_DOCUMENT
1274
                                SET path = '".$new_item_path."'
1275
                                WHERE
1276
                                    c_id = $course_id AND
1277
                                    session_id = $sessionId AND
1278
                                    id = ".$documentId;
1279
                        Database::query($sql);
1280
1281
                        $file_renamed_from_disk = true;
1282
                    } else {
1283
                        // Couldn't rename - file permissions problem?
1284
                        error_log(
1285
                            __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
1286
                            0
1287
                        );
1288
                    }
1289
                }
1290
            }
1291
        }
1292
        // Checking inconsistency
1293
        //error_log('Doc status: (1 del db :'.($file_deleted_from_db?'yes':'no').') - (2 del disk: '.($file_deleted_from_disk?'yes':'no').') - (3 ren disk: '.($file_renamed_from_disk?'yes':'no').')');
1294
        if ($file_deleted_from_db && $file_deleted_from_disk ||
1295
            $file_deleted_from_db && $file_renamed_from_disk
1296
        ) {
1297
            return true;
1298
        } else {
1299
            //Something went wrong
1300
            //The file or directory isn't there anymore (on the filesystem)
1301
            // This means it has been removed externally. To prevent a
1302
            // blocking error from happening, we drop the related items from the
1303
            // item_property and the document table.
1304
            error_log(
1305
                __FILE__.' '.__LINE__.': System inconsistency detected. The file or directory '.$base_work_dir.$path.' seems to have been removed from the filesystem independently from the web platform. To restore consistency, the elements using the same path will be removed from the database',
1306
                0
1307
            );
1308
            return false;
1309
        }
1310
    }
1311
1312
    /**
1313
     * Removes documents from search engine database
1314
     *
1315
     * @param string $course_id Course code
1316
     * @param int $document_id Document id to delete
1317
     */
1318 View Code Duplication
    public static function delete_document_from_search_engine($course_id, $document_id)
1319
    {
1320
        // remove from search engine if enabled
1321
        if (api_get_setting('search_enabled') == 'true') {
1322
            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
1323
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1324
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1325
            $res = Database::query($sql);
1326
            if (Database::num_rows($res) > 0) {
1327
                $row2 = Database::fetch_array($res);
1328
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
1329
                $di = new ChamiloIndexer();
1330
                $di->remove_document((int) $row2['search_did']);
1331
            }
1332
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1333
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1334
            Database::query($sql);
1335
1336
            // remove terms from db
1337
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
1338
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
1339
        }
1340
    }
1341
1342
    /**
1343
     * Gets the id of a document with a given path
1344
     *
1345
     * @param array $courseInfo
1346
     * @param string $path
1347
     * @param int $sessionId
1348
     * @return int id of document / false if no doc found
1349
     */
1350
    public static function get_document_id($courseInfo, $path, $sessionId = null)
1351
    {
1352
        $table = Database :: get_course_table(TABLE_DOCUMENT);
1353
        $courseId = $courseInfo['real_id'];
1354
1355
        if (!isset($sessionId)) {
1356
            $sessionId = api_get_session_id();
1357
        } else {
1358
            $sessionId = intval($sessionId);
1359
        }
1360
1361
        $path = Database::escape_string($path);
1362 View Code Duplication
        if (!empty($courseId) && !empty($path)) {
1363
            $sql = "SELECT id FROM $table
1364
                    WHERE
1365
                        c_id = $courseId AND
1366
                        path LIKE BINARY '$path' AND
1367
                        session_id = $sessionId
1368
                    LIMIT 1";
1369
1370
            $result = Database::query($sql);
1371
            if (Database::num_rows($result)) {
1372
                $row = Database::fetch_array($result);
1373
1374
                return intval($row['id']);
1375
            }
1376
        }
1377
1378
        return false;
1379
    }
1380
1381
    /**
1382
     * Gets the document data with a given id
1383
     *
1384
     * @param int $id Document Id (id field in c_document table)
1385
     * @param string $course_code Course code
1386
     * @param bool $load_parents load folder parents.
1387
     * @param int $session_id The session ID,
1388
     * 0 if requires context *out of* session, and null to use global context
1389
     * @return array document content
1390
     */
1391
    public static function get_document_data_by_id(
1392
        $id,
1393
        $course_code,
1394
        $load_parents = false,
1395
        $session_id = null
1396
    ) {
1397
        $course_info = api_get_course_info($course_code);
1398
        $course_id = $course_info['real_id'];
1399
1400
        if (empty($course_info)) {
1401
            return false;
1402
        }
1403
1404
        if (isset($session_id)) {
1405
            $session_id = intval($session_id);
1406
        } else {
1407
            $session_id = api_get_session_id();
1408
        }
1409
1410
        $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
1411
1412
        $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
1413
        $id = intval($id);
1414
        $sql = "SELECT * FROM $TABLE_DOCUMENT
1415
                WHERE c_id = $course_id AND session_id = $session_id AND id = $id";
1416
1417
        $result = Database::query($sql);
1418
        if ($result && Database::num_rows($result) == 1) {
1419
            $row = Database::fetch_array($result, 'ASSOC');
1420
1421
            //@todo need to clarify the name of the URLs not nice right now
1422
            $url_path = urlencode($row['path']);
1423
            $path = str_replace('%2F', '/', $url_path);
1424
            $pathinfo = pathinfo($row['path']);
1425
1426
            $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
1427
            $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
1428
            $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1429
            $row['absolute_path_from_document'] = '/document' . $row['path'];
1430
            $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
1431
            $row['direct_url'] = $www . $path;
1432
1433
            if (dirname($row['path']) == '.') {
1434
                $row['parent_id'] = '0';
1435
            } else {
1436
                $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
1437
            }
1438
            $parents = array();
1439
1440
            //Use to generate parents (needed for the breadcrumb)
1441
            //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
1442
1443
            if ($load_parents) {
1444
                $dir_array = explode('/', $row['path']);
1445
                $dir_array = array_filter($dir_array);
1446
                $array_len = count($dir_array) + 1;
1447
                $real_dir = '';
1448
1449
                for ($i = 1; $i < $array_len; $i++) {
1450
                    $real_dir .= '/' . $dir_array[$i];
1451
                    $parent_id = self::get_document_id($course_info, $real_dir);
1452
                    if ($session_id != 0 && empty($parent_id)) {
1453
                        $parent_id = self::get_document_id($course_info, $real_dir, 0);
1454
                    }
1455
                    if (!empty($parent_id)) {
1456
                        $sub_document_data = self::get_document_data_by_id(
1457
                            $parent_id,
1458
                            $course_code,
1459
                            false,
1460
                            $session_id
1461
                        );
1462
                        if ($session_id != 0 and !$sub_document_data) {
1463
                            $sub_document_data = self::get_document_data_by_id(
1464
                                $parent_id,
1465
                                $course_code,
1466
                                false,
1467
                                0
1468
                            );
1469
                        }
1470
                        //@todo add visibility here
1471
                        $parents[] = $sub_document_data;
1472
                    }
1473
                }
1474
            }
1475
            $row['parents'] = $parents;
1476
1477
            return $row;
1478
        }
1479
1480
        return false;
1481
    }
1482
1483
    /**
1484
     * Allow to set a specific document as a new template for CKeditor
1485
     * for a particular user in a particular course
1486
     *
1487
     * @param string $title
1488
     * @param string $description
1489
     * @param int $document_id_for_template the document id
1490
     * @param string $course_code
1491
     * @param int $user_id
1492
     * @return bool
1493
     */
1494
    public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
1495
    {
1496
        // Database table definition
1497
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1498
        $params = [
1499
            'title' => $title,
1500
            'description' => $description,
1501
            'course_code' => $course_code,
1502
            'user_id' => $user_id,
1503
            'ref_doc' => $document_id_for_template,
1504
            'image' => $image,
1505
        ];
1506
        Database::insert($table_template, $params);
1507
        return true;
1508
    }
1509
1510
    /**
1511
     * Unset a document as template
1512
     *
1513
     * @param int $document_id
1514
     * @param string $course_code
1515
     * @param int $user_id
1516
     */
1517
    public static function unset_document_as_template($document_id, $course_code, $user_id)
1518
    {
1519
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1520
        $course_code = Database::escape_string($course_code);
1521
        $user_id = intval($user_id);
1522
        $document_id = intval($document_id);
1523
1524
        $sql = 'SELECT id FROM ' . $table_template . '
1525
                WHERE
1526
                    course_code="' . $course_code . '" AND
1527
                    user_id="' . $user_id . '" AND
1528
                    ref_doc="' . $document_id . '"';
1529
        $result = Database::query($sql);
1530
        $template_id = Database::result($result, 0, 0);
1531
1532
        my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
1533
1534
        $sql = 'DELETE FROM ' . $table_template . '
1535
                WHERE
1536
                    course_code="' . $course_code . '" AND
1537
                    user_id="' . $user_id . '" AND
1538
                    ref_doc="' . $document_id . '"';
1539
1540
        Database::query($sql);
1541
    }
1542
1543
    /**
1544
     * Return true if the documentpath have visibility=1 as
1545
     * item_property (you should use the is_visible_by_id)
1546
     *
1547
     * @param string $document_path the relative complete path of the document
0 ignored issues
show
Bug introduced by
There is no parameter named $document_path. 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...
1548
     * @param array  $course the _course array info of the document's course
1549
     * @param int
1550
     * @param string
1551
     * @return bool
1552
     */
1553
    public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
1554
    {
1555
        $docTable = Database::get_course_table(TABLE_DOCUMENT);
1556
        $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
1557
1558
        $course_id = $course['real_id'];
1559
        //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
1560
1561
        $session_id = intval($session_id);
1562
        $condition = "AND d.session_id IN  ('$session_id', '0') ";
1563
        // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
1564
1565
        /*
1566
          When using hotpotatoes files, a new html files are generated
1567
          in the hotpotatoes folder to display the test.
1568
          The genuine html file is copied to math4.htm(user_id).t.html
1569
          Images files are not copied, and keep same name.
1570
          To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
1571
          In this case, we have to remove (user_id).t.html to check the visibility of the file
1572
          For images, we just check the path of the image file.
1573
1574
          Exemple of hotpotatoes folder :
1575
          A.jpg
1576
          maths4-consigne.jpg
1577
          maths4.htm
1578
          maths4.htm1.t.html
1579
          maths4.htm52.t.html
1580
          maths4.htm654.t.html
1581
          omega.jpg
1582
          theta.jpg
1583
         */
1584
1585
        if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
1586
            $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
1587
        }
1588
1589
        if (!in_array($file_type, array('file', 'folder'))) {
1590
            $file_type = 'file';
1591
        }
1592
1593
        $sql = "SELECT visibility
1594
                FROM $docTable d
1595
                INNER JOIN $propTable ip
1596
                ON (d.id = ip.ref AND d.c_id  = $course_id AND ip.c_id = $course_id)
1597
        		WHERE
1598
        		    ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
1599
        			filetype = '$file_type' AND
1600
        			locate(concat(path,'/'), '" . Database::escape_string($doc_path.'/'). "')=1
1601
                ";
1602
1603
        $result = Database::query($sql);
1604
        $is_visible = false;
1605 View Code Duplication
        if (Database::num_rows($result) > 0) {
1606
            $row = Database::fetch_array($result, 'ASSOC');
1607
            if ($row['visibility'] == 1) {
1608
                $is_visible = api_is_allowed_in_course() || api_is_platform_admin();
1609
            }
1610
        }
1611
1612
        /* improved protection of documents viewable directly through the url:
1613
            incorporates the same protections of the course at the url of
1614
            documents:
1615
            access allowed for the whole world Open, access allowed for
1616
            users registered on the platform Private access, document accessible
1617
            only to course members (see the Users list), Completely closed;
1618
            the document is only accessible to the course admin and
1619
            teaching assistants.*/
1620
        //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
1621
        return $is_visible;
1622
    }
1623
1624
    /**
1625
     * Return true if user can see a file
1626
     *
1627
     * @param   int     document id
1628
     * @param   array   course info
1629
     * @param   int
1630
     * @param   int
1631
     * @param bool
1632
     * @return  bool
1633
     */
1634
    public static function is_visible_by_id(
1635
        $doc_id,
1636
        $course_info,
1637
        $session_id,
1638
        $user_id,
1639
        $admins_can_see_everything = true
1640
    ) {
1641
        $user_in_course = false;
1642
1643
        //1. Checking the course array
1644
        if (empty($course_info)) {
1645
            $course_info = api_get_course_info();
1646
            if (empty($course_info)) {
1647
                return false;
1648
            }
1649
        }
1650
1651
        $doc_id = intval($doc_id);
1652
        $session_id = intval($session_id);
1653
1654
        //2. Course and Session visibility are handle in local.inc.php/global.inc.php
1655
        //3. Checking if user exist in course/session
1656
1657
        if ($session_id == 0) {
1658
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']) || api_is_platform_admin()
1659
            ) {
1660
                $user_in_course = true;
1661
            }
1662
            // Check if course is open then we can consider that the student is registered to the course
1663
            if (isset($course_info) &&
1664
                in_array(
1665
                    $course_info['visibility'],
1666
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
1667
                )
1668
            ) {
1669
                $user_in_course = true;
1670
            }
1671 View Code Duplication
        } else {
1672
            $user_status = SessionManager::get_user_status_in_course_session(
1673
                $user_id,
1674
                $course_info['real_id'],
1675
                $session_id
1676
            );
1677
1678
            if (in_array($user_status, array('0', '2', '6'))) {
1679
                //is true if is an student, course session teacher or coach
1680
                $user_in_course = true;
1681
            }
1682
1683
            if (api_is_platform_admin()) {
1684
                $user_in_course = true;
1685
            }
1686
        }
1687
1688
        // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
1689
1690
        if ($user_in_course) {
1691
1692
            // 4.1 Checking document visibility for a Course
1693
            if ($session_id == 0) {
1694
                $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
1695
1696
                if (isset($item_info['visibility'])) {
1697
                    // True for admins if document exists
1698
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1699
                        return true;
1700
                    }
1701
                    if ($item_info['visibility'] == 1) {
1702
                        return true;
1703
                    }
1704
                }
1705
            } else {
1706
                // 4.2 Checking document visibility for a Course in a Session
1707
                $item_info = api_get_item_property_info(
1708
                    $course_info['real_id'],
1709
                    'document',
1710
                    $doc_id,
1711
                    0
1712
                );
1713
1714
                $item_info_in_session = api_get_item_property_info(
1715
                    $course_info['real_id'],
1716
                    'document',
1717
                    $doc_id,
1718
                    $session_id
1719
                );
1720
1721
                // True for admins if document exists
1722
                if (isset($item_info['visibility'])) {
1723
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1724
                        return true;
1725
                    }
1726
                }
1727
1728
                if (isset($item_info_in_session['visibility'])) {
1729
                    if ($item_info_in_session['visibility'] == 1) {
1730
                        return true;
1731
                    }
1732
                } else {
1733
                    if ($item_info['visibility'] == 1) {
1734
                        return true;
1735
                    }
1736
                }
1737
            }
1738
        } elseif ($admins_can_see_everything && api_is_platform_admin()) {
1739
            return true;
1740
        }
1741
        return false;
1742
    }
1743
1744
    /**
1745
     * Allow attach a certificate to a course
1746
     * @param string $course_id
1747
     * @param int $document_id
1748
     * @param int $session_id
1749
     *
1750
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1751
     */
1752
    public static function attach_gradebook_certificate($course_id, $document_id, $session_id = 0)
1753
    {
1754
        $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1755
        $session_id = intval($session_id);
1756
        if (empty($session_id)) {
1757
            $session_id = api_get_session_id();
1758
        }
1759
1760 View Code Duplication
        if (empty($session_id)) {
1761
            $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
1762
        } elseif ($session_id > 0) {
1763
            $sql_session = 'AND session_id=' . intval($session_id);
1764
        } else {
1765
            $sql_session = '';
1766
        }
1767
        $sql = 'UPDATE ' . $tbl_category . ' SET document_id="' . intval($document_id) . '"
1768
                WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
1769
        Database::query($sql);
1770
    }
1771
1772
    /**
1773
     * get the document id of default certificate
1774
     * @param string $course_id
1775
     * @param int $session_id
1776
     *
1777
     * @return int The default certificate id
1778
     */
1779
    public static function get_default_certificate_id($course_id, $session_id = 0)
1780
    {
1781
        $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1782
        $session_id = intval($session_id);
1783
        if (empty($session_id)) {
1784
            $session_id = api_get_session_id();
1785
        }
1786
1787 View Code Duplication
        if (empty($session_id)) {
1788
            $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
1789
        } elseif ($session_id > 0) {
1790
            $sql_session = 'AND session_id=' . intval($session_id);
1791
        } else {
1792
            $sql_session = '';
1793
        }
1794
        $sql = 'SELECT document_id FROM ' . $tbl_category . '
1795
                WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
1796
1797
        $rs = Database::query($sql);
1798
        $num = Database::num_rows($rs);
1799
        if ($num == 0) {
1800
            return null;
1801
        }
1802
        $row = Database::fetch_array($rs);
1803
1804
        return $row['document_id'];
1805
    }
1806
1807
    /**
1808
     * allow replace user info in file html
1809
     * @param int $user_id
1810
     * @param string $course_code
1811
     * @param int $sessionId
1812
     * @param bool $is_preview
1813
     * @return string The html content of the certificate
1814
     */
1815
    public static function replace_user_info_into_html($user_id, $course_code, $sessionId, $is_preview = false)
1816
    {
1817
        $user_id = intval($user_id);
1818
        $course_info = api_get_course_info($course_code);
1819
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
1820
        $course_id = $course_info['real_id'];
1821
1822
        $document_id = self::get_default_certificate_id(
1823
            $course_code,
1824
            $sessionId
1825
        );
1826
1827
        $my_content_html = null;
1828
        if ($document_id) {
1829
            $sql = "SELECT path FROM $tbl_document
1830
                    WHERE c_id = $course_id AND id = $document_id";
1831
            $rs = Database::query($sql);
1832
            $new_content = '';
1833
            $all_user_info = array();
1834
            if (Database::num_rows($rs)) {
1835
                $row = Database::fetch_array($rs);
1836
                $filepath = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1837
                if (is_file($filepath)) {
1838
                    $my_content_html = file_get_contents($filepath);
1839
                }
1840
                $all_user_info = self::get_all_info_to_certificate($user_id, $course_code, $is_preview);
1841
1842
                $info_to_be_replaced_in_content_html = $all_user_info[0];
1843
                $info_to_replace_in_content_html = $all_user_info[1];
1844
                $new_content = str_replace(
1845
                    $info_to_be_replaced_in_content_html,
1846
                    $info_to_replace_in_content_html,
1847
                    $my_content_html
1848
                );
1849
            }
1850
1851
            return array(
1852
                'content' => $new_content,
1853
                'variables' => $all_user_info,
1854
            );
1855
        }
1856
        return array();
1857
    }
1858
1859
    /**
1860
     * Return all content to replace and all content to be replace
1861
     * @param int $user_id
1862
     * @param int $course_id
1863
     * @param bool $is_preview
1864
     * @return array
1865
     */
1866
    static function get_all_info_to_certificate($user_id, $course_id, $is_preview = false)
1867
    {
1868
        $info_list = array();
1869
        $user_id = intval($user_id);
1870
1871
        $course_info = api_get_course_info($course_id);
1872
1873
        //info portal
1874
        $organization_name = api_get_setting('Institution');
1875
        $portal_name = api_get_setting('siteName');
1876
1877
        // Extra user data information
1878
        $extra_user_info_data = UserManager::get_extra_user_data(
1879
            $user_id,
1880
            false,
1881
            false,
1882
            false,
1883
            true
1884
        );
1885
1886
        // get extra fields
1887
        $extraField = new ExtraField('user');
1888
        $extraFields = $extraField->get_all(['filter = ? AND visible = ?' => [1, 1]]);
1889
1890
        //Student information
1891
        $user_info = api_get_user_info($user_id);
1892
        $first_name = $user_info['firstname'];
1893
        $last_name = $user_info['lastname'];
1894
        $official_code = $user_info['official_code'];
1895
1896
        //Teacher information
1897
        $info_teacher_id = UserManager::get_user_id_of_course_admin_or_session_admin($course_info);
1898
        $teacher_info = api_get_user_info($info_teacher_id);
1899
        $teacher_first_name = $teacher_info['firstname'];
1900
        $teacher_last_name = $teacher_info['lastname'];
1901
1902
        // info gradebook certificate
1903
        $info_grade_certificate = UserManager::get_info_gradebook_certificate($course_id, $user_id);
1904
1905
        $date_certificate = $info_grade_certificate['created_at'];
1906
        $date_long_certificate = '';
1907
1908
        $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
1909
        if (!empty($date_certificate)) {
1910
            $date_long_certificate = api_convert_and_format_date($date_certificate);
1911
            $date_no_time = api_convert_and_format_date($date_certificate, DATE_FORMAT_LONG_NO_DAY);
1912
        }
1913
1914
        if ($is_preview) {
1915
            $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
1916
            $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
1917
        }
1918
1919
        $url = api_get_path(WEB_PATH) . 'certificates/index.php?id=' . $info_grade_certificate['id'];
1920
1921
        $externalStyleFile = api_get_path(SYS_CSS_PATH) . 'themes/' . api_get_visual_theme() . '/certificate.css';
1922
        $externalStyle = '';
1923
1924
        if (is_file($externalStyleFile)) {
1925
            $externalStyle = file_get_contents($externalStyleFile);
1926
        }
1927
1928
        //replace content
1929
        $info_to_replace_in_content_html = array(
1930
            $first_name,
1931
            $last_name,
1932
            $organization_name,
1933
            $portal_name,
1934
            $teacher_first_name,
1935
            $teacher_last_name,
1936
            $official_code,
1937
            $date_long_certificate,
1938
            $date_no_time,
1939
            $course_id,
1940
            $course_info['name'],
1941
            $info_grade_certificate['grade'],
1942
            $url,
1943
            '<a href="' . $url . '" target="_blank">' . get_lang('CertificateOnlineLink') . '</a>',
1944
            '((certificate_barcode))',
1945
            $externalStyle
1946
        );
1947
1948
        $info_to_be_replaced_in_content_html = array('((user_firstname))',
1949
            '((user_lastname))',
1950
            '((gradebook_institution))',
1951
            '((gradebook_sitename))',
1952
            '((teacher_firstname))',
1953
            '((teacher_lastname))',
1954
            '((official_code))',
1955
            '((date_certificate))',
1956
            '((date_certificate_no_time))',
1957
            '((course_code))',
1958
            '((course_title))',
1959
            '((gradebook_grade))',
1960
            '((certificate_link))',
1961
            '((certificate_link_html))',
1962
            '((certificate_barcode))',
1963
            '((external_style))'
1964
        );
1965
1966
        if (!empty($extraFields)) {
1967
            foreach ($extraFields as $extraField) {
1968
                $valueExtra = isset($extra_user_info_data[$extraField['variable']]) ? $extra_user_info_data[$extraField['variable']] : '';
1969
                $info_to_be_replaced_in_content_html[] = '((' . strtolower($extraField['variable']) . '))';
1970
                $info_to_replace_in_content_html[] = $valueExtra;
1971
            }
1972
        }
1973
1974
        $info_list[] = $info_to_be_replaced_in_content_html;
1975
        $info_list[] = $info_to_replace_in_content_html;
1976
1977
        return $info_list;
1978
    }
1979
1980
    /**
1981
     * Remove default certificate
1982
     * @param string $course_id The course code
1983
     * @param int $default_certificate_id The document id of the default certificate
1984
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1985
     */
1986
    public static function remove_attach_certificate($course_id, $default_certificate_id)
1987
    {
1988
        if (empty($default_certificate_id)) {
1989
            return false;
1990
        }
1991
1992
        $default_certificate = self::get_default_certificate_id($course_id);
1993
        if ((int) $default_certificate == (int) $default_certificate_id) {
1994
            $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1995
            $session_id = api_get_session_id();
1996 View Code Duplication
            if ($session_id == 0 || is_null($session_id)) {
1997
                $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
1998
            } elseif ($session_id > 0) {
1999
                $sql_session = 'AND session_id=' . intval($session_id);
2000
            } else {
2001
                $sql_session = '';
2002
            }
2003
2004
            $sql = 'UPDATE ' . $tbl_category . ' SET document_id=null
2005
                    WHERE
2006
                        course_code = "' . Database::escape_string($course_id) . '" AND
2007
                        document_id="' . $default_certificate_id . '" ' . $sql_session;
2008
            Database::query($sql);
2009
        }
2010
    }
2011
2012
    /**
2013
     * Create directory certificate
2014
     * @param string $courseCode
2015
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2016
     */
2017
    public static function create_directory_certificate_in_course($courseCode)
2018
    {
2019
        $courseInfo = api_get_course_info($courseCode);
2020
        if (!empty($courseInfo)) {
2021
            $to_group_id = 0;
2022
            $to_user_id = null;
2023
            $course_dir = $courseInfo['path'] . "/document/";
2024
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
2025
            $base_work_dir = $sys_course_path . $course_dir;
2026
            $base_work_dir_test = $base_work_dir . 'certificates';
2027
            $dir_name = '/certificates';
2028
            $post_dir_name = get_lang('CertificatesFiles');
2029
            $visibility_command = 'invisible';
2030
2031
            $id = self::get_document_id_of_directory_certificate();
2032
2033
            if (empty($id)) {
2034
2035
                create_unexisting_directory(
2036
                    $courseInfo,
2037
                    api_get_user_id(),
2038
                    api_get_session_id(),
2039
                    $to_group_id,
2040
                    $to_user_id,
2041
                    $base_work_dir,
2042
                    $dir_name,
2043
                    $post_dir_name,
2044
                    null,
2045
                    false
2046
                );
2047
2048
                $id = self::get_document_id_of_directory_certificate();
2049
2050
                if (empty($id)) {
2051
2052
                    $id = add_document(
2053
                        $courseInfo,
2054
                        $dir_name,
2055
                        'folder',
2056
                        0,
2057
                        $post_dir_name,
2058
                        null,
2059
                        0,
2060
                        true,
2061
                        $to_group_id
2062
                    );
2063
                }
2064
2065
                if (!empty($id)) {
2066
                    api_item_property_update(
2067
                        $courseInfo,
2068
                        TOOL_DOCUMENT,
2069
                        $id,
2070
                        $visibility_command,
2071
                        api_get_user_id()
2072
                    );
2073
                }
2074
            }
2075
        }
2076
    }
2077
2078
    /**
2079
     * Get the document id of the directory certificate
2080
     * @return int The document id of the directory certificate
2081
     */
2082
    public static function get_document_id_of_directory_certificate()
2083
    {
2084
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
2085
        $course_id = api_get_course_int_id();
2086
        $sql = "SELECT id FROM $tbl_document WHERE c_id = $course_id AND path='/certificates' ";
2087
        $rs = Database::query($sql);
2088
        $row = Database::fetch_array($rs);
2089
        return $row['id'];
2090
    }
2091
2092
    /**
2093
     * Check if a directory given is for certificate
2094
     * @param string $dir path of directory
2095
     * @return bool  true if is a certificate or false otherwise
2096
     */
2097
    public static function is_certificate_mode($dir)
2098
    {
2099
        // I'm in the certification module?
2100
        $is_certificate_mode = false;
2101
        $is_certificate_array = explode('/', $dir);
2102
        array_shift($is_certificate_array);
2103
        if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
2104
            $is_certificate_mode = true;
2105
        }
2106
        return $is_certificate_mode;
2107
    }
2108
2109
    /**
2110
     * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
2111
     * This allows for a better SCORM export or replace urls inside content html from copy course
2112
     * The list will generally include pictures, flash objects, java applets, or any other
2113
     * stuff included in the source of the current item. The current item is expected
2114
     * to be an HTML file or string html. If it is not, then the function will return and empty list.
2115
     * @param	string  source html (content or path)
2116
     * @param	bool  	is file or string html
2117
     * @param	string	type (one of the app tools) - optional (otherwise takes the current item's type)
2118
     * @param	int		level of recursivity we're in
2119
     * @return	array	List of file paths. An additional field containing 'local' or 'remote' helps determine
2120
     * if the file should be copied into the zip or just linked
2121
     */
2122
    public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
2123
    {
2124
        $max = 5;
2125
        $attributes = array();
2126
        $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars');
2127
        $explode_attributes = array('flashvars' => 'file');
2128
        $abs_path = '';
2129
2130
        if ($recursivity > $max) {
2131
            return array();
2132
        }
2133
2134
        if (!isset($type)) {
2135
            $type = TOOL_DOCUMENT;
2136
        }
2137
2138
        if (!$is_file) {
2139
            $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
2140
        } else {
2141
            if (is_file($source_html)) {
2142
                $abs_path = $source_html;
2143
                //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
2144
                $info = pathinfo($abs_path);
2145
                $ext = $info['extension'];
2146
                switch (strtolower($ext)) {
2147
                    case 'html':
2148
                    case 'htm':
2149
                    case 'shtml':
2150
                    case 'css':
2151
                        $file_content = file_get_contents($abs_path);
2152
                        //get an array of attributes from the HTML source
2153
                        $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
2154
                        break;
2155
                    default:
2156
                        break;
2157
                }
2158
            } else {
2159
                return false;
2160
            }
2161
        }
2162
2163
        $files_list = array();
2164
2165
        switch ($type) {
2166
            case TOOL_DOCUMENT:
2167
            case TOOL_QUIZ:
2168
            case 'sco':
2169
                foreach ($wanted_attributes as $attr) {
2170
                    if (isset($attributes[$attr])) {
2171
                        //find which kind of path these are (local or remote)
2172
                        $sources = $attributes[$attr];
2173
                        foreach ($sources as $source) {
2174
                            //skip what is obviously not a resource
2175
                            if (strpos($source, '+this.')) {
2176
                                continue; //javascript code - will still work unaltered
2177
                            }
2178
                            if (strpos($source, '.') === false) {
2179
                                continue; //no dot, should not be an external file anyway
2180
                            }
2181
                            if (strpos($source, 'mailto:')) {
2182
                                continue; //mailto link
2183
                            }
2184
                            if (strpos($source, ';') && !strpos($source, '&amp;')) {
2185
                                continue; //avoid code - that should help
2186
                            }
2187
2188 View Code Duplication
                            if ($attr == 'value') {
2189
                                if (strpos($source, 'mp3file')) {
2190
                                    $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
2191
                                    $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
2192
                                    if (substr($mp3file, 0, 1) == '/') {
2193
                                        $files_list[] = array($mp3file, 'local', 'abs');
2194
                                    } else {
2195
                                        $files_list[] = array($mp3file, 'local', 'rel');
2196
                                    }
2197
                                } elseif (strpos($source, 'flv=') === 0) {
2198
                                    $source = substr($source, 4);
2199
                                    if (strpos($source, '&') > 0) {
2200
                                        $source = substr($source, 0, strpos($source, '&'));
2201
                                    }
2202
                                    if (strpos($source, '://') > 0) {
2203
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2204
                                            //we found the current portal url
2205
                                            $files_list[] = array($source, 'local', 'url');
2206
                                        } else {
2207
                                            //we didn't find any trace of current portal
2208
                                            $files_list[] = array($source, 'remote', 'url');
2209
                                        }
2210
                                    } else {
2211
                                        $files_list[] = array($source, 'local', 'abs');
2212
                                    }
2213
                                    /* skipping anything else to avoid two entries
2214
                                    (while the others can have sub-files in their url, flv's can't)*/
2215
                                    continue;
2216
                                }
2217
                            }
2218
                            if (strpos($source, '://') > 0) {
2219
                                //cut at '?' in a URL with params
2220
                                if (strpos($source, '?') > 0) {
2221
                                    $second_part = substr($source, strpos($source, '?'));
2222
                                    if (strpos($second_part, '://') > 0) {
2223
                                        //if the second part of the url contains a url too, treat the second one before cutting
2224
                                        $pos1 = strpos($second_part, '=');
2225
                                        $pos2 = strpos($second_part, '&');
2226
                                        $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
2227 View Code Duplication
                                        if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
2228
                                            //we found the current portal url
2229
                                            $files_list[] = array($second_part, 'local', 'url');
2230
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2231
                                            if (count($in_files_list) > 0) {
2232
                                                $files_list = array_merge($files_list, $in_files_list);
2233
                                            }
2234
                                        } else {
2235
                                            //we didn't find any trace of current portal
2236
                                            $files_list[] = array($second_part, 'remote', 'url');
2237
                                        }
2238 View Code Duplication
                                    } elseif (strpos($second_part, '=') > 0) {
2239
                                        if (substr($second_part, 0, 1) === '/') {
2240
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2241
                                            $files_list[] = array($second_part, 'local', 'abs');
2242
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2243
                                            if (count($in_files_list) > 0) {
2244
                                                $files_list = array_merge($files_list, $in_files_list);
2245
                                            }
2246
                                        } elseif (strstr($second_part, '..') === 0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strstr($second_part, '..') (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
2247
                                            //link is relative but going back in the hierarchy
2248
                                            $files_list[] = array($second_part, 'local', 'rel');
2249
                                            //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
2250
                                            //$new_abs_path = realpath($dir.'/'.$second_part);
2251
                                            $dir = '';
2252
                                            if (!empty($abs_path)) {
2253
                                                $dir = dirname($abs_path) . '/';
2254
                                            }
2255
                                            $new_abs_path = realpath($dir . $second_part);
2256
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2257
                                            if (count($in_files_list) > 0) {
2258
                                                $files_list = array_merge($files_list, $in_files_list);
2259
                                            }
2260
                                        } else {
2261
                                            //no starting '/', making it relative to current document's path
2262
                                            if (substr($second_part, 0, 2) == './') {
2263
                                                $second_part = substr($second_part, 2);
2264
                                            }
2265
                                            $files_list[] = array($second_part, 'local', 'rel');
2266
                                            $dir = '';
2267
                                            if (!empty($abs_path)) {
2268
                                                $dir = dirname($abs_path) . '/';
2269
                                            }
2270
                                            $new_abs_path = realpath($dir . $second_part);
2271
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2272
                                            if (count($in_files_list) > 0) {
2273
                                                $files_list = array_merge($files_list, $in_files_list);
2274
                                            }
2275
                                        }
2276
                                    }
2277
                                    //leave that second part behind now
2278
                                    $source = substr($source, 0, strpos($source, '?'));
2279
                                    if (strpos($source, '://') > 0) {
2280 View Code Duplication
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2281
                                            //we found the current portal url
2282
                                            $files_list[] = array($source, 'local', 'url');
2283
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2284
                                            if (count($in_files_list) > 0) {
2285
                                                $files_list = array_merge($files_list, $in_files_list);
2286
                                            }
2287
                                        } else {
2288
                                            //we didn't find any trace of current portal
2289
                                            $files_list[] = array($source, 'remote', 'url');
2290
                                        }
2291 View Code Duplication
                                    } else {
2292
                                        //no protocol found, make link local
2293
                                        if (substr($source, 0, 1) === '/') {
2294
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2295
                                            $files_list[] = array($source, 'local', 'abs');
2296
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2297
                                            if (count($in_files_list) > 0) {
2298
                                                $files_list = array_merge($files_list, $in_files_list);
2299
                                            }
2300
                                        } elseif (strstr($source, '..') === 0) { //link is relative but going back in the hierarchy
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strstr($source, '..') (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
2301
                                            $files_list[] = array($source, 'local', 'rel');
2302
                                            $dir = '';
2303
                                            if (!empty($abs_path)) {
2304
                                                $dir = dirname($abs_path) . '/';
2305
                                            }
2306
                                            $new_abs_path = realpath($dir . $source);
2307
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2308
                                            if (count($in_files_list) > 0) {
2309
                                                $files_list = array_merge($files_list, $in_files_list);
2310
                                            }
2311
                                        } else {
2312
                                            //no starting '/', making it relative to current document's path
2313
                                            if (substr($source, 0, 2) == './') {
2314
                                                $source = substr($source, 2);
2315
                                            }
2316
                                            $files_list[] = array($source, 'local', 'rel');
2317
                                            $dir = '';
2318
                                            if (!empty($abs_path)) {
2319
                                                $dir = dirname($abs_path) . '/';
2320
                                            }
2321
                                            $new_abs_path = realpath($dir . $source);
2322
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2323
                                            if (count($in_files_list) > 0) {
2324
                                                $files_list = array_merge($files_list, $in_files_list);
2325
                                            }
2326
                                        }
2327
                                    }
2328
                                }
2329
                                //found some protocol there
2330 View Code Duplication
                                if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2331
                                    //we found the current portal url
2332
                                    $files_list[] = array($source, 'local', 'url');
2333
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2334
                                    if (count($in_files_list) > 0) {
2335
                                        $files_list = array_merge($files_list, $in_files_list);
2336
                                    }
2337
                                } else {
2338
                                    //we didn't find any trace of current portal
2339
                                    $files_list[] = array($source, 'remote', 'url');
2340
                                }
2341 View Code Duplication
                            } else {
2342
                                //no protocol found, make link local
2343
                                if (substr($source, 0, 1) === '/') {
2344
                                    //link starts with a /, making it absolute (relative to DocumentRoot)
2345
                                    $files_list[] = array($source, 'local', 'abs');
2346
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2347
                                    if (count($in_files_list) > 0) {
2348
                                        $files_list = array_merge($files_list, $in_files_list);
2349
                                    }
2350
                                } elseif (strpos($source, '..') === 0) {
2351
                                    //link is relative but going back in the hierarchy
2352
                                    $files_list[] = array($source, 'local', 'rel');
2353
                                    $dir = '';
2354
                                    if (!empty($abs_path)) {
2355
                                        $dir = dirname($abs_path) . '/';
2356
                                    }
2357
                                    $new_abs_path = realpath($dir . $source);
2358
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2359
                                    if (count($in_files_list) > 0) {
2360
                                        $files_list = array_merge($files_list, $in_files_list);
2361
                                    }
2362
                                } else {
2363
                                    //no starting '/', making it relative to current document's path
2364
                                    if (substr($source, 0, 2) == './') {
2365
                                        $source = substr($source, 2);
2366
                                    }
2367
                                    $files_list[] = array($source, 'local', 'rel');
2368
                                    $dir = '';
2369
                                    if (!empty($abs_path)) {
2370
                                        $dir = dirname($abs_path) . '/';
2371
                                    }
2372
                                    $new_abs_path = realpath($dir . $source);
2373
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2374
                                    if (count($in_files_list) > 0) {
2375
                                        $files_list = array_merge($files_list, $in_files_list);
2376
                                    }
2377
                                }
2378
                            }
2379
                        }
2380
                    }
2381
                }
2382
                break;
2383
            default: //ignore
2384
                break;
2385
        }
2386
2387
        $checked_files_list = array();
2388
        $checked_array_list = array();
2389
2390
        if (count($files_list) > 0) {
2391 View Code Duplication
            foreach ($files_list as $idx => $file) {
2392
                if (!empty($file[0])) {
2393
                    if (!in_array($file[0], $checked_files_list)) {
2394
                        $checked_files_list[] = $files_list[$idx][0];
2395
                        $checked_array_list[] = $files_list[$idx];
2396
                    }
2397
                }
2398
            }
2399
        }
2400
        return $checked_array_list;
2401
    }
2402
2403
    /**
2404
     * Parses the HTML attributes given as string.
2405
     *
2406
     * @param    string  HTML attribute string
2407
     * @param	 array	 List of attributes that we want to get back
2408
     * @param    array
2409
     * @return   array   An associative array of attributes
2410
     * @author 	 Based on a function from the HTML_Common2 PEAR module     *
2411
     */
2412
    public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
2413
    {
2414
        $attributes = array();
2415
        $regs = array();
2416
        $reduced = false;
2417
        if (count($wanted) > 0) {
2418
            $reduced = true;
2419
        }
2420
        try {
2421
            //Find all occurences of something that looks like a URL
2422
            // The structure of this regexp is:
2423
            // (find protocol) then
2424
            // (optionally find some kind of space 1 or more times) then
2425
            // find (either an equal sign or a bracket) followed by an optional space
2426
            // followed by some text without quotes (between quotes itself or not)
2427
            // then possible closing brackets if we were in the opening bracket case
2428
            // OR something like @import()
2429
            $res = preg_match_all(
2430
                '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
2431
                // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
2432
                // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
2433
                '([ \n\t\r]+)?(' .
2434
                // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
2435
                '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
2436
                '|' .
2437
                // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
2438
                '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
2439
                '))' .
2440
                '|' .
2441
                // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
2442
                '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
2443
                $attrString,
2444
                $regs
2445
            );
2446
        } catch (Exception $e) {
2447
            error_log('Caught exception: ' . $e->getMessage(), 0);
2448
        }
2449
        if ($res) {
2450
            for ($i = 0; $i < count($regs[1]); $i++) {
2451
                $name = trim($regs[3][$i]);
2452
                $check = trim($regs[0][$i]);
2453
                $value = trim($regs[10][$i]);
2454 View Code Duplication
                if (empty($value) and !empty($regs[13][$i])) {
2455
                    $value = $regs[13][$i];
2456
                }
2457 View Code Duplication
                if (empty($name) && !empty($regs[16][$i])) {
2458
                    $name = '@import';
2459
                    $value = trim($regs[16][$i]);
2460
                }
2461
                if (!empty($name)) {
2462
                    if (!$reduced OR in_array(strtolower($name), $wanted)) {
2463
                        if ($name == $check) {
2464
                            $attributes[strtolower($name)][] = strtolower($name);
2465
                        } else {
2466 View Code Duplication
                            if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
2467
                                $value = substr($value, 1, -1);
2468
                            }
2469
2470
                            if ($value == 'API.LMSGetValue(name') {
2471
                                $value = 'API.LMSGetValue(name)';
2472
                            }
2473
                            //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
2474
                            if (isset($explode_variables[$name])) {
2475
                                $value_modified = str_replace('&amp;', '&', $value);
2476
                                $value_array = explode('&', $value_modified);
2477
                                foreach ($value_array as $item) {
2478
                                    list($key, $item_value) = explode('=', $item);
2479
                                    if ($key == $explode_variables[$name]) {
2480
                                        $attributes[strtolower($name)][] = $item_value;
2481
                                    }
2482
                                }
2483
                            }
2484
                            $attributes[strtolower($name)][] = $value;
2485
                        }
2486
                    }
2487
                }
2488
            }
2489
        }
2490
2491
        return $attributes;
2492
    }
2493
2494
    /**
2495
     * Replace urls inside content html from a copy course
2496
     * @param string $content_html
2497
     * @param string $origin_course_code
2498
     * @param string $destination_course_directory
2499
     * @param string $origin_course_path_from_zip
2500
     * @param string $origin_course_info_path
2501
     *
2502
     * @return string	new content html with replaced urls or return false if content is not a string
2503
     */
2504
    static function replace_urls_inside_content_html_from_copy_course(
2505
        $content_html,
2506
        $origin_course_code,
2507
        $destination_course_directory,
2508
        $origin_course_path_from_zip = null,
2509
        $origin_course_info_path = null
2510
    ) {
2511
        if (empty($content_html)) {
2512
            return false;
2513
        }
2514
2515
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2516
        $orig_course_info = api_get_course_info($origin_course_code);
2517
2518
        // Course does not exist in the current DB probably this came from a zip file?
2519
        if (empty($orig_course_info)) {
2520
            if (!empty($origin_course_path_from_zip)) {
2521
                $orig_course_path = $origin_course_path_from_zip.'/';
2522
                $orig_course_info_path = $origin_course_info_path;
2523
            }
2524
        } else {
2525
            $orig_course_path = api_get_path(SYS_COURSE_PATH).$orig_course_info['path'] . '/';
2526
            $orig_course_info_path = $orig_course_info['path'];
2527
        }
2528
2529
        $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
2530
        $destination_course_info = api_get_course_info($destination_course_code);
2531
        $dest_course_path = api_get_path(SYS_COURSE_PATH) . $destination_course_directory . '/';
2532
        $dest_course_path_rel = api_get_path(REL_COURSE_PATH) . $destination_course_directory . '/';
2533
2534
        $user_id = api_get_user_id();
2535
2536
        if (!empty($orig_source_html)) {
2537
            foreach ($orig_source_html as $source) {
2538
2539
                // Get information about source url
2540
                $real_orig_url = $source[0]; // url
2541
                $scope_url = $source[1];   // scope (local, remote)
2542
                $type_url = $source[2]; // type (rel, abs, url)
2543
2544
                // Get path and query from origin url
2545
                $orig_parse_url = parse_url($real_orig_url);
2546
                $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
2547
                $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
2548
2549
                // Replace origin course code by destination course code from origin url query
2550
                $dest_url_query = '';
2551
2552
                if (!empty($real_orig_query)) {
2553
                    $dest_url_query = '?' . $real_orig_query;
2554
                    if (strpos($dest_url_query, $origin_course_code) !== false) {
2555
                        $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2556
                    }
2557
                }
2558
2559
                if ($scope_url == 'local') {
2560
                    if ($type_url == 'abs' || $type_url == 'rel') {
2561
                        $document_file = strstr($real_orig_path, 'document');
2562
2563
                        if (strpos($real_orig_path, $document_file) !== false) {
2564
                            $origin_filepath = $orig_course_path.$document_file;
2565
                            $destination_filepath = $dest_course_path.$document_file;
2566
2567
                            // copy origin file inside destination course
2568
                            if (file_exists($origin_filepath)) {
2569
                                $filepath_dir = dirname($destination_filepath);
2570
2571 View Code Duplication
                                if (!is_dir($filepath_dir)) {
2572
                                    $perm = api_get_permissions_for_new_directories();
2573
                                    $result = @mkdir($filepath_dir, $perm, true);
2574
                                    if ($result) {
2575
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
2576
2577
                                        //Add to item properties to the new folder
2578
                                        $doc_id = add_document(
2579
                                            $destination_course_info,
2580
                                            $filepath_to_add,
2581
                                            'folder',
2582
                                            0,
2583
                                            basename($filepath_to_add)
2584
                                        );
2585
                                        api_item_property_update(
2586
                                            $destination_course_info,
2587
                                            TOOL_DOCUMENT,
2588
                                            $doc_id,
2589
                                            'FolderCreated',
2590
                                            $user_id,
2591
                                            null,
2592
                                            null,
2593
                                            null,
2594
                                            null
2595
                                        );
2596
                                    }
2597
                                }
2598
2599 View Code Duplication
                                if (!file_exists($destination_filepath)) {
2600
                                    $result = @copy($origin_filepath, $destination_filepath);
2601
                                    if ($result) {
2602
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
2603
                                        $size = filesize($destination_filepath);
2604
2605
                                        // Add to item properties to the file
2606
                                        $doc_id = add_document(
2607
                                            $destination_course_info,
2608
                                            $filepath_to_add,
2609
                                            'file',
2610
                                            $size,
2611
                                            basename($filepath_to_add)
2612
                                        );
2613
                                        api_item_property_update(
2614
                                            $destination_course_info,
2615
                                            TOOL_DOCUMENT,
2616
                                            $doc_id,
2617
                                            'FolderCreated',
2618
                                            $user_id,
2619
                                            null,
2620
                                            null,
2621
                                            null,
2622
                                            null
2623
                                        );
2624
                                    }
2625
                                }
2626
                            }
2627
2628
                            // Replace origin course path by destination course path.
2629
                            if (strpos($content_html, $real_orig_url) !== false) {
2630
                                $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
2631
2632
                                //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
2633
                                // See BT#7780
2634
                                $destination_url = $dest_course_path_rel . $document_file . $dest_url_query;
2635
2636
                                // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
2637
                                if (strpos($real_orig_path, $origin_course_code) === false) {
2638
                                    $url_course_path = $real_orig_path;
2639
                                    $destination_url = $real_orig_path;
2640
                                }
2641
                                $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2642
                            }
2643
                        }
2644
2645
                        // replace origin course code by destination course code  from origin url
2646
                        if (strpos($real_orig_url, '?') === 0) {
2647
                            $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
2648
                            $content_html = str_replace($real_orig_url, $dest_url, $content_html);
2649
                        }
2650
                    }
2651
                }
2652
            }
2653
        }
2654
2655
        return $content_html;
2656
    }
2657
2658
    /**
2659
     * Replace urls inside content html when moving a file
2660
     * @todo this code is only called in document.php but is commented
2661
     * @param string     content html
2662
     * @param string     origin
2663
     * @param string     destination
2664
     * @return string    new content html with replaced urls or return false if content is not a string
2665
     */
2666
    function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
2667
    {
2668 View Code Duplication
        if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
2669
            $original = $original_path . $file_name;
2670
        } else {
2671
            $original = $original_path . '/' . $file_name;
2672
        }
2673 View Code Duplication
        if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
2674
            $destination = $destiny_path . $file_name;
2675
        } else {
2676
            $destination = $destiny_path . '/' . $file_name;
2677
        }
2678
        $original_count = count(explode('/', $original));
2679
        $destination_count = count(explode('/', $destination));
2680
        if ($original_count == $destination_count) {
2681
            //Nothing to change
2682
            return true;
2683
        }
2684
        if ($original_count > $destination_count) {
2685
            $mode = 'outside';
2686
        } else {
2687
            $mode = 'inside';
2688
        }
2689
        //We do not select the $original_path becayse the file was already moved
2690
        $content_html = file_get_contents($destiny_path . '/' . $file_name);
2691
        $destination_file = $destiny_path . '/' . $file_name;
2692
2693
        $pre_original = strstr($original_path, 'document');
2694
        $pre_destin = strstr($destiny_path, 'document');
2695
        $pre_original = substr($pre_original, 8, strlen($pre_original));
2696
        $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
2697
2698
        $levels = count(explode('/', $pre_destin)) - 1;
2699
        $link_to_add = '';
2700
        for ($i = 1; $i <= $levels; $i++) {
2701
            $link_to_add .= '../';
2702
        }
2703
2704
        if ($pre_original == '/') {
2705
            $pre_original = '';
2706
        }
2707
2708
        if ($pre_destin == '/') {
2709
            $pre_destin = '';
2710
        }
2711
2712
        if ($pre_original != '') {
2713
            $pre_original = '..' . $pre_original . '/';
2714
        }
2715
2716
        if ($pre_destin != '') {
2717
            $pre_destin = '..' . $pre_destin . '/';
2718
        }
2719
2720
        $levels = explode('/', $pre_original);
2721
        $count_pre_destination_levels = 0;
2722
        foreach ($levels as $item) {
2723
            if (!empty($item) && $item != '..') {
2724
                $count_pre_destination_levels++;
2725
            }
2726
        }
2727
        $count_pre_destination_levels--;
2728
        //$count_pre_destination_levels = count() - 3;
2729
        if ($count_pre_destination_levels == 0) {
2730
            $count_pre_destination_levels = 1;
2731
        }
2732
        //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
2733
        $pre_remove = '';
2734
        for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
2735
            $pre_remove .='..\/';
2736
        }
2737
2738
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2739
2740
        foreach ($orig_source_html as $source) {
0 ignored issues
show
Bug introduced by
The expression $orig_source_html of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2741
2742
            // get information about source url
2743
            $real_orig_url = $source[0];   // url
2744
            $scope_url = $source[1];   // scope (local, remote)
2745
            $type_url = $source[2];   // tyle (rel, abs, url)
2746
            // Get path and query from origin url
2747
            $orig_parse_url = parse_url($real_orig_url);
2748
            $real_orig_path = $orig_parse_url['path'];
2749
            $real_orig_query = $orig_parse_url['query'];
2750
2751
            // Replace origin course code by destination course code from origin url query
2752
            /*
2753
              $dest_url_query = '';
2754
              if (!empty($real_orig_query)) {
2755
              $dest_url_query = '?'.$real_orig_query;
2756
              if (strpos($dest_url_query,$origin_course_code) !== false) {
2757
              $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2758
              }
2759
              } */
2760
2761
            if ($scope_url == 'local') {
2762
                if ($type_url == 'abs' || $type_url == 'rel') {
2763
                    $document_file = strstr($real_orig_path, 'document');
2764
2765
                    if (strpos($real_orig_path, $document_file) !== false) {
2766
                        echo 'continue1';
2767
                        continue;
2768
                    } else {
2769
                        $real_orig_url_temp = '';
2770
                        if ($mode == 'inside') {
2771
                            $real_orig_url_temp = str_replace('../', '', $real_orig_url);
2772
                            $destination_url = $link_to_add . $real_orig_url_temp;
2773
                        } else {
2774
                            $real_orig_url_temp = $real_orig_url;
2775
2776
                            $destination_url = preg_replace("/" . $pre_remove . "/", '', $real_orig_url, 1);
2777
                        }
2778
                        if ($real_orig_url == $destination_url) {
2779
                            //echo 'continue2';
2780
                            continue;
2781
                        }
2782
                        $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2783
                    }
2784
                } else {
2785
                    echo 'continue3';
2786
                    continue;
2787
                }
2788
            }
2789
        }
2790
        $return = file_put_contents($destination, $content_html);
2791
        return $return;
2792
    }
2793
2794
    /**
2795
     * @param int $document_id
2796
     * @param string $course_code
2797
     */
2798
    public static function export_to_pdf($document_id, $course_code)
2799
    {
2800
        $course_data = api_get_course_info($course_code);
2801
        $document_data = self::get_document_data_by_id($document_id, $course_code);
2802
        $file_path = api_get_path(SYS_COURSE_PATH) . $course_data['path'] . '/document' . $document_data['path'];
2803
        $pdf = new PDF('A4-L', 'L');
2804
        $pdf->html_to_pdf($file_path, $document_data['title'], $course_code);
2805
    }
2806
2807
    /**
2808
     * Uploads a document
2809
     *
2810
     * @param array $files the $_FILES variable
2811
     * @param string $path
2812
     * @param string $title
2813
     * @param string $comment
2814
     * @param int $unzip unzip or not the file
2815
     * @param string $if_exists overwrite, rename or warn (default)
2816
     * @param bool $index_document index document (search xapian module)
2817
     * @param bool $show_output print html messages
2818
     * @return array|bool
2819
     */
2820
    public static function upload_document(
2821
        $files,
2822
        $path,
2823
        $title = null,
2824
        $comment = null,
2825
        $unzip = 0,
2826
        $if_exists = null,
2827
        $index_document = false,
2828
        $show_output = false,
2829
        $fileKey = 'file'
2830
    ) {
2831
        $course_info = api_get_course_info();
2832
        $sessionId = api_get_session_id();
2833
        $course_dir = $course_info['path'] . '/document';
2834
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
2835
        $base_work_dir = $sys_course_path . $course_dir;
2836
2837
        if (isset($files[$fileKey])) {
2838
            $upload_ok = process_uploaded_file($files[$fileKey], $show_output);
2839
2840
            if ($upload_ok) {
2841
                $new_path = handle_uploaded_document(
2842
                    $course_info,
2843
                    $files[$fileKey],
2844
                    $base_work_dir,
2845
                    $path,
2846
                    api_get_user_id(),
2847
                    api_get_group_id(),
2848
                    null,
2849
                    $unzip,
2850
                    $if_exists,
2851
                    $show_output,
2852
                    false,
2853
                    null,
2854
                    $sessionId
2855
                );
2856
2857
                if ($new_path) {
2858
                    $documentId = DocumentManager::get_document_id(
2859
                        $course_info,
2860
                        $new_path,
0 ignored issues
show
Bug introduced by
It seems like $new_path defined by handle_uploaded_document...alse, null, $sessionId) on line 2841 can also be of type boolean; however, DocumentManager::get_document_id() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2861
                        $sessionId
2862
                    );
2863
2864
                    if (!empty($documentId)) {
2865
                        $table_document = Database::get_course_table(TABLE_DOCUMENT);
2866
                        $params = array();
2867
                        /*if ($if_exists == 'rename') {
2868
                            // Remove prefix
2869
                            $suffix = DocumentManager::getDocumentSuffix(
2870
                                $course_info,
2871
                                $sessionId,
2872
                                api_get_group_id()
2873
                            );
2874
                            $new_path = basename($new_path);
2875
                            $new_path = str_replace($suffix, '', $new_path);
2876
                            error_log('renamed');
2877
                            error_log($new_path);
2878
                            $params['title'] = get_document_title($new_path);
2879
                        } else {
2880
                            if (!empty($title)) {
2881
                                $params['title'] = get_document_title($title);
2882
                            } else {
2883
                                $params['title'] = get_document_title($files['file']['name']);
2884
                            }
2885
                        }*/
2886
2887
                        if (!empty($title)) {
2888
                            $params['title'] = $title;
2889
                        }
2890
2891
                        if (!empty($comment)) {
2892
                            $params['comment'] = trim($comment);
2893
                        }
2894
2895
                        Database::update(
2896
                            $table_document,
2897
                            $params,
2898
                            array(
2899
                                'id = ? AND c_id = ? ' => array(
2900
                                    $documentId,
2901
                                    $course_info['real_id']
2902
                                )
2903
                            )
2904
                        );
2905
                    }
2906
2907
                    // Showing message when sending zip files
2908
                    if ($new_path === true && $unzip == 1 && $show_output) {
2909
                        Display::display_confirmation_message(
2910
                            get_lang('UplUploadSucceeded') . '<br />',
2911
                            false
2912
                        );
2913
                    }
2914
2915
                    if ($index_document) {
2916
                        self::index_document(
2917
                            $documentId,
2918
                            $course_info['code'],
2919
                            null,
2920
                            $_POST['language'],
2921
                            $_REQUEST,
2922
                            $if_exists
2923
                        );
2924
                    }
2925
2926 View Code Duplication
                    if (!empty($documentId) && is_numeric($documentId)) {
2927
                        $documentData = self::get_document_data_by_id(
2928
                            $documentId,
2929
                            $course_info['code'],
2930
                            false,
2931
                            $sessionId
2932
                        );
2933
2934
                        return $documentData;
2935
                    }
2936
                }
2937
            }
2938
        }
2939
2940
        return false;
2941
    }
2942
2943
    /**
2944
     * Obtains the text inside the file with the right parser
2945
     */
2946
    public static function get_text_content($doc_path, $doc_mime)
2947
    {
2948
        // TODO: review w$ compatibility
2949
        // Use usual exec output lines array to store stdout instead of a temp file
2950
        // because we need to store it at RAM anyway before index on ChamiloIndexer object
2951
        $ret_val = null;
2952
        switch ($doc_mime) {
2953
            case 'text/plain':
2954
                $handle = fopen($doc_path, 'r');
2955
                $output = array(fread($handle, filesize($doc_path)));
2956
                fclose($handle);
2957
                break;
2958
            case 'application/pdf':
2959
                exec("pdftotext $doc_path -", $output, $ret_val);
2960
                break;
2961
            case 'application/postscript':
2962
                $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
2963
                exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
2964
                if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
2965
                    return false;
2966
                }
2967
                exec("pdftotext $temp_file -", $output, $ret_val);
2968
                unlink($temp_file);
2969
                break;
2970
            case 'application/msword':
2971
                exec("catdoc $doc_path", $output, $ret_val);
2972
                break;
2973
            case 'text/html':
2974
                exec("html2text $doc_path", $output, $ret_val);
2975
                break;
2976
            case 'text/rtf':
2977
                // Note: correct handling of code pages in unrtf
2978
                // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
2979
                exec("unrtf --text $doc_path", $output, $ret_val);
2980
                if ($ret_val == 127) { // command not found
2981
                    return false;
2982
                }
2983
                // Avoid index unrtf comments
2984
                if (is_array($output) && count($output) > 1) {
2985
                    $parsed_output = array();
2986
                    foreach ($output as & $line) {
2987
                        if (!preg_match('/^###/', $line, $matches)) {
2988
                            if (!empty($line)) {
2989
                                $parsed_output[] = $line;
2990
                            }
2991
                        }
2992
                    }
2993
                    $output = $parsed_output;
2994
                }
2995
                break;
2996
            case 'application/vnd.ms-powerpoint':
2997
                exec("catppt $doc_path", $output, $ret_val);
2998
                break;
2999
            case 'application/vnd.ms-excel':
3000
                exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
3001
                break;
3002
        }
3003
3004
        $content = '';
3005
        if (!is_null($ret_val)) {
3006
            if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
3007
                return false;
3008
            }
3009
        }
3010
        if (isset($output)) {
3011
            foreach ($output as & $line) {
3012
                $content .= $line . "\n";
3013
            }
3014
            return $content;
3015
        } else {
3016
            return false;
3017
        }
3018
    }
3019
3020
    /**
3021
     * Calculates the total size of all documents in a course
3022
     *
3023
     * @author Bert vanderkimpen
3024
     * @param  int $course_id
3025
     * @param  int $group_id (to calculate group document space)
3026
     * @param  int $session_id
3027
     *
3028
     * @return int total size
3029
     */
3030
    static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
3031
    {
3032
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3033
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
3034
3035
        if (isset($course_id)) {
3036
            $course_id = intval($course_id);
3037
        } else {
3038
            $course_id = api_get_course_int_id();
3039
        }
3040
3041
        $group_condition = null;
3042
        if (isset($group_id)) {
3043
            $group_id = intval($group_id);
3044
            $group_condition = " AND props.to_group_id='" . $group_id . "' ";
3045
        }
3046
3047
        $session_condition = null;
3048
        if (isset($session_id)) {
3049
            $session_id = intval($session_id);
3050
            $session_condition = " AND props.session_id='" . $session_id . "' ";
3051
        }
3052
3053
        $sql = "SELECT SUM(size)
3054
                FROM $TABLE_ITEMPROPERTY AS props
3055
                INNER JOIN $TABLE_DOCUMENT AS docs
3056
                ON (docs.id = props.ref AND props.c_id = docs.c_id)
3057
                WHERE
3058
                    props.c_id 	= $course_id AND
3059
                    docs.c_id 	= $course_id AND
3060
                    props.tool 	= '" . TOOL_DOCUMENT . "' AND
3061
                    props.visibility <> 2
3062
                    $group_condition
3063
                    $session_condition
3064
                ";
3065
        $result = Database::query($sql);
3066
3067
        if ($result && Database::num_rows($result) != 0) {
3068
            $row = Database::fetch_row($result);
3069
            return $row[0];
3070
        } else {
3071
            return 0;
3072
        }
3073
    }
3074
3075
    /**
3076
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3077
     */
3078
    static function display_quota($course_quota, $already_consumed_space)
3079
    {
3080
        $course_quota_m = round($course_quota / 1048576);
3081
        $already_consumed_space_m = round($already_consumed_space / 1048576);
3082
3083
        $message = get_lang('MaximumAllowedQuota') . ' <strong>' . $course_quota_m . ' megabyte</strong>.<br />';
3084
        $message .= get_lang('CourseCurrentlyUses') . ' <strong>' . $already_consumed_space_m . ' megabyte</strong>.<br />';
3085
3086
        $percentage = round(($already_consumed_space / $course_quota * 100), 1);
3087
3088
        $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
3089
3090
        // Decide where to place percentage in graph
3091
        if ($percentage >= 50) {
3092
            $text_in_filled = '&nbsp;' . $other_percentage . '%';
3093
            $text_in_unfilled = '';
3094
        } else {
3095
            $text_in_unfilled = '&nbsp;' . $other_percentage . '%';
3096
            $text_in_filled = '';
3097
        }
3098
3099
        // Decide the background colour of the graph
3100
        if ($percentage < 65) {
3101
            $colour = '#00BB00';        // Safe - green
3102
        } elseif ($percentage < 90) {
3103
            $colour = '#ffd400';        // Filling up - yelloworange
3104
        } else {
3105
            $colour = '#DD0000';        // Full - red
3106
        }
3107
3108
        // This is used for the table width: a table of only 100 pixels looks too small
3109
        $visual_percentage = 4 * $percentage;
3110
        $visual_other_percentage = 4 * $other_percentage;
3111
3112
        $message .= get_lang('PercentageQuotaInUse') . ': <strong>' . $percentage . '%</strong>.<br />' .
3113
            get_lang('PercentageQuotaFree') . ': <strong>' . $other_percentage . '%</strong>.<br />';
3114
3115
        $show_percentage = '&nbsp;' . $percentage . '%';
3116
        $message .= '<div style="width: 80%; text-align: center; -moz-border-radius: 5px 5px 5px 5px; border: 1px solid #aaa; background-image: url(\'' . api_get_path(WEB_CODE_PATH) . 'css/' . api_get_visual_theme() . '/images/bg-header4.png\');" class="document-quota-bar">' .
3117
            '<div style="width:' . $percentage . '%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>' .
3118
            '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">' . $show_percentage . '</span></div>';
3119
        echo $message;
3120
    }
3121
3122
    /**
3123
     * Display the document quota in a simple way
3124
     *
3125
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3126
     */
3127
    static function display_simple_quota($course_quota, $already_consumed_space)
3128
    {
3129
        $course_quota_m = round($course_quota / 1048576);
3130
        $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
3131
        $percentage = $already_consumed_space / $course_quota * 100;
3132
        $percentage = round($percentage, 1);
3133
        $message = get_lang('YouAreCurrentlyUsingXOfYourX');
3134
        $message = sprintf($message, $already_consumed_space_m, $percentage . '%', $course_quota_m . ' ');
3135
        echo Display::div($message, array('id' => 'document_quota'));
3136
    }
3137
3138
    /**
3139
     * Checks if there is enough place to add a file on a directory
3140
     * on the base of a maximum directory size allowed
3141
     *
3142
     * @author Bert Vanderkimpen
3143
     * @param  int $file_size size of the file in byte
3144
     * @param  int $max_dir_space maximum size
3145
     * @return boolean true if there is enough space, false otherwise
3146
     *
3147
     * @see enough_space() uses  documents_total_space() function
3148
     */
3149
    static function enough_space($file_size, $max_dir_space) {
3150
        if ($max_dir_space) {
3151
            $already_filled_space = self::documents_total_space();
3152
            if (($file_size + $already_filled_space) > $max_dir_space) {
3153
                return false;
3154
            }
3155
        }
3156
        return true;
3157
    }
3158
3159
    /**
3160
     * @param array $params count, url, extension
3161
     * @return string
3162
     */
3163
    static function generate_jplayer_jquery($params = array())
3164
    {
3165
        $js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
3166
3167
        $js = '
3168
            $("#jquery_jplayer_' . $params['count'] . '").jPlayer({
3169
                ready: function() {
3170
                    $(this).jPlayer("setMedia", {
3171
                        ' . $params['extension'] . ' : "' . $params['url'] . '"
3172
                    });
3173
                },
3174
                play: function() { // To avoid both jPlayers playing together.
3175
                    $(this).jPlayer("pauseOthers");
3176
                },
3177
                //errorAlerts: true,
3178
                //warningAlerts: true,
3179
                swfPath: "' . $js_path . 'jquery-jplayer/jplayer/",
3180
                //supplied: "m4a, oga, mp3, ogg, wav",
3181
                supplied: "' . $params['extension'] . '",
3182
                wmode: "window",
3183
                solution: "flash, html",  // Do not change this setting
3184
                cssSelectorAncestor: "#jp_container_' . $params['count'] . '",
3185
            });  	 ' . "\n\n";
3186
3187
        return $js;
3188
    }
3189
3190
    /**
3191
     *
3192
     * Shows a play icon next to the document title in the document list
3193
     * @param int
3194
     * @param string
3195
     * @return string	html content
3196
     */
3197
    static function generate_media_preview($i, $type = 'simple')
3198
    {
3199
        $i = intval($i);
3200
3201
        $extra_controls = $progress = '';
3202
        if ($type == 'advanced') {
3203
            $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
3204
                                <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
3205
                                <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
3206
            $progress = '<div class="jp-progress">
3207
                                <div class="jp-seek-bar">
3208
                                    <div class="jp-play-bar"></div>
3209
                                </div>
3210
                            </div>';
3211
        }
3212
3213
        //Shows only the play button
3214
        $html = '<div id="jquery_jplayer_' . $i . '" class="jp-jplayer"></div>
3215
                <div id="jp_container_' . $i . '" class="jp-audio">
3216
                    <div class="jp-type-single">
3217
                        <div class="jp-gui jp-interface">
3218
                            <ul class="jp-controls">
3219
                                <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
3220
                                <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
3221
                                ' . $extra_controls . '
3222
                            </ul>
3223
                            ' . $progress . '
3224
                        </div>
3225
                    </div>
3226
                </div>';
3227
        //<div id="jplayer_inspector_'.$i.'"></div>
3228
        return $html;
3229
    }
3230
3231
    /**
3232
     * @param array $document_data
3233
     * @return string
3234
     */
3235
    public static function generate_video_preview($document_data = array())
3236
    {
3237
        //<button class="jp-video-play-icon" role="button" tabindex="0">play</button>
3238
        $html = '
3239
        <div id="jp_container_1" class="jp-video center-block" role="application" aria-label="media player">
3240
            <div class="jp-type-single">
3241
                <div id="jquery_jplayer_1" class="jp-jplayer"></div>
3242
                <div class="jp-gui">
3243
                    <div class="jp-video-play">
3244
                    </div>
3245
                    <div class="jp-interface">
3246
                        <div class="jp-progress">
3247
                            <div class="jp-seek-bar">
3248
                                <div class="jp-play-bar"></div>
3249
                            </div>
3250
                        </div>
3251
                        <div class="jp-current-time" role="timer" aria-label="time">&nbsp;</div>
3252
                        <div class="jp-duration" role="timer" aria-label="duration">&nbsp;</div>
3253
                        <div class="jp-controls-holder">
3254
                          <div class="jp-controls">
3255
                            <button class="jp-play" role="button" tabindex="0">play</button>
3256
                            <button class="jp-stop" role="button" tabindex="0">stop</button>
3257
                          </div>
3258
                          <div class="jp-volume-controls">
3259
                            <button class="jp-mute" role="button" tabindex="0">mute</button>
3260
                            <button class="jp-volume-max" role="button" tabindex="0">max volume</button>
3261
                            <div class="jp-volume-bar">
3262
                                <div class="jp-volume-bar-value"></div>
3263
                            </div>
3264
                          </div>
3265
                          <div class="jp-toggles">
3266
                            <button class="jp-repeat" role="button" tabindex="0">repeat</button>
3267
                            <button class="jp-full-screen" role="button" tabindex="0">full screen</button>
3268
                          </div>
3269
                        </div>
3270
                        <div class="jp-details">
3271
                          <div class="jp-title" aria-label="title">&nbsp;</div>
3272
                        </div>
3273
                    </div>
3274
                </div>
3275
                <div class="jp-no-solution">
3276
                    <span>' . get_lang('UpdateRequire') . '</span>
3277
                    ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile") . '
3278
                </div>
3279
            </div>
3280
        </div>';
3281
        return $html;
3282
    }
3283
3284
    /**
3285
     * @param array $course_info
3286
     * @param bool $lp_id
3287
     * @param string $target
3288
     * @param int $session_id
3289
     * @param bool $add_move_button
3290
     * @param string $filter_by_folder
3291
     * @param string $overwrite_url
3292
     * @param bool $showInvisibleFiles
3293
     * @param bool $showOnlyFolders
3294
     * @param int $folderId
3295
     * @return string
3296
     */
3297
    public static function get_document_preview(
3298
        $course_info,
3299
        $lp_id = false,
3300
        $target = '',
3301
        $session_id = 0,
3302
        $add_move_button = false,
3303
        $filter_by_folder = null,
3304
        $overwrite_url = null,
3305
        $showInvisibleFiles = false,
3306
        $showOnlyFolders = false,
3307
        $folderId = false
3308
    ) {
3309
        if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
3310
            return '';
3311
        }
3312
3313
        $overwrite_url = Security::remove_XSS($overwrite_url);
3314
        $user_id = api_get_user_id();
3315
        $user_in_course = false;
3316
3317
        if (api_is_platform_admin()) {
3318
            $user_in_course = true;
3319
        }
3320
3321
        if (!$user_in_course) {
3322
            if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
3323
                $user_in_course = true;
3324
            }
3325
        }
3326
3327
        // Condition for the session
3328
        $session_id = intval($session_id);
3329
3330
        if (!$user_in_course) {
3331
            if (empty($session_id)) {
3332
                if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
3333
                    $user_in_course = true;
3334
                }
3335
                // Check if course is open then we can consider that the student is registered to the course
3336
                if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
3337
                    $user_in_course = true;
3338
                }
3339 View Code Duplication
            } else {
3340
                $user_status = SessionManager::get_user_status_in_course_session(
3341
                    $user_id,
3342
                    $course_info['real_id'],
3343
                    $session_id
3344
                );
3345
                //is true if is an student, course session teacher or coach
3346
                if (in_array($user_status, array('0', '2', '6'))) {
3347
                    $user_in_course = true;
3348
                }
3349
            }
3350
        }
3351
3352
        $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
3353
        $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
3354
        $condition_session = " AND (last.session_id = '$session_id' OR last.session_id = '0' OR last.session_id IS NULL)";
3355
3356
        $add_folder_filter = null;
3357
        if (!empty($filter_by_folder)) {
3358
            $add_folder_filter = " AND docs.path LIKE '" . Database::escape_string($filter_by_folder) . "%'";
3359
        }
3360
3361
        // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
3362
        $lp_visibility_condition = null;
3363
        if ($lp_id) {
3364
            // $lp_visibility_condition = " OR filetype='folder'";
3365
            if ($showInvisibleFiles) {
3366
                $lp_visibility_condition .= ' OR last.visibility = 0';
3367
            }
3368
        }
3369
3370
        $showOnlyFoldersCondition = null;
3371
        if ($showOnlyFolders) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
3372
            //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
3373
        }
3374
3375
        $folderCondition = " AND docs.path LIKE '/%' ";
3376
3377
        if (!api_is_allowed_to_edit()) {
3378
            $protectedFolders = self::getProtectedFolderFromStudent();
3379
            foreach ($protectedFolders as $folder) {
3380
                $folderCondition .= " AND docs.path NOT LIKE '$folder' ";
3381
            }
3382
        }
3383
3384
        $parentData = [];
3385
        if ($folderId !== false) {
3386
            $parentData = self::get_document_data_by_id($folderId, $course_info['code']);
3387
            if (!empty($parentData)) {
3388
                $cleanedPath = $parentData['path'];
3389
                $num = substr_count($cleanedPath, '/');
3390
3391
                $notLikeCondition = null;
3392
                for ($i = 1; $i <= $num; $i++) {
3393
                    $repeat = str_repeat('/%', $i+1);
3394
                    $notLikeCondition .= " AND docs.path NOT LIKE '".Database::escape_string($cleanedPath.$repeat)."' ";
3395
                }
3396
3397
                $folderCondition = " AND
3398
                    docs.id <> $folderId AND
3399
                    docs.path LIKE '".$cleanedPath."/%'
3400
                    $notLikeCondition
3401
                ";
3402
            } else {
3403
                $folderCondition = " AND
3404
                docs.filetype = 'file' ";
3405
            }
3406
        }
3407
3408
        $levelCondition = null;
3409
        if ($folderId === false) {
3410
            $levelCondition = " AND docs.path NOT LIKE'/%/%'";
3411
        }
3412
3413
        $sql = "SELECT last.visibility, docs.*
3414
                FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
3415
                ON (docs.id = last.ref AND docs.c_id = last.c_id)
3416
                WHERE
3417
                    docs.path NOT LIKE '%_DELETED_%' AND
3418
                    last.tool = '" . TOOL_DOCUMENT . "' $condition_session AND
3419
                    (last.visibility = '1' $lp_visibility_condition) AND
3420
                    last.visibility <> 2 AND
3421
                    docs.c_id = {$course_info['real_id']} AND
3422
                    last.c_id = {$course_info['real_id']}
3423
                    $showOnlyFoldersCondition
3424
                    $folderCondition
3425
                    $levelCondition
3426
                    $add_folder_filter
3427
                ORDER BY docs.filetype DESC, docs.title ASC";
3428
3429
        $res_doc = Database::query($sql);
3430
        $resources = Database::store_result($res_doc, 'ASSOC');
3431
3432
        $return = '';
3433
        if ($lp_id) {
3434
            if ($folderId === false) {
3435
                $return .= '<div class="lp_resource_element">';
3436
                $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
3437
                $return .= Display::url(
3438
                    get_lang('NewDocument'),
3439
                    api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
3440
                );
3441
                $return .= '</div>';
3442
            }
3443
        } else {
3444
            $return .= Display::div(
3445
                Display::url(
3446
                    Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
3447
                    ' javascript:void(0);',
3448
                    array('id' => 'close_div_' . $course_info['real_id'] . '_' . $session_id, 'class' => 'close_div')
3449
                ),
3450
                array('style' => 'position:absolute;right:10px')
3451
            );
3452
        }
3453
3454
        // If you want to debug it, I advise you to do "echo" on the eval statements.
3455
        $newResources = array();
3456
3457
        if (!empty($resources) && $user_in_course) {
3458
            foreach ($resources as $resource) {
3459
                $is_visible = self::is_visible_by_id(
3460
                    $resource['id'],
3461
                    $course_info,
3462
                    $session_id,
3463
                    api_get_user_id()
3464
                );
3465
3466
                if (!$is_visible) {
3467
                    continue;
3468
                }
3469
                $newResources[] = $resource;
3470
            }
3471
        }
3472
3473
        $label = get_lang('Documents');
3474
3475
        $documents = [];
3476
        if ($folderId === false) {
3477
            $documents[$label] = array(
3478
                'id' => 0,
3479
                'files' => $newResources
3480
            );
3481
        } else {
3482
            if (!empty($parentData)) {
3483
                $documents[$parentData['title']] = array(
3484
                    'id' => intval($folderId),
3485
                    'files' => $newResources
3486
                );
3487
            }
3488
        }
3489
3490
        $write_result = self::write_resources_tree(
3491
            $course_info,
3492
            $session_id,
3493
            $documents,
3494
            $lp_id,
3495
            $target,
3496
            $add_move_button,
3497
            $overwrite_url,
3498
            $folderId
3499
        );
3500
3501
        $return .= $write_result;
3502
        if ($lp_id == false) {
3503
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
3504
            $return .= "<script>
3505
            $('.doc_folder').click(function() {
3506
                var realId = this.id;
3507
                var my_id = this.id.split('_')[2];
3508
                var tempId = 'temp_'+my_id;
3509
                $('#res_'+my_id).show();
3510
3511
                var tempDiv = $('#'+realId).find('#'+tempId);
3512
                if (tempDiv.length == 0) {
3513
                    $.ajax({
3514
                        async: false,
3515
                        type: 'GET',
3516
                        url:  '".$url."',
3517
                        data: 'folder_id='+my_id,
3518
                        success: function(data) {
3519
                            $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
3520
                        }
3521
                    });
3522
                }
3523
            });
3524
3525
            $('.close_div').click(function() {
3526
                var course_id = this.id.split('_')[2];
3527
                var session_id = this.id.split('_')[3];
3528
                $('#document_result_'+course_id+'_'+session_id).hide();
3529
                $('.lp_resource').remove();
3530
                $('.document_preview_container').html('');
3531
            });
3532
3533
            </script>";
3534 View Code Duplication
        } else {
3535
            //For LPs
3536
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
3537
            $return .= "<script>
3538
3539
            function testResources(id, img) {
3540
                var numericId = id.split('_')[1];
3541
                var parentId = 'doc_id_'+numericId;
3542
                var tempId = 'temp_'+numericId;
3543
                var image = $('#'+img);
3544
3545
                if (image.hasClass('open')) {
3546
                    image.removeClass('open');
3547
                    image.attr('src', '" . Display::returnIconPath('nolines_plus.gif')."');
3548
                    $('#'+id).show();
3549
                    $('#'+tempId).hide();
3550
                } else {
3551
                    image.addClass('open');
3552
                    image.attr('src', '" . Display::returnIconPath('nolines_minus.gif') . "');
3553
                    $('#'+id).hide();
3554
                    $('#'+tempId).show();
3555
3556
                    var tempDiv = $('#'+parentId).find('#'+tempId);
3557
                    if (tempDiv.length == 0) {
3558
                        $.ajax({
3559
                            type: 'GET',
3560
                            async: false,
3561
                            url:  '".$url."',
3562
                            data: 'folder_id='+numericId,
3563
                            success: function(data) {
3564
                                tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
3565
                            }
3566
                        });
3567
                    }
3568
                }
3569
            }
3570
            </script>";
3571
        }
3572
3573
        if (!$user_in_course) {
3574
            $return = '';
3575
        }
3576
3577
        return $return;
3578
    }
3579
3580
    /**
3581
     * @param array $course_info
3582
     * @param int $session_id
3583
     * @param array $resource
3584
     * @param int $lp_id
3585
     * @param bool $add_move_button
3586
     * @param string $target
3587
     * @param string $overwrite_url
3588
     * @return null|string
3589
     */
3590
    private static function parseFile(
3591
        $course_info,
3592
        $session_id,
3593
        $resource,
3594
        $lp_id,
3595
        $add_move_button,
3596
        $target,
3597
        $overwrite_url
3598
    ) {
3599
        $img_sys_path = api_get_path(SYS_CODE_PATH) . 'img/';
3600
        $web_code_path = api_get_path(WEB_CODE_PATH);
3601
3602
        $documentId = $resource['id'];
3603
        $path = $resource['path'];
3604
3605
        if (empty($path)) {
3606
            $num = 0;
3607
        } else {
3608
            $num = substr_count($path, '/') - 1;
3609
        }
3610
3611
        // It's a file.
3612
        $icon = choose_image($path);
3613
        $position = strrpos($icon, '.');
3614
        $icon = substr($icon, 0, $position) . '_small.gif';
3615
        $my_file_title = $resource['title'];
3616
        $visibility = $resource['visibility'];
3617
3618
        // If title is empty we try to use the path
3619
        if (empty($my_file_title)) {
3620
            $my_file_title = basename($path);
3621
        }
3622
3623
        // Show the "image name" not the filename of the image.
3624
        if ($lp_id) {
3625
            // LP URL
3626
            $url = api_get_path(WEB_CODE_PATH).'newscorm/lp_controller.php?'.api_get_cidreq().'&amp;action=add_item&amp;type=' . TOOL_DOCUMENT . '&amp;file=' . $documentId . '&amp;lp_id=' . $lp_id;
3627 View Code Duplication
            if (!empty($overwrite_url)) {
3628
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId.'';
3629
            }
3630
        } else {
3631
            // Direct document URL
3632
            $url = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
3633 View Code Duplication
            if (!empty($overwrite_url)) {
3634
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId;
3635
            }
3636
        }
3637
3638
        $img = Display::returnIconPath($icon);
3639
        if (!file_exists($img_sys_path . $icon)) {
3640
            $img = Display::returnIconPath('default_small.gif');
3641
        }
3642
3643
        $link = Display::url(
3644
            '<img alt="" src="' . $img . '" title="" />&nbsp;' . $my_file_title, $url,
3645
            array('target' => $target)
3646
        );
3647
3648
        $visibilityClass = null;
3649
        if ($visibility == 0) {
3650
            $visibilityClass = ' invisible ';
3651
        }
3652
        $return = null;
3653
3654
        if ($lp_id == false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $lp_id of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
3655
            $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3656
        } else {
3657
            $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3658
        }
3659
3660
        $return .= '<div class="item_data" style="margin-left:' . ($num  * 18) . 'px;margin-right:5px;">';
3661
3662 View Code Duplication
        if ($add_move_button) {
3663
            $return .= '<a class="moved" href="#">';
3664
            $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
3665
            $return .= '</a> ';
3666
        }
3667
        $return .= $link;
3668
        $return .= '</div></li>';
3669
3670
        return $return;
3671
    }
3672
3673
    /**
3674
     * @param int $folderId
3675
     * @param array $resource
3676
     * @param int $lp_id
3677
     * @return null|string
3678
     */
3679
    private static function parseFolder($folderId, $resource, $lp_id)
3680
    {
3681
        $title = isset($resource['title']) ? $resource['title'] : null;
3682
        $path = isset($resource['path']) ? $resource['path'] : null;
3683
3684
        if (empty($path)) {
3685
            $num = 0;
3686
        } else {
3687
            $num = substr_count($path, '/');
3688
        }
3689
3690
        // It's a folder.
3691
        //hide some folders
3692
        if (in_array($path,
3693
            array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
3694
            return null;
3695
        } elseif (preg_match('/_groupdocs/', $path)) {
3696
            return null;
3697
        } elseif (preg_match('/sf_user_/', $path)) {
3698
            return null;
3699
        } elseif (preg_match('/shared_folder_session_/', $path)) {
3700
            return null;
3701
        }
3702
3703
        //trad some titles
3704
        /*
3705
        if ($key == 'images') {
3706
            $key = get_lang('Images');
3707
        } elseif ($key == 'gallery') {
3708
            $key = get_lang('Gallery');
3709
        } elseif ($key == 'flash') {
3710
            $key = get_lang('Flash');
3711
        } elseif ($key == 'audio') {
3712
            $key = get_lang('Audio');
3713
        } elseif ($key == 'video') {
3714
            $key = get_lang('Video');
3715
        }*/
3716
3717
        $onclick = '';
3718
3719
        // if in LP, hidden folder are displayed in grey
3720
        $folder_class_hidden = "";
3721
        if ($lp_id) {
3722
            if (isset($resource['visible']) && $resource['visible'] == 0) {
3723
                $folder_class_hidden = "doc_folder_hidden"; // in base.css
3724
            }
3725
            $onclick = 'onclick="javascript: testResources(\'res_' . $resource['id'] . '\',\'img_' . $resource['id'] . '\')"';
3726
        }
3727
        $return = null;
3728
3729
        if (empty($path)) {
3730
            $return = '<ul class="lp_resource">';
3731
        }
3732
3733
        $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_' . $resource['id'] . '"  style="margin-left:' . ($num * 18) . 'px; ">';
3734
3735
        $image = Display::returnIconPath('nolines_plus.gif');
3736
        if (empty($path)) {
3737
            $image = Display::returnIconPath('nolines_minus.gif');
3738
        }
3739
        $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'] . '" '.$onclick.'>';
3740
        $return .= Display::return_icon('lp_folder.gif').'&nbsp;';
3741
        $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
3742
        $return .= '</li>';
3743
3744
        if (empty($path)) {
3745
            if ($folderId == false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $folderId of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
3746
                $return .= '<div id="res_' . $resource['id'] . '" >';
3747
            } else {
3748
                $return .= '<div id="res_' . $resource['id'] . '" style="display: none;" >';
3749
            }
3750
        }
3751
3752
        return $return;
3753
    }
3754
3755
    /**
3756
     * Generate and return an HTML list of resources based on a given array.
3757
     * This list is used to show the course creator a list of available resources to choose from
3758
     * when creating a learning path.
3759
     * @param array $course_info
3760
     * @param int $session_id
3761
     * @param array $documents
3762
     * @param bool $lp_id
3763
     * @param string $target
3764
     * @param bool $add_move_button
3765
     * @param string $overwrite_url
3766
     * @param int $folderId
3767
     *
3768
     * @return string
3769
     */
3770
    public static function write_resources_tree(
3771
        $course_info,
3772
        $session_id,
3773
        $documents,
3774
        $lp_id = false,
3775
        $target = '',
3776
        $add_move_button = false,
3777
        $overwrite_url = null,
3778
        $folderId = false
3779
    ) {
3780
        $return = '';
3781
3782
        if (!empty($documents)) {
3783
            foreach ($documents as $key => $resource) {
3784
                if (isset($resource['id']) && is_int($resource['id'])) {
3785
                    $mainFolderResource = array(
3786
                        'id' => $resource['id'],
3787
                        'title' => $key,
3788
                    );
3789
3790
                    if ($folderId === false) {
3791
                        $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
3792
                    }
3793
3794
                    if (isset($resource['files'])) {
3795
                        $return .= self::write_resources_tree(
3796
                            $course_info,
3797
                            $session_id,
3798
                            $resource['files'],
3799
                            $lp_id,
3800
                            $target,
3801
                            $add_move_button,
3802
                            $overwrite_url
3803
                        );
3804
                    }
3805
                    $return .= '</div>';
3806
                    $return .= '</ul>';
3807
                } else {
3808
                    if ($resource['filetype'] == 'folder') {
3809
                        $return .= self::parseFolder($folderId, $resource, $lp_id);
0 ignored issues
show
Bug introduced by
It seems like $folderId defined by parameter $folderId on line 3778 can also be of type false; however, DocumentManager::parseFolder() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
3810
                    } else {
3811
                        $return .= self::parseFile(
3812
                            $course_info,
3813
                            $session_id,
3814
                            $resource,
3815
                            $lp_id,
3816
                            $add_move_button,
3817
                            $target,
3818
                            $overwrite_url
3819
                        );
3820
                    }
3821
                }
3822
            }
3823
        }
3824
3825
        return $return;
3826
    }
3827
3828
    /**
3829
     * @param int $doc_id
3830
     * @param string $course_code
3831
     * @param int $session_id
3832
     * @param int $user_id
3833
     * @param int $groupId
3834
     * @return bool
3835
     */
3836
    public static function check_visibility_tree(
3837
        $doc_id,
3838
        $course_code,
3839
        $session_id,
3840
        $user_id,
3841
        $groupId = 0
3842
    ) {
3843
        $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
3844
        if ($session_id != 0 && !$document_data) {
3845
            $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
3846
        }
3847
3848
        if (!empty($document_data)) {
3849
            // If admin or course teacher, allow anyway
3850
            if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
3851
                return true;
3852
            }
3853
            $course_info = api_get_course_info($course_code);
3854
            if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
3855
                if (!empty($groupId)) {
3856
                    return true;
3857
                }
3858
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3859
                return $visible;
3860
            } else {
3861
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3862
3863
                if (!$visible) {
3864
                    return false;
3865
                } else {
3866
                    return self::check_visibility_tree(
3867
                        $document_data['parent_id'],
3868
                        $course_code,
3869
                        $session_id,
3870
                        $user_id,
3871
                        $groupId
3872
                    );
3873
                }
3874
            }
3875
        } else {
3876
            return false;
3877
        }
3878
    }
3879
3880
    /**
3881
     * Index a given document.
3882
     * @param   int     Document ID inside its corresponding course
3883
     * @param   string  Course code
3884
     * @param   int     Session ID (not used yet)
3885
     * @param   string  Language of document's content (defaults to course language)
3886
     * @param   array   Array of specific fields (['code'=>'value',...])
3887
     * @param   string  What to do if the file already exists (default or overwrite)
3888
     * @param   bool    When set to true, this runs the indexer without actually saving anything to any database
3889
     * @return  bool    Returns true on presumed success, false on failure
3890
     */
3891
    public static function index_document(
3892
        $docid,
3893
        $course_code,
3894
        $session_id = 0,
3895
        $lang = 'english',
3896
        $specific_fields_values = array(),
3897
        $if_exists = '',
3898
        $simulation = false
3899
    ) {
3900
        if (api_get_setting('search_enabled') !== 'true') {
3901
            return false;
3902
        }
3903
        if (empty($docid) or $docid != intval($docid)) {
3904
            return false;
3905
        }
3906
        if (empty($session_id)) {
3907
            $session_id = api_get_session_id();
3908
        }
3909
        $course_info = api_get_course_info($course_code);
3910
        $course_dir = $course_info['path'] . '/document';
3911
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
3912
        $base_work_dir = $sys_course_path . $course_dir;
3913
3914
        $course_id = $course_info['real_id'];
3915
        $table_document = Database::get_course_table(TABLE_DOCUMENT);
3916
3917
        $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
3918
        $result = Database::query($qry);
3919
        if (Database::num_rows($result) == 1) {
3920
            $row = Database::fetch_array($result);
3921
            $doc_path = api_get_path(SYS_COURSE_PATH) . $course_dir . $row['path'];
3922
            //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
3923
            // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
3924
            $doc_mime = mime_content_type($doc_path);
3925
            $allowed_mime_types = self::file_get_mime_type(true);
3926
3927
            // mime_content_type does not detect correctly some formats that are going to be supported for index, so an extensions array is used for the moment
3928
            if (empty($doc_mime)) {
3929
                $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
3930
                $extensions = preg_split("/[\/\\.]/", $doc_path);
3931
                $doc_ext = strtolower($extensions[count($extensions) - 1]);
3932
                if (in_array($doc_ext, $allowed_extensions)) {
3933
                    switch ($doc_ext) {
3934
                        case 'ppt':
3935
                        case 'pps':
3936
                            $doc_mime = 'application/vnd.ms-powerpoint';
3937
                            break;
3938
                        case 'xls':
3939
                            $doc_mime = 'application/vnd.ms-excel';
3940
                            break;
3941
                    }
3942
                }
3943
            }
3944
3945
            //@todo move this nightmare in a search controller or something like that!!! J.M
3946
3947
            if (in_array($doc_mime, $allowed_mime_types)) {
3948
                $file_title = $row['title'];
3949
                $file_content = self::get_text_content($doc_path, $doc_mime);
3950
                $course_code = Database::escape_string($course_code);
3951
3952
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
3953
                require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
3954
3955
                $ic_slide = new IndexableChunk();
3956
                $ic_slide->addValue('title', $file_title);
3957
                $ic_slide->addCourseId($course_code);
3958
                $ic_slide->addToolId(TOOL_DOCUMENT);
3959
                $xapian_data = array(
3960
                    SE_COURSE_ID => $course_code,
3961
                    SE_TOOL_ID => TOOL_DOCUMENT,
3962
                    SE_DATA => array('doc_id' => $docid),
3963
                    SE_USER => api_get_user_id(),
3964
                );
3965
3966
                $ic_slide->xapian_data = serialize($xapian_data);
3967
                $di = new ChamiloIndexer();
3968
                $return = $di->connectDb(null, null, $lang);
3969
3970
                require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
3971
                $specific_fields = get_specific_field_list();
3972
3973
                // process different depending on what to do if file exists
3974
                /**
3975
                 * @TODO Find a way to really verify if the file had been
3976
                 * overwriten. Now all work is done at
3977
                 * handle_uploaded_document() and it's difficult to verify it
3978
                 */
3979
                if (!empty($if_exists) && $if_exists == 'overwrite') {
3980
                    // Overwrite the file on search engine
3981
                    // Actually, it consists on a delete of terms from db,
3982
                    // insert new ones, create a new search engine document,
3983
                    // and remove the old one
3984
                    // Get search_did
3985
                    $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
3986
                    $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
3987
                    $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
3988
3989
                    $res = Database::query($sql);
3990
3991
                    if (Database::num_rows($res) > 0) {
3992
                        $se_ref = Database::fetch_array($res);
3993
                        if (!$simulation) {
3994
                            $di->remove_document($se_ref['search_did']);
3995
                        }
3996
                        $all_specific_terms = '';
3997
                        foreach ($specific_fields as $specific_field) {
3998
                            if (!$simulation) {
3999
                                delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
4000
                            }
4001
                            // Update search engine
4002
                            if (isset($specific_fields_values[$specific_field['code']])) {
4003
                                $sterms = trim($specific_fields_values[$specific_field['code']]);
4004
                            } else { //if the specific field is not defined, force an empty one
4005
                                $sterms = '';
4006
                            }
4007
                            $all_specific_terms .= ' ' . $sterms;
4008
                            $sterms = explode(',', $sterms);
4009
                            foreach ($sterms as $sterm) {
4010
                                $sterm = trim($sterm);
4011
                                if (!empty($sterm)) {
4012
                                    $ic_slide->addTerm($sterm, $specific_field['code']);
4013
                                    // updated the last param here from $value to $sterm without being sure - see commit15464
4014
                                    if (!$simulation) {
4015
                                        add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
4016
                                    }
4017
                                }
4018
                            }
4019
                        }
4020
                        // Add terms also to content to make terms findable by probabilistic search
4021
                        $file_content = $all_specific_terms . ' ' . $file_content;
4022
4023
                        if (!$simulation) {
4024
                            $ic_slide->addValue('content', $file_content);
4025
                            $di->addChunk($ic_slide);
4026
                            // Index and return a new search engine document id
4027
                            $did = $di->index();
4028
4029
                            if ($did) {
4030
                                // update the search_did on db
4031
                                $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4032
                                $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
4033
                                $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
4034
                                Database::query($sql);
4035
                            }
4036
                        }
4037
                    }
4038
                } else {
4039
                    // Add all terms
4040
                    $all_specific_terms = '';
4041 View Code Duplication
                    foreach ($specific_fields as $specific_field) {
4042
                        if (isset($specific_fields_values[$specific_field['code']])) {
4043
                            $sterms = trim($specific_fields_values[$specific_field['code']]);
4044
                        } else { //if the specific field is not defined, force an empty one
4045
                            $sterms = '';
4046
                        }
4047
                        $all_specific_terms .= ' ' . $sterms;
4048
                        if (!empty($sterms)) {
4049
                            $sterms = explode(',', $sterms);
4050
                            foreach ($sterms as $sterm) {
4051
                                if (!$simulation) {
4052
                                    $ic_slide->addTerm(trim($sterm), $specific_field['code']);
4053
                                    add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
4054
                                }
4055
                            }
4056
                        }
4057
                    }
4058
                    // Add terms also to content to make terms findable by probabilistic search
4059
                    $file_content = $all_specific_terms . ' ' . $file_content;
4060
                    if (!$simulation) {
4061
                        $ic_slide->addValue('content', $file_content);
4062
                        $di->addChunk($ic_slide);
4063
                        // Index and return search engine document id
4064
                        $did = $di->index();
4065
                        if ($did) {
4066
                            // Save it to db
4067
                            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4068
                            $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
4069
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
4070
                            $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
4071
                            Database::query($sql);
4072
                        } else {
4073
                            return false;
4074
                        }
4075
                    }
4076
                }
4077
            } else {
4078
                return false;
4079
            }
4080
        }
4081
        return true;
4082
    }
4083
4084
    /**
4085
     * @return array
4086
     */
4087
    public static function get_web_odf_extension_list()
4088
    {
4089
        return array('ods', 'odt', 'odp');
4090
    }
4091
4092
    /**
4093
     * Set of extension allowed to use Jodconverter
4094
     * @param $mode 'from'
4095
     *              'to'
4096
     *              'all'
4097
     * @param $format   'text'
4098
     *                  'spreadsheet'
4099
     *                  'presentation'
4100
     *                  'drawing'
4101
     *                  'all'
4102
     * @return array
4103
     */
4104
    public static function getJodconverterExtensionList($mode, $format)
4105
    {
4106
        $extensionList = array();
4107
        $extensionListFromText = array(
4108
            'odt',
4109
            'sxw',
4110
            'rtf',
4111
            'doc',
4112
            'docx',
4113
            'wpd',
4114
            'txt',
4115
        );
4116
        $extensionListToText = array(
4117
            'pdf',
4118
            'odt',
4119
            'sxw',
4120
            'rtf',
4121
            'doc',
4122
            'docx',
4123
            'txt',
4124
        );
4125
        $extensionListFromSpreadsheet = array(
4126
            'ods',
4127
            'sxc',
4128
            'xls',
4129
            'xlsx',
4130
            'csv',
4131
            'tsv',
4132
        );
4133
        $extensionListToSpreadsheet = array(
4134
            'pdf',
4135
            'ods',
4136
            'sxc',
4137
            'xls',
4138
            'xlsx',
4139
            'csv',
4140
            'tsv',
4141
        );
4142
        $extensionListFromPresentation = array(
4143
            'odp',
4144
            'sxi',
4145
            'ppt',
4146
            'pptx',
4147
        );
4148
        $extensionListToPresentation = array(
4149
            'pdf',
4150
            'swf',
4151
            'odp',
4152
            'sxi',
4153
            'ppt',
4154
            'pptx',
4155
        );
4156
        $extensionListFromDrawing = array('odg');
4157
        $extensionListToDrawing = array('svg', 'swf');
4158
4159
        if ($mode === 'from') {
4160 View Code Duplication
            if ($format === 'text') {
4161
                $extensionList = array_merge($extensionList, $extensionListFromText);
4162
            } elseif ($format === 'spreadsheet') {
4163
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4164
            } elseif ($format === 'presentation') {
4165
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4166
            } elseif ($format === 'drawing') {
4167
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4168
            } elseif ($format === 'all') {
4169
                $extensionList = array_merge($extensionList, $extensionListFromText);
4170
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4171
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4172
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4173
            }
4174 View Code Duplication
        } elseif ($mode === 'to') {
4175
            if ($format === 'text') {
4176
                $extensionList = array_merge($extensionList, $extensionListToText);
4177
            } elseif ($format === 'spreadsheet') {
4178
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4179
            } elseif ($format === 'presentation') {
4180
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4181
            } elseif ($format === 'drawing') {
4182
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4183
            } elseif ($format === 'all') {
4184
                $extensionList = array_merge($extensionList, $extensionListToText);
4185
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4186
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4187
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4188
            }
4189
        } elseif ($mode === 'all') {
4190
            if ($format === 'text') {
4191
                $extensionList = array_merge($extensionList, $extensionListFromText);
4192
                $extensionList = array_merge($extensionList, $extensionListToText);
4193
            } elseif ($format === 'spreadsheet') {
4194
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4195
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4196
            } elseif ($format === 'presentation') {
4197
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4198
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4199
            } elseif ($format === 'drawing') {
4200
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4201
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4202
            } elseif ($format === 'all') {
4203
                $extensionList = array_merge($extensionList, $extensionListFromText);
4204
                $extensionList = array_merge($extensionList, $extensionListToText);
4205
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4206
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4207
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4208
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4209
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4210
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4211
            }
4212
        }
4213
        return $extensionList;
4214
    }
4215
4216
    /**
4217
     * Get Format type list by extension and mode
4218
     * @param string $mode Mode to search format type list
4219
     * @example 'from'
4220
     * @example 'to'
4221
     * @param string $extension file extension to check file type
4222
     * @return array
4223
     */
4224
    public static function getFormatTypeListConvertor($mode = 'from', $extension)
4225
    {
4226
        $formatTypesList = array();
4227
        $formatTypes = array('text', 'spreadsheet', 'presentation', 'drawing');
4228
        foreach ($formatTypes as $formatType) {
4229
            if (
4230
            in_array(
4231
                $extension,
4232
                self::getJodconverterExtensionList($mode, $formatType)
4233
            )
4234
            ) {
4235
                $formatTypesList[] = $formatType;
4236
            }
4237
        }
4238
        return $formatTypesList;
4239
    }
4240
4241
    /**
4242
     * @param string $path
4243
     * @param bool $is_certificate_mode
4244
     * @return bool
4245
     */
4246
    public static function is_folder_to_avoid($path, $is_certificate_mode = false)
4247
    {
4248
        $foldersToAvoid = array(
4249
            '/HotPotatoes_files',
4250
            '/certificates',
4251
        );
4252
        $systemFolder = api_get_course_setting('show_system_folders');
4253
4254
        if ($systemFolder == 1) {
4255
            $foldersToAvoid = array();
4256
        }
4257
4258
        if (basename($path) == 'css') {
4259
            return true;
4260
        }
4261
4262
        if ($is_certificate_mode == false) {
4263
            //Certificate results
4264
            if (strstr($path, 'certificates')) {
4265
                return true;
4266
            }
4267
        }
4268
4269
        // Admin setting for Hide/Show the folders of all users
4270 View Code Duplication
        if (api_get_setting('show_users_folders') == 'false') {
4271
            $foldersToAvoid[] = '/shared_folder';
4272
4273
            if (strstr($path, 'shared_folder_session_')) {
4274
                return true;
4275
            }
4276
        }
4277
4278
        // Admin setting for Hide/Show Default folders to all users
4279
        if (api_get_setting('show_default_folders') == 'false') {
4280
            $foldersToAvoid[] = '/images';
4281
            $foldersToAvoid[] = '/flash';
4282
            $foldersToAvoid[] = '/audio';
4283
            $foldersToAvoid[] = '/video';
4284
        }
4285
4286
        // Admin setting for Hide/Show chat history folder
4287
        if (api_get_setting('show_chat_folder') == 'false') {
4288
            $foldersToAvoid[] = '/chat_files';
4289
        }
4290
4291
        if (is_array($foldersToAvoid)) {
4292
4293
            return in_array($path, $foldersToAvoid);
4294
        } else {
4295
4296
            return false;
4297
        }
4298
    }
4299
4300
    /**
4301
     * @return array
4302
     */
4303 View Code Duplication
    public static function get_system_folders()
4304
    {
4305
        return array(
4306
            '/certificates',
4307
            '/HotPotatoes_files',
4308
            '/chat_files',
4309
            '/images',
4310
            '/flash',
4311
            '/audio',
4312
            '/video',
4313
            '/shared_folder',
4314
            '/learning_path'
4315
        );
4316
    }
4317
4318
    /**
4319
     * @return array
4320
     */
4321
    public static function getProtectedFolderFromStudent()
4322
    {
4323
        return array(
4324
            '/certificates',
4325
            '/HotPotatoes_files',
4326
            '/chat_files',
4327
            '/shared_folder',
4328
            '/learning_path'
4329
        );
4330
    }
4331
4332
    /**
4333
     * @param string $courseCode
4334
     * @return string 'visible' or 'invisible' string
4335
     */
4336
    public static function getDocumentDefaultVisibility($courseCode)
4337
    {
4338
        $settings = api_get_setting('tool_visible_by_default_at_creation');
4339
4340
        $defaultVisibility = 'visible';
4341
4342
        if (isset($settings['documents'])) {
4343
            $portalDefaultVisibility =  'invisible';
4344
            if ($settings['documents'] == 'true') {
4345
                $portalDefaultVisibility = 'visible';
4346
            }
4347
4348
            $defaultVisibility = $portalDefaultVisibility;
4349
        }
4350
4351
        if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
4352
            $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
4353
            if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
4354
                $defaultVisibility = $courseVisibility;
4355
            }
4356
        }
4357
        return $defaultVisibility;
4358
    }
4359
4360
    /**
4361
     * @param array $courseInfo
4362
     * @param int $id doc id
4363
     * @param string $visibility visible/invisible
4364
     * @param int $userId
4365
     */
4366
    public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
4367
    {
4368
        $sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
4369
4370
        if (!empty($sessionList)) {
4371
            foreach ($sessionList as $session) {
4372
                $sessionId = $session['id'];
4373
                api_item_property_update(
4374
                    $courseInfo,
4375
                    TOOL_DOCUMENT,
4376
                    $id,
4377
                    $visibility,
4378
                    $userId,
4379
                    null,
4380
                    null,
4381
                    null,
4382
                    null,
4383
                    $sessionId
4384
                );
4385
            }
4386
        }
4387
    }
4388
4389
    /**
4390
     * @param string $file
4391
     * @return string
4392
     */
4393
    public static function readNanogongFile($file)
4394
    {
4395
        $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
4396
        $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
4397
        $html .= '<param name="SoundFileURL" value="'.$file.'" />';
4398
        $html .= '<param name="ShowSaveButton" value="false" />';
4399
        $html .= '<param name="ShowTime" value="true" />';
4400
        $html .= '<param name="ShowRecordButton" value="false" />';
4401
        $html .= '</applet>';
4402
        return $html;
4403
    }
4404
4405
    /**
4406
     * @param string $filePath
4407
     * @param string $path
4408
     * @param array $courseInfo
4409
     * @param int $sessionId
4410
     * @param string $whatIfFileExists overwrite|rename
4411
     * @param int $userId
4412
     * @param int $groupId
4413
     * @param int $toUserId
4414
     * @param string $comment
4415
     * @return bool|path
4416
     */
4417
    public static function addFileToDocumentTool(
4418
        $filePath,
4419
        $path,
4420
        $courseInfo,
4421
        $sessionId,
4422
        $userId,
4423
        $whatIfFileExists = 'overwrite',
4424
        $groupId = null,
4425
        $toUserId = null,
4426
        $comment = null
4427
    ) {
4428
        if (!file_exists($filePath)) {
4429
            return false;
4430
        }
4431
4432
        $fileInfo = pathinfo($filePath);
4433
4434
        $file = array(
4435
            'name' => $fileInfo['basename'],
4436
            'tmp_name' => $filePath,
4437
            'size' => filesize($filePath),
4438
            'from_file' => true
4439
        );
4440
4441
        $course_dir = $courseInfo['path'].'/document';
4442
        $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
4443
4444
        $filePath = handle_uploaded_document(
4445
            $courseInfo,
4446
            $file,
4447
            $baseWorkDir,
4448
            $path,
4449
            $userId,
4450
            $groupId,
4451
            $toUserId,
4452
            false,
4453
            $whatIfFileExists,
4454
            false,
4455
            false,
4456
            $comment,
4457
            $sessionId
4458
        );
4459
4460
        if ($filePath) {
4461
            return DocumentManager::get_document_id(
4462
                $courseInfo,
4463
                $filePath,
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by handle_uploaded_document..., $comment, $sessionId) on line 4444 can also be of type boolean; however, DocumentManager::get_document_id() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4464
                $sessionId
4465
            );
4466
        }
4467
        return false;
4468
    }
4469
4470
    /**
4471
     * Converts wav to mp3 file.
4472
     * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
4473
     * @param string $wavFile
4474
     * @param bool $removeWavFileIfSuccess
4475
     * @return bool
4476
     */
4477
    public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
4478
    {
4479
        if (file_exists($wavFile)) {
4480
            try {
4481
                $ffmpeg = \FFMpeg\FFMpeg::create();
4482
                $video = $ffmpeg->open($wavFile);
4483
4484
                $mp3File = str_replace('wav', 'mp3', $wavFile);
4485
                $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
4486
                if ($result && $removeWavFileIfSuccess) {
4487
                    unlink($wavFile);
4488
                }
4489
4490
                if (file_exists($mp3File)) {
4491
                    return $mp3File;
4492
                }
4493
            } catch (Exception $e) {
4494
                error_log($e->getMessage());
4495
                error_log($e->getPrevious()->getMessage());
4496
            }
4497
        }
4498
        return false;
4499
    }
4500
4501
    /**
4502
     * @param string $documentData wav document information
4503
     * @param array $courseInfo
4504
     * @param int $sessionId
4505
     * @param int $userId user that adds the document
4506
     * @param string $whatIfFileExists
4507
     * @param bool $deleteWavFile
4508
     *
4509
     * @return bool
4510
     */
4511
    public static function addAndConvertWavToMp3(
4512
        $documentData,
4513
        $courseInfo,
4514
        $sessionId,
4515
        $userId,
4516
        $whatIfFileExists = 'overwrite',
4517
        $deleteWavFile = false
4518
    ) {
4519
        if (empty($documentData)) {
4520
            return false;
4521
        }
4522
4523
        if (isset($documentData['absolute_path']) &&
4524
            file_exists($documentData['absolute_path'])
4525
        ) {
4526
            $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
4527
            error_log($mp3FilePath);
4528
4529
            if (!empty($mp3FilePath) && file_exists($mp3FilePath)) {
4530
4531
                $documentId = self::addFileToDocumentTool(
4532
                    $mp3FilePath,
4533
                    dirname($documentData['path']),
4534
                    $courseInfo,
4535
                    $sessionId,
4536
                    $userId,
4537
                    $whatIfFileExists,
4538
                    null,
4539
                    null,
4540
                    $documentData['comment']
4541
                );
4542
4543 View Code Duplication
                if (!empty($documentId)) {
4544
4545
                    if ($deleteWavFile) {
4546
                        $coursePath = $courseInfo['directory'].'/document';
4547
                        $documentPath = api_get_path(SYS_COURSE_PATH).$coursePath;
4548
                        self::delete_document(
4549
                            $courseInfo,
4550
                            null,
4551
                            $documentPath,
4552
                            $sessionId,
4553
                            $documentData['id']
4554
                        );
4555
                    }
4556
4557
                    return $documentId;
4558
                }
4559
            }
4560
        }
4561
4562
        return false;
4563
    }
4564
4565
    /**
4566
     * Sets
4567
     * @param string $file ($document_data['path'])
4568
     * @param string $file_url_sys
4569
     * @return string
4570
     */
4571
    public static function generateAudioTempFile($file, $file_url_sys)
4572
    {
4573
        //make temp audio
4574
        $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
4575
        if (!file_exists($temp_folder)) {
4576
            @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
4577
        }
4578
4579
        //make htaccess with allow from all, and file index.html into temp/audio
4580
        $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
4581 View Code Duplication
        if (!file_exists($htaccess)) {
4582
            $htaccess_content="order deny,allow\r\nallow from all\r\nOptions -Indexes";
4583
            $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
4584
            if ($fp) {
4585
                fwrite($fp, $htaccess_content);
4586
                fclose($fp);
4587
            }
4588
        }
4589
4590
        //encript temp name file
4591
        $name_crip = sha1(uniqid());//encript
4592
        $findext= explode(".", $file);
4593
        $extension = $findext[count($findext)-1];
4594
        $file_crip = $name_crip.'.'.$extension;
4595
4596
        //copy file to temp/audio directory
4597
        $from_sys = $file_url_sys;
4598
        $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4599
4600
        if (file_exists($from_sys)) {
4601
            copy($from_sys, $to_sys);
4602
        }
4603
4604
        //get  file from tmp directory
4605
        $_SESSION['temp_audio_nanogong'] = $to_sys;
4606
4607
        return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4608
    }
4609
4610
    /**
4611
     * Erase temp nanogong audio.
4612
     */
4613
    public static function removeGeneratedAudioTempFile()
4614
    {
4615 View Code Duplication
        if (isset($_SESSION['temp_audio_nanogong'])
4616
            && !empty($_SESSION['temp_audio_nanogong'])
4617
            && is_file($_SESSION['temp_audio_nanogong'])) {
4618
4619
            unlink($_SESSION['temp_audio_nanogong']);
4620
            unset($_SESSION['temp_audio_nanogong']);
4621
        }
4622
    }
4623
4624
    /**
4625
     * Check if the past is used in this course.
4626
     * @param array $courseInfo
4627
     * @param string $path
4628
     *
4629
     * @return array
4630
     */
4631
    public static function getDocumentByPathInCourse($courseInfo, $path)
4632
    {
4633
        $table = Database::get_course_table(TABLE_DOCUMENT);
4634
        $path = Database::escape_string($path);
4635
        $courseId = $courseInfo['real_id'];
4636
        if (empty($courseId)) {
4637
            return false;
4638
        }
4639
        $sql = "SELECT * FROM $table WHERE c_id = $courseId AND path = '$path'";
4640
        $result = Database::query($sql);
4641
        return Database::store_result($result, 'ASSOC');
4642
    }
4643
4644
    /**
4645
     * @param array $_course
4646
     * @return int
4647
     */
4648
    public static function createDefaultAudioFolder($_course)
4649
    {
4650
        if (!isset($_course['path'])) {
4651
            return false;
4652
        }
4653
4654
        $audioId = null;
4655
        $path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
4656
        if (!is_dir($path.'audio')) {
4657
            mkdir($path.'audio', api_get_permissions_for_new_directories());
4658
            $audioId = add_document($_course, '/audio', 'folder', 0, 'Audio');
4659
            api_item_property_update(
4660
                $_course,
4661
                TOOL_DOCUMENT,
4662
                $audioId,
4663
                'FolderCreated',
4664
                api_get_user_id(),
4665
                null,
4666
                null,
4667
                null,
4668
                null,
4669
                api_get_session_id()
4670
            );
4671
        }
4672
4673
        return $audioId;
4674
    }
4675
4676
    /**
4677
     * Generate a default certificate for a courses
4678
     *
4679
     * @global string $css CSS directory
4680
     * @global string $img_dir image directory
4681
     * @global string $default_course_dir Course directory
4682
     * @global string $js JS directory
4683
     * @param array $courseData The course info
4684
     * @param bool $fromBaseCourse
4685
     * @param int $sessionId
4686
     */
4687
    public static function generateDefaultCertificate($courseData, $fromBaseCourse = false, $sessionId = 0)
4688
    {
4689
        global $css, $img_dir, $default_course_dir, $js;
4690
        $codePath = api_get_path(REL_CODE_PATH);
4691
        $dir = '/certificates';
4692
4693
        $title = get_lang('DefaultCertificate');
4694
        $comment = null;
4695
4696
        $fileName = api_replace_dangerous_char($title);
4697
        $filePath = api_get_path(SYS_COURSE_PATH) . "{$courseData['path']}/document{$dir}";
4698
        $fileFullPath = "{$filePath}/{$fileName}.html";
4699
        $fileSize = 0;
4700
        $fileType = 'file';
4701
        $templateContent = file_get_contents(api_get_path(SYS_CODE_PATH).'gradebook/certificate_template/template.html');
4702
4703
        $search = array('{CSS}', '{IMG_DIR}', '{REL_CODE_PATH}', '{COURSE_DIR}');
4704
        $replace = array($css.$js, $img_dir, $codePath, $default_course_dir);
4705
4706
        $fileContent = str_replace($search, $replace, $templateContent);
4707
4708
        $saveFilePath = "{$dir}/{$fileName}.html";
4709
4710
        if (!is_dir($filePath)) {
4711
            mkdir($filePath, api_get_permissions_for_new_directories());
4712
        }
4713
4714
        if ($fromBaseCourse) {
4715
            $defaultCertificateId = self::get_default_certificate_id($courseData['code'], 0);
4716
4717
            if (!empty($defaultCertificateId)) {
4718
                // We have a certificate from the course base
4719
                $documentData = DocumentManager::get_document_data_by_id(
4720
                    $defaultCertificateId,
4721
                    $courseData['code'],
4722
                    false,
4723
                    0
4724
                );
4725
4726
                if ($documentData) {
4727
                    $fileContent = file_get_contents($documentData['absolute_path']);
4728
                }
4729
            }
4730
        }
4731
4732
        $defaultCertificateFile = $fp = @fopen($fileFullPath, 'w');
4733
4734
        if ($defaultCertificateFile != false) {
4735
            @fputs($defaultCertificateFile, $fileContent);
4736
            fclose($defaultCertificateFile);
4737
            chmod($fileFullPath, api_get_permissions_for_new_files());
4738
4739
            $fileSize = filesize($fileFullPath);
4740
        }
4741
4742
        $documentId = add_document(
4743
            $courseData,
4744
            $saveFilePath,
4745
            $fileType,
4746
            $fileSize,
4747
            $title,
4748
            $comment,
4749
            0,//$readonly = 0,
4750
            true, //$save_visibility = true,
4751
            null, //$group_id = null,
4752
            $sessionId
4753
        );
4754
4755
        api_item_property_update(
4756
            $courseData,
4757
            TOOL_DOCUMENT,
4758
            $documentId,
4759
            'DocumentAdded',
4760
            api_get_user_id(),
4761
            null,
4762
            null,
4763
            null,
4764
            null,
4765
            $sessionId
4766
        );
4767
4768
        $defaultCertificateId = self::get_default_certificate_id(
4769
            $courseData['code'],
4770
            $sessionId
4771
        );
4772
4773
        if (!isset($defaultCertificateId)) {
4774
            self::attach_gradebook_certificate($courseData['code'], $documentId, $sessionId);
4775
        }
4776
    }
4777
4778
    /**
4779
     * Update the document name
4780
     * @param int $documentId The document id
4781
     * @param string $newName The new name
4782
     */
4783
    public static function renameDocument($documentId, $newName)
4784
    {
4785
        $documentId = intval($documentId);
4786
        $newName = Database::escape_string($newName);
4787
4788
        $docuentTable = Database::get_course_table(TABLE_DOCUMENT);
4789
4790
        $values = array(
4791
            'title' => $newName
4792
        );
4793
4794
        $whereConditions = array(
4795
            'id = ?' => $documentId
4796
        );
4797
4798
        Database::update($docuentTable, $values, $whereConditions);
4799
    }
4800
4801
    /**
4802
     * Get folder/file suffix
4803
     *
4804
     * @param array $courseInfo
4805
     * @param int $sessionId
4806
     * @param int $groupId
4807
     *
4808
     * @return string
4809
     */
4810
    public static function getDocumentSuffix($courseInfo, $sessionId, $groupId)
4811
    {
4812
        // If no session or group, then no suffix.
4813
        if (empty($sessionId) && empty($groupId)) {
4814
4815
            return '';
4816
        }
4817
4818
        return '__'.intval($sessionId).'__'.intval($groupId);
4819
    }
4820
4821
    /**
4822
     * Fix a document name adding session id and group id
4823
     * Turns picture.jpg -> picture__1__2.jpg
4824
     * Where 1 = session id and 2 group id
4825
     * Of session id and group id are empty then the function returns:
4826
     * picture.jpg ->  picture.jpg
4827
     *
4828
     * @param string $name folder or file name
4829
     * @param string $type 'folder' or 'file'
4830
     * @param array $courseInfo
4831
     * @param int $sessionId
4832
     * @param int $groupId
4833
     *
4834
     * @return string
4835
     */
4836
    public static function fixDocumentName($name, $type, $courseInfo, $sessionId, $groupId)
4837
    {
4838
        $suffix = self::getDocumentSuffix($courseInfo, $sessionId, $groupId);
4839
4840
        switch ($type) {
4841
            case 'folder':
4842
                $name = $name.$suffix;
4843
                break;
4844
            case 'file':
4845
                $name = self::addSuffixToFileName($name, $suffix);
4846
                break;
4847
        }
4848
4849
        return $name;
4850
    }
4851
4852
    /**
4853
     * Add a suffix to a file Example:
4854
     * /folder/picture.jpg => to /folder/picture_this.jpg
4855
     * where "_this" is the suffix
4856
     * @param string $name
4857
     * @param string $suffix
4858
     * @return string
4859
     */
4860
    public static function addSuffixToFileName($name, $suffix)
4861
    {
4862
        $extension = pathinfo($name, PATHINFO_EXTENSION);
4863
        $fileName = pathinfo($name, PATHINFO_FILENAME);
4864
        $dir = pathinfo($name, PATHINFO_DIRNAME);
4865
4866
        if ($dir == '.') {
4867
            $dir = null;
4868
        }
4869
4870
        if (!empty($dir) && $dir != '/') {
4871
            $dir = $dir.'/';
4872
        }
4873
4874
        $name = $dir.$fileName.$suffix.'.'.$extension;
4875
        return $name;
4876
    }
4877
4878
    /**
4879
     * Check if folder exist in the course base or in the session course
4880
     * @param string $folder Example: /folder/folder2
4881
     * @param array $courseInfo
4882
     * @param int $sessionId
4883
     * @param int $groupId
4884
     *
4885
     * @return bool
4886
     */
4887 View Code Duplication
    public static function folderExists(
4888
        $folder,
4889
        $courseInfo,
4890
        $sessionId,
4891
        $groupId
4892
    ) {
4893
        $courseId = $courseInfo['real_id'];
4894
4895
        if (empty($courseId)) {
4896
            return false;
4897
        }
4898
4899
        $sessionId = intval($sessionId);
4900
        $folderWithSuffix = self::fixDocumentName(
4901
            $folder,
4902
            'folder',
4903
            $courseInfo,
4904
            $sessionId,
4905
            $groupId
4906
        );
4907
4908
        $folder = Database::escape_string($folder);
4909
        $folderWithSuffix = Database::escape_string($folderWithSuffix);
4910
4911
        // Check if pathname already exists inside document table
4912
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
4913
        $sql = "SELECT id, path FROM $tbl_document
4914
                WHERE
4915
                    filetype = 'folder' AND
4916
                    c_id = $courseId AND
4917
                    (path = '$folder' OR path = '$folderWithSuffix') AND
4918
                    (session_id = 0 OR session_id = $sessionId)
4919
        ";
4920
4921
        $rs = Database::query($sql);
4922
        if (Database::num_rows($rs)) {
4923
            return true;
4924
        }
4925
4926
        return false;
4927
    }
4928
4929
    /**
4930
     * Check if file exist in the course base or in the session course
4931
     * @param string $fileName Example: /folder/picture.jpg
4932
     * @param array $courseInfo
4933
     * @param int $sessionId
4934
     * @param int $groupId
4935
     *
4936
     * @return bool
4937
     */
4938 View Code Duplication
    public static function documentExists(
4939
        $fileName,
4940
        $courseInfo,
4941
        $sessionId,
4942
        $groupId
4943
    ) {
4944
        $courseId = $courseInfo['real_id'];
4945
4946
        if (empty($courseId)) {
4947
            return false;
4948
        }
4949
4950
        $sessionId = intval($sessionId);
4951
        $fileNameEscape = Database::escape_string($fileName);
4952
4953
        $fileNameWithSuffix = self::fixDocumentName(
4954
            $fileName,
4955
            'file',
4956
            $courseInfo,
4957
            $sessionId,
4958
            $groupId
4959
        );
4960
4961
        $fileNameWithSuffix = Database::escape_string($fileNameWithSuffix);
4962
4963
        // Check if pathname already exists inside document table
4964
        $table = Database::get_course_table(TABLE_DOCUMENT);
4965
        $sql = "SELECT id, path FROM $table
4966
                WHERE
4967
                    filetype = 'file' AND
4968
                    c_id = $courseId AND
4969
                    (
4970
                        path = '".$fileNameEscape."' OR
4971
                        path = '$fileNameWithSuffix'
4972
                    ) AND
4973
                    (session_id = 0 OR session_id = $sessionId)
4974
        ";
4975
        $rs = Database::query($sql);
4976
        if (Database::num_rows($rs)) {
4977
            return true;
4978
        }
4979
4980
        return false;
4981
    }
4982
4983
    /**
4984
     * Undo the suffix applied to a file example:
4985
     * turns picture__1__1.jpg to picture.jpg
4986
     * @param string $name
4987
     * @param int $courseId
4988
     * @param int $sessionId
4989
     * @param int $groupId
4990
     *
4991
     * @return string
4992
     */
4993
    public static function undoFixDocumentName(
4994
        $name,
4995
        $courseId,
4996
        $sessionId,
4997
        $groupId
4998
    ) {
4999
        if (empty($sessionId) && empty($groupId)) {
5000
            return $name;
5001
        }
5002
5003
        $suffix = self::getDocumentSuffix(
5004
            array('real_id' => $courseId),
5005
            $sessionId,
5006
            $groupId
5007
        );
5008
5009
        $name = str_replace($suffix, '', $name);
5010
5011
        return $name;
5012
    }
5013
5014
    /**
5015
     * @param string $path
5016
     * @param string $name
5017
     * @param array $courseInfo
5018
     * @param int $sessionId
5019
     * @param int $groupId
5020
     *
5021
     * @return string
5022
     */
5023
    public static function getUniqueFileName($path, $name, $courseInfo, $sessionId, $groupId)
5024
    {
5025
        $counter = 1;
5026
        $filePath = $path.$name;
5027
        $uniqueName = $name;
5028
        while ($documentExists = self::documentExists(
5029
            $filePath,
5030
            $courseInfo,
5031
            $sessionId,
5032
            $groupId
5033
        )) {
5034
            $uniqueName = self::addSuffixToFileName($name, '_' . $counter);
5035
            $filePath = $path . $uniqueName;
5036
            $counter++;
5037
        }
5038
5039
        return $uniqueName;
5040
    }
5041
5042
5043
    /**
5044
     * Builds the form that enables the user to
5045
     * select a directory to browse/upload in
5046
     *
5047
     * @param array 	An array containing the folders we want to be able to select
5048
     * @param string	The current folder (path inside of the "document" directory, including the prefix "/")
5049
     * @param string	Group directory, if empty, prevents documents to be uploaded (because group documents cannot be uploaded in root)
5050
     * @param	boolean	Whether to change the renderer (this will add a template <span> to the QuickForm object displaying the form)
5051
     * @todo this funcionality is really bad : jmontoya
5052
     * @return string html form
5053
     */
5054
    public static function build_directory_selector($folders, $document_id, $group_dir = '', $change_renderer = false)
5055
    {
5056
        $doc_table = Database::get_course_table(TABLE_DOCUMENT);
5057
        $course_id = api_get_course_int_id();
5058
        $folder_titles = array();
5059
5060
        if (is_array($folders)) {
5061
            $escaped_folders = array();
5062
            foreach ($folders as $key => & $val) {
5063
                $escaped_folders[$key] = Database::escape_string($val);
5064
            }
5065
            $folder_sql = implode("','", $escaped_folders);
5066
5067
            $sql = "SELECT * FROM $doc_table
5068
                WHERE filetype = 'folder' AND c_id = $course_id AND path IN ('" . $folder_sql . "')";
5069
            $res = Database::query($sql);
5070
            $folder_titles = array();
5071
            while ($obj = Database::fetch_object($res)) {
5072
                $folder_titles[$obj->path] = $obj->title;
5073
            }
5074
        }
5075
5076
        $form = new FormValidator('selector', 'GET', api_get_self() . '?' . api_get_cidreq());
5077
        $form->addElement('hidden', 'cidReq', api_get_course_id());
5078
        $parent_select = $form->addSelect('id', get_lang('CurrentDirectory'), '', array('onchange' => 'javascript: document.selector.submit();'));
5079
5080
        if ($change_renderer) {
5081
            $renderer = $form->defaultRenderer();
5082
            $renderer->setElementTemplate('<span>{label} : {element}</span> ', 'curdirpath');
5083
        }
5084
5085
        // Group documents cannot be uploaded in the root
5086
        if (empty($group_dir)) {
5087
            $parent_select->addOption(get_lang('Documents'), '/');
5088
5089
            if (is_array($folders)) {
5090
                foreach ($folders as $folder_id => & $folder) {
5091
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5092
                    $path_parts = explode('/', $folder);
5093
                    $folder_titles[$folder] = cut($folder_titles[$folder], 80);
5094
                    $counter = count($path_parts) - 2;
5095 View Code Duplication
                    if ($counter > 0) {
5096
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', $counter) . ' &mdash; ' . $folder_titles[$folder];
5097
                    } else {
5098
                        $label = ' &mdash; ' . $folder_titles[$folder];
5099
                    }
5100
                    $parent_select->addOption($label, $folder_id);
5101
                    if ($selected != '') {
5102
                        $parent_select->setSelected($folder_id);
5103
                    }
5104
                }
5105
            }
5106
        } else {
5107
            if (!empty($folders)) {
5108
                foreach ($folders as $folder_id => & $folder) {
5109
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5110
                    $label = $folder_titles[$folder];
5111 View Code Duplication
                    if ($folder == $group_dir) {
5112
                        $label = get_lang('Documents');
5113
                    } else {
5114
                        $path_parts = explode('/', str_replace($group_dir, '', $folder));
5115
                        $label = cut($label, 80);
5116
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', count($path_parts) - 2) . ' &mdash; ' . $label;
5117
                    }
5118
                    $parent_select->addOption($label, $folder_id);
5119
                    if ($selected != '') {
5120
                        $parent_select->setSelected($folder_id);
5121
                    }
5122
                }
5123
            }
5124
        }
5125
        $html = $form->toHtml();
5126
5127
        return $html;
5128
    }
5129
5130
    /**
5131
     * Create a html hyperlink depending on if it's a folder or a file
5132
     *
5133
     * @param array $document_data
5134
     * @param int $show_as_icon - if it is true, only a clickable icon will be shown
5135
     * @param int $visibility (1/0)
5136
     * @param int $counter
5137
     *
5138
     * @return string url
5139
     */
5140
    public static function create_document_link(
5141
        $document_data,
5142
        $show_as_icon = false,
5143
        $counter = null,
5144
        $visibility
5145
    ) {
5146
        global $dbl_click_id;
5147
        $course_info = api_get_course_info();
5148
        $www = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/document';
5149
        $webOdflist = DocumentManager::get_web_odf_extension_list();
5150
5151
        // Get the title or the basename depending on what we're using
5152 View Code Duplication
        if ($document_data['title'] != '') {
5153
            $title = $document_data['title'];
5154
        } else {
5155
            $title = basename($document_data['path']);
5156
        }
5157
5158
        $filetype = $document_data['filetype'];
5159
        $size = $filetype == 'folder' ? get_total_folder_size($document_data['path'], api_is_allowed_to_edit(null, true)) : $document_data['size'];
5160
        $path = $document_data['path'];
5161
5162
        $url_path = urlencode($document_data['path']);
5163
5164
        // Add class="invisible" on invisible files
5165
        $visibility_class = ($visibility == false) ? ' class="muted"' : '';
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $visibility of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
5166
        $forcedownload_link = null;
5167
        $forcedownload_icon = null;
5168
        $prevent_multiple_click = null;
5169
5170
        if (!$show_as_icon) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $show_as_icon of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
5171
            // Build download link (icon)
5172
            $forcedownload_link = ($filetype == 'folder') ? api_get_self() . '?' . api_get_cidreq() . '&action=downloadfolder&id=' . $document_data['id'] : api_get_self() . '?' . api_get_cidreq() . '&amp;action=download&amp;id=' . $document_data['id'];
5173
            // Folder download or file download?
5174
            $forcedownload_icon = ($filetype == 'folder') ? 'save_pack.png' : 'save.png';
5175
            // Prevent multiple clicks on zipped folder download
5176
            $prevent_multiple_click = ($filetype == 'folder') ? " onclick=\"javascript: if(typeof clic_$dbl_click_id == 'undefined' || !clic_$dbl_click_id) { clic_$dbl_click_id=true; window.setTimeout('clic_" . ($dbl_click_id++) . "=false;',10000); } else { return false; }\"" : '';
5177
        }
5178
5179
        $target = '_self';
5180
        $is_browser_viewable_file = false;
5181
5182
        if ($filetype == 'file') {
5183
            // Check the extension
5184
            $ext = explode('.', $path);
5185
            $ext = strtolower($ext[sizeof($ext) - 1]);
5186
5187
            // HTML-files an some other types are shown in a frameset by default.
5188
            $is_browser_viewable_file = self::is_browser_viewable($ext);
5189
5190
            if ($is_browser_viewable_file) {
5191
                if ($ext == 'pdf' || in_array($ext, $webOdflist)) {
5192
                    $url = api_get_self() . '?' . api_get_cidreq() . '&amp;action=download&amp;id=' . $document_data['id'];
5193
                } else {
5194
                    $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5195
                }
5196
            } else {
5197
                // url-encode for problematic characters (we may not call them dangerous characters...)
5198
                $path = str_replace('%2F', '/', $url_path) . '?' . api_get_cidreq();
5199
                $url = $www . $path;
5200
            }
5201
5202
            /*$path = str_replace('%2F', '/', $url_path); //yox view hack otherwise the image can't be well read
5203
            $url = $www . $path;*/
5204
        } else {
5205
            $url = api_get_self() . '?' . api_get_cidreq() . '&id=' . $document_data['id'];
5206
        }
5207
5208
        // The little download icon
5209
        $tooltip_title = $title;
5210
5211
        $tooltip_title_alt = $tooltip_title;
5212
        if ($path == '/shared_folder') {
5213
            $tooltip_title_alt = get_lang('UserFolders');
5214
        } elseif (strstr($path, 'shared_folder_session_')) {
5215
            $tooltip_title_alt = get_lang('UserFolders') . ' (' . api_get_session_name(api_get_session_id()) . ')';
5216
        } elseif (strstr($tooltip_title, 'sf_user_')) {
5217
            $userinfo = api_get_user_info(substr($tooltip_title, 8));
5218
            $tooltip_title_alt = get_lang('UserFolder') . ' ' . $userinfo['complete_name'];
5219
        } elseif ($path == '/chat_files') {
5220
            $tooltip_title_alt = get_lang('ChatFiles');
5221
        } elseif ($path == '/learning_path') {
5222
            $tooltip_title_alt = get_lang('LearningPaths');
5223
        } elseif ($path == '/video') {
5224
            $tooltip_title_alt = get_lang('Video');
5225
        } elseif ($path == '/audio') {
5226
            $tooltip_title_alt = get_lang('Audio');
5227
        } elseif ($path == '/flash') {
5228
            $tooltip_title_alt = get_lang('Flash');
5229
        } elseif ($path == '/images') {
5230
            $tooltip_title_alt = get_lang('Images');
5231
        } elseif ($path == '/images/gallery') {
5232
            $tooltip_title_alt = get_lang('DefaultCourseImages');
5233
        }
5234
5235
        $current_session_id = api_get_session_id();
5236
        $copy_to_myfiles = $open_in_new_window_link = null;
5237
5238
        $curdirpath = isset($_GET['curdirpath']) ? Security::remove_XSS($_GET['curdirpath']) : null;
5239
        $send_to = null;
5240
5241
        $checkExtension = $path;
5242
5243
        if (!$show_as_icon) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $show_as_icon of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
5244
            if ($filetype == 'folder') {
5245
                if (api_is_allowed_to_edit() ||
5246
                    api_is_platform_admin() ||
5247
                    api_get_setting('students_download_folders') == 'true'
5248
                ) {
5249
                    //filter when I am into shared folder, I can show for donwload only my shared folder
5250
                    if (DocumentManager::is_shared_folder($curdirpath, $current_session_id)) {
5251
                        if (preg_match('/shared_folder\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5252
                            preg_match('/shared_folder_session_' . $current_session_id . '\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5253
                            api_is_allowed_to_edit() || api_is_platform_admin()
5254
                        ) {
5255
                            $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5256
                                Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5257
                        }
5258
                    } elseif (!preg_match('/shared_folder/', urldecode($forcedownload_link)) ||
5259
                        api_is_allowed_to_edit() ||
5260
                        api_is_platform_admin()
5261
                    ) {
5262
                        $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5263
                            Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5264
                    }
5265
                }
5266 View Code Duplication
            } else {
5267
                $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5268
                    Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5269
            }
5270
5271
            // Copy files to users myfiles
5272
            if (api_get_setting('allow_social_tool') == 'true' &&
5273
                api_get_setting('users_copy_files') == 'true' &&
5274
                !api_is_anonymous()
5275
            ) {
5276
                $copy_myfiles_link = ($filetype == 'file') ? api_get_self() . '?' . api_get_cidreq() . '&action=copytomyfiles&id=' . $document_data['id'] : api_get_self() . '?' . api_get_cidreq();
5277
5278 View Code Duplication
                if ($filetype == 'file') {
5279
5280
                    $copy_to_myfiles = '<a href="' . $copy_myfiles_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5281
                        Display::return_icon('briefcase.png', get_lang('CopyToMyFiles'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5282
5283
                    if (api_get_setting('allow_my_files') === 'false') {
5284
                        $copy_to_myfiles = '';
5285
                    }
5286
                }
5287
5288
                if ($filetype == 'file') {
5289
                    $send_to = Portfolio::share('document', $document_data['id'], array('style' => 'float:right;'));
5290
                }
5291
            }
5292
5293
            $pdf_icon = '';
5294
            $extension = pathinfo($path, PATHINFO_EXTENSION);
5295
            if (!api_is_allowed_to_edit() &&
5296
                api_get_setting('students_export2pdf') == 'true' &&
5297
                $filetype == 'file' &&
5298
                in_array($extension, array('html', 'htm'))
5299
            ) {
5300
                $pdf_icon = ' <a style="float:right".' . $prevent_multiple_click . ' href="' . api_get_self() . '?' . api_get_cidreq() . '&action=export_to_pdf&id=' . $document_data['id'] . '">' .
5301
                    Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a> ';
5302
            }
5303
5304 View Code Duplication
            if ($is_browser_viewable_file) {
5305
                $open_in_new_window_link = '<a href="' . $www . str_replace('%2F', '/', $url_path) . '?' . api_get_cidreq() . '" style="float:right"' . $prevent_multiple_click . ' target="_blank">' .
5306
                    Display::return_icon('open_in_new_window.png', get_lang('OpenInANewWindow'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5307
            }
5308
5309
            if ($filetype == 'file') {
5310
                // Sound preview with jplayer
5311
                if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5312
                    (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5313
                    preg_match('/ogg$/i', urldecode($checkExtension))
5314
                ) {
5315
                    return '<span style="float:left" ' . $visibility_class . '>' .
5316
                    $title .
5317
                    '</span>' . $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5318
                } elseif (
5319
5320
                    // Show preview
5321
                    preg_match('/swf$/i', urldecode($checkExtension)) ||
5322
                    preg_match('/png$/i', urldecode($checkExtension)) ||
5323
                    preg_match('/gif$/i', urldecode($checkExtension)) ||
5324
                    preg_match('/jpg$/i', urldecode($checkExtension)) ||
5325
                    preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5326
                    preg_match('/bmp$/i', urldecode($checkExtension)) ||
5327
                    preg_match('/svg$/i', urldecode($checkExtension)) ||
5328
                    (
5329
                        preg_match('/wav$/i', urldecode($checkExtension)) &&
5330
                        preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5331
                        api_get_setting('enable_nanogong') == 'true'
5332
                    )
5333
                ) {
5334
                    // Simpler version of showinframesmin.php with no headers
5335
                    $url = 'show_content.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5336
                    $class = 'ajax';
5337
                    if ($visibility == false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $visibility of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
5338
                        $class = "ajax invisible";
5339
                    }
5340
                    return Display::url(
5341
                        $title,
5342
                        $url,
5343
                        [
5344
                            'class' => $class,
5345
                            'title' => $tooltip_title_alt,
5346
                            'data-title' => $title,
5347
                            'style' => 'float: left;'
5348
                        ]
5349
                    )
5350
                    . $force_download_html . $send_to . $copy_to_myfiles
5351
                    . $open_in_new_window_link . $pdf_icon;
5352
                } else {
5353
                    // For PDF Download the file.
5354
                    $pdfPreview = null;
5355
                    if ($ext != 'pdf' && !in_array($ext, $webOdflist)) {
5356
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5357
                    } else {
5358
                        $pdfPreview = Display::url(
5359
                            Display::return_icon('preview.gif', get_lang('Preview')),
5360
                            api_get_path(WEB_CODE_PATH).'document/showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'],
5361
                            array('style' => 'float:right')
5362
                        );
5363
                    }
5364
                    // No plugin just the old and good showinframes.php page
5365
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" style="float:left" ' . $visibility_class . ' >' . $title . '</a>' .
5366
                    $pdfPreview.$force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5367
                }
5368
            } else {
5369
                return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' . $title . '</a>' .
5370
                $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5371
            }
5372
            // end copy files to users myfiles
5373
        } else {
5374
            // Icon column
5375
            if (preg_match('/shared_folder/', urldecode($checkExtension)) &&
5376
                preg_match('/shared_folder$/', urldecode($checkExtension)) == false &&
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing preg_match('/shared_fold...ecode($checkExtension)) of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
5377
                preg_match('/shared_folder_session_' . $current_session_id . '$/', urldecode($url)) == false
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing preg_match('/shared_fold... '$/', urldecode($url)) of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
5378
            ) {
5379
                if ($filetype == 'file') {
5380
                    //Sound preview with jplayer
5381
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5382
                        (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5383
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5384
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5385
5386
                        return $sound_preview;
5387
                    } elseif (
5388
                        // Show preview
5389
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5390
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5391
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5392
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5393
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5394
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5395
                        preg_match('/svg$/i', urldecode($checkExtension)) ||
5396
                        (
5397
                            preg_match('/wav$/i', urldecode($checkExtension)) &&
5398
                            preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5399
                            api_get_setting('enable_nanogong') == 'true'
5400
                        )
5401
                    ) {
5402
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5403
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5404
                        DocumentManager::build_document_icon_tag($filetype, $path) .
5405
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5406 View Code Duplication
                    } else {
5407
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5408
                        DocumentManager::build_document_icon_tag($filetype, $path) .
5409
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5410
                    }
5411 View Code Duplication
                } else {
5412
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5413
                    DocumentManager::build_document_icon_tag($filetype, $path) .
5414
                    Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5415
                }
5416
            } else {
5417
                if ($filetype == 'file') {
5418
                    // Sound preview with jplayer
5419
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5420
                        (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5421
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5422
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5423
5424
                        return $sound_preview;
5425
                    } elseif (
5426
                        //Show preview
5427
                        preg_match('/html$/i', urldecode($checkExtension)) ||
5428
                        preg_match('/htm$/i', urldecode($checkExtension)) ||
5429
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5430
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5431
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5432
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5433
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5434
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5435
                        preg_match('/svg$/i', urldecode($checkExtension)) ||
5436
                        (
5437
                            preg_match('/wav$/i', urldecode($checkExtension)) &&
5438
                            preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5439
                            api_get_setting('enable_nanogong') == 'true'
5440
                        )
5441
                    ) {
5442
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id']; //without preview
5443
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5444
                        DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5445 View Code Duplication
                    } else {
5446
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5447
                        DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5448
                    }
5449 View Code Duplication
                } else {
5450
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5451
                    DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5452
                }
5453
            }
5454
        }
5455
    }
5456
5457
    /**
5458
     * Builds an img html tag for the file type
5459
     *
5460
     * @param string $type (file/folder)
5461
     * @param string $path
5462
     * @return string img html tag
5463
     */
5464
    public static function build_document_icon_tag($type, $path)
5465
    {
5466
        $basename = basename($path);
5467
        $current_session_id = api_get_session_id();
5468
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
5469
        $user_image = false;
5470
        if ($type == 'file') {
5471
            $icon = choose_image($basename);
5472
5473
            if (preg_match('/_chnano_.wav$/i', $basename)) {
5474
                $icon = "jplayer_play.png";
5475
                $basename = 'wav' . ' ' . '(Nanogong)';
5476
            } else {
5477
                $basename = substr(strrchr($basename, '.'), 1);
5478
            }
5479
        } else {
5480
            if ($path == '/shared_folder') {
5481
                $icon = 'folder_users.gif';
5482
                if ($is_allowed_to_edit) {
5483
                    $basename = get_lang('HelpUsersFolder');
5484
                } else {
5485
                    $basename = get_lang('UserFolders');
5486
                }
5487
            } elseif (strstr($basename, 'sf_user_')) {
5488
                $userinfo = api_get_user_info(substr($basename, 8));
5489
                $icon = $userinfo['avatar_small'];
5490
5491
                $basename = get_lang('UserFolder') . ' ' . $userinfo['complete_name'];
5492
                $user_image = true;
5493
            } elseif (strstr($path, 'shared_folder_session_')) {
5494
                if ($is_allowed_to_edit) {
5495
                    $basename = '***(' . api_get_session_name($current_session_id) . ')*** ' . get_lang('HelpUsersFolder');
5496
                } else {
5497
                    $basename = get_lang('UserFolders') . ' (' . api_get_session_name($current_session_id) . ')';
5498
                }
5499
                $icon = 'folder_users.gif';
5500
            } else {
5501
                $icon = 'folder_document.gif';
5502
5503
                if ($path == '/audio') {
5504
                    $icon = 'folder_audio.gif';
5505
                    if (api_is_allowed_to_edit()) {
5506
                        $basename = get_lang('HelpDefaultDirDocuments');
5507
                    } else {
5508
                        $basename = get_lang('Audio');
5509
                    }
5510 View Code Duplication
                } elseif ($path == '/flash') {
5511
                    $icon = 'folder_flash.gif';
5512
                    if (api_is_allowed_to_edit()) {
5513
                        $basename = get_lang('HelpDefaultDirDocuments');
5514
                    } else {
5515
                        $basename = get_lang('Flash');
5516
                    }
5517
                } elseif ($path == '/images') {
5518
                    $icon = 'folder_images.gif';
5519
                    if (api_is_allowed_to_edit()) {
5520
                        $basename = get_lang('HelpDefaultDirDocuments');
5521
                    } else {
5522
                        $basename = get_lang('Images');
5523
                    }
5524 View Code Duplication
                } elseif ($path == '/video') {
5525
                    $icon = 'folder_video.gif';
5526
                    if (api_is_allowed_to_edit()) {
5527
                        $basename = get_lang('HelpDefaultDirDocuments');
5528
                    } else {
5529
                        $basename = get_lang('Video');
5530
                    }
5531
                } elseif ($path == '/images/gallery') {
5532
                    $icon = 'folder_gallery.gif';
5533
                    if (api_is_allowed_to_edit()) {
5534
                        $basename = get_lang('HelpDefaultDirDocuments');
5535
                    } else {
5536
                        $basename = get_lang('Gallery');
5537
                    }
5538
                } elseif ($path == '/chat_files') {
5539
                    $icon = 'folder_chat.png';
5540
                    if (api_is_allowed_to_edit()) {
5541
                        $basename = get_lang('HelpFolderChat');
5542
                    } else {
5543
                        $basename = get_lang('ChatFiles');
5544
                    }
5545
                } elseif ($path == '/learning_path') {
5546
                    $icon = 'folder_learningpath.gif';
5547
                    if (api_is_allowed_to_edit()) {
5548
                        $basename = get_lang('HelpFolderLearningPaths');
5549
                    } else {
5550
                        $basename = get_lang('LearningPaths');
5551
                    }
5552
                }
5553
            }
5554
        }
5555
        if ($user_image) {
5556
            return Display::img($icon, $basename, array(), false);
5557
        }
5558
        return Display::return_icon($icon, $basename, array());
5559
    }
5560
5561
    /**
5562
     * Creates the row of edit icons for a file/folder
5563
     *
5564
     * @param string $curdirpath current path (cfr open folder)
0 ignored issues
show
Bug introduced by
There is no parameter named $curdirpath. 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...
5565
     * @param string $type (file/folder)
0 ignored issues
show
Bug introduced by
There is no parameter named $type. 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...
5566
     * @param string $path dbase path of file/folder
0 ignored issues
show
Bug introduced by
There is no parameter named $path. 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...
5567
     * @param int $visibility (1/0)
5568
     * @param int $id dbase id of the document
5569
     * @return string html img tags with hyperlinks
5570
     */
5571
    public static function build_edit_icons($document_data, $id, $is_template, $is_read_only = 0, $visibility)
5572
    {
5573
        $web_odf_extension_list = DocumentManager::get_web_odf_extension_list();
5574
        $document_id = $document_data['id'];
5575
        $type = $document_data['filetype'];
5576
        $is_read_only = $document_data['readonly'];
5577
        $path = $document_data['path'];
5578
        $parent_id = DocumentManager::get_document_id(api_get_course_info(), dirname($path));
5579
        $curdirpath = dirname($document_data['path']);
5580
        $is_certificate_mode = DocumentManager::is_certificate_mode($path);
5581
        $curdirpath = urlencode($curdirpath);
5582
        $extension = pathinfo($path, PATHINFO_EXTENSION);
5583
        //@todo Implement remote support for converter
5584
        $usePpt2lp = (api_get_setting('service_ppt2lp', 'active') == 'true' && api_get_setting('service_ppt2lp', 'host') == 'localhost');
5585
        $formatTypeList = DocumentManager::getFormatTypeListConvertor('from', $extension);
5586
        $formatType = current($formatTypeList);
5587
5588
        // Build URL-parameters for table-sorting
5589
        $sort_params = array();
5590
        if (isset($_GET['column'])) {
5591
            $sort_params[] = 'column=' . Security::remove_XSS($_GET['column']);
5592
        }
5593
        if (isset($_GET['page_nr'])) {
5594
            $sort_params[] = 'page_nr=' . Security::remove_XSS($_GET['page_nr']);
5595
        }
5596
        if (isset($_GET['per_page'])) {
5597
            $sort_params[] = 'per_page=' . Security::remove_XSS($_GET['per_page']);
5598
        }
5599
        if (isset($_GET['direction'])) {
5600
            $sort_params[] = 'direction=' . Security::remove_XSS($_GET['direction']);
5601
        }
5602
        $sort_params = implode('&amp;', $sort_params);
5603
        $visibility_icon = ($visibility == 0) ? 'invisible' : 'visible';
5604
        $visibility_command = ($visibility == 0) ? 'set_visible' : 'set_invisible';
5605
5606
        $modify_icons = '';
5607
5608
        // If document is read only *or* we're in a session and the document
5609
        // is from a non-session context, hide the edition capabilities
5610
        if ($is_read_only /* or ($session_id!=api_get_session_id()) */) {
5611
            if (api_is_course_admin() || api_is_platform_admin()) {
5612 View Code Duplication
                if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5613
                    $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5614
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5615
                } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5616
                    $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5617
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5618
                } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5619
                    $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5620
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5621
                } else {
5622
                    $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&id=' . $document_id. '">' .
5623
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5624
                }
5625
            } else {
5626
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5627
            }
5628
            $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL);
5629
            if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5630
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), '', ICON_SIZE_SMALL);
5631
            }
5632
            $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('Delete'), array(), ICON_SIZE_SMALL);
5633
        } else {
5634
            //Edit button
5635
            if (in_array($path, DocumentManager::get_system_folders())) {
5636
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5637 View Code Duplication
            } elseif ($is_certificate_mode ) {
5638
                // gradebook category doesn't seem to be taken into account
5639
                $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id . '&curdirpath=/certificates">' . Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5640
            } else {
5641
                if (api_get_session_id()) {
5642
                    if ($document_data['session_id'] == api_get_session_id()) {
5643 View Code Duplication
                        if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5644
                            $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5645
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5646
                        } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5647
                            $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5648
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5649
                        } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5650
                            $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5651
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5652
                        } else {
5653
                            $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5654
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5655
                        }
5656
                    } else {
5657
                        $modify_icons .= '&nbsp;' . Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>';
5658
                    }
5659 View Code Duplication
                } else {
5660
                    if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5661
                        $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5662
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5663
                    } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5664
                        $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5665
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5666
                    } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5667
                        $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&amp;id=' . $document_id . '">' .
5668
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5669
                    } else {
5670
                        $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5671
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5672
                    }
5673
                }
5674
            }
5675
5676
            // Move button.
5677
            if ($is_certificate_mode || in_array($path, DocumentManager::get_system_folders())) {
5678
                $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5679
            } else {
5680
                if (api_get_session_id()) {
5681
                    if ($document_data['session_id'] == api_get_session_id()) {
5682
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5683
                            Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5684
                    } else {
5685
                        $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5686
                    }
5687
                } else {
5688
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5689
                        Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5690
                }
5691
            }
5692
5693
            //Visibility button
5694
            if ($is_certificate_mode) {
5695
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), array(), ICON_SIZE_SMALL) . '</a>';
5696
            } else {
5697
                if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5698
                    if ($visibility_icon == 'invisible') {
5699
                        $tip_visibility = get_lang('Show');
5700
                    } else {
5701
                        $tip_visibility = get_lang('Hide');
5702
                    }
5703
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;' . $visibility_command . '=' . $id . '&amp;' . $sort_params . '">' .
5704
                        Display::return_icon($visibility_icon . '.png', $tip_visibility, '', ICON_SIZE_SMALL) . '</a>';
5705
                }
5706
            }
5707
5708
            // Delete button
5709
            if (in_array($path, DocumentManager::get_system_folders())) {
5710
                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5711
            } else {
5712
                $titleToShow = addslashes(basename($document_data['title']));
5713
5714
                if (isset($_GET['curdirpath']) &&
5715
                    $_GET['curdirpath'] == '/certificates' &&
5716
                    DocumentManager::get_default_certificate_id(api_get_course_id()) == $id
5717
                ) {
5718
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;' . $sort_params . 'delete_certificate_id=' . $id . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5719
                        Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5720
                } else {
5721
                    if ($is_certificate_mode) {
5722
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid=' . $document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5723
                            Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5724
                    } else {
5725
                        if (api_get_session_id()) {
5726
                            if ($document_data['session_id'] == api_get_session_id()) {
5727
                                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">'.
5728
                                    Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5729
                            } else {
5730
                                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5731
                            }
5732
                        } else {
5733
                            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow. '\');">' .
5734
                                Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5735
                        }
5736
                    }
5737
                }
5738
            }
5739
5740
            // Add action to covert to PDF, will create a new document whit same filename but .pdf extension
5741
            // @TODO: add prompt to select a format target
5742
            if (in_array($path, DocumentManager::get_system_folders())) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
5743
                // nothing to do
5744 View Code Duplication
            } else {
5745
                if ($usePpt2lp && $formatType) {
5746
                    $modify_icons .= '&nbsp;<a class="convertAction" href="#" ' .
5747
                        'data-documentId = ' . $document_id .
5748
                        ' data-formatType = ' . $formatType . '>' .
5749
                        Display::return_icon(
5750
                            'convert.png',
5751
                            get_lang('Convert'),
5752
                            array(),
5753
                            ICON_SIZE_SMALL
5754
                        ) . '</a>';
5755
                }
5756
            }
5757
        }
5758
5759
        if ($type == 'file' && ($extension == 'html' || $extension == 'htm')) {
5760
            if ($is_template == 0) {
5761
                if ((isset($_GET['curdirpath']) && $_GET['curdirpath'] != '/certificates') || !isset($_GET['curdirpath'])) {
5762
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;add_as_template=' . $id .  '&amp;' . $sort_params . '">' .
5763
                        Display::return_icon('wizard.png', get_lang('AddAsTemplate'), array(), ICON_SIZE_SMALL) . '</a>';
5764
                }
5765
                if (isset($_GET['curdirpath']) && $_GET['curdirpath'] == '/certificates') {//allow attach certificate to course
5766
                    $visibility_icon_certificate = 'nocertificate';
5767
                    if (DocumentManager::get_default_certificate_id(api_get_course_id()) == $id) {
5768
                        $visibility_icon_certificate = 'certificate';
5769
                        $certificate = get_lang('DefaultCertificate');
5770
                        $preview = get_lang('PreviewCertificate');
5771
                        $is_preview = true;
5772
                    } else {
5773
                        $is_preview = false;
5774
                        $certificate = get_lang('NoDefaultCertificate');
5775
                    }
5776
                    if (isset($_GET['selectcat'])) {
5777
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;selectcat=' . intval($_GET['selectcat']) . '&amp;set_certificate=' . $id . '&amp;' . $sort_params . '">';
5778
                        $modify_icons .= Display::return_icon($visibility_icon_certificate.'.png', $certificate);
5779
                        $modify_icons .= '</a>';
5780
                        if ($is_preview) {
5781
                            $modify_icons .= '&nbsp;<a target="_blank"  href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;set_preview=' . $id . '&amp;' . $sort_params . '" >' .
5782
                                Display::return_icon('preview_view.png', $preview, '', ICON_SIZE_SMALL) . '</a>';
5783
                        }
5784
                    }
5785
                }
5786
            } else {
5787
                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&curdirpath=' . $curdirpath . '&amp;remove_as_template=' . $id. '&amp;' . $sort_params . '">' .
5788
                    Display::return_icon('wizard_na.png', get_lang('RemoveAsTemplate'), '', ICON_SIZE_SMALL) . '</a>';
5789
            }
5790
            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&action=export_to_pdf&id=' . $id . '">' .
5791
                Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a>';
5792
        }
5793
        return $modify_icons;
5794
    }
5795
5796
    /**
5797
     * @param $folders
5798
     * @param $curdirpath
5799
     * @param $move_file
5800
     * @param string $group_dir
5801
     * @return string
5802
     */
5803
    public static function build_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
5804
    {
5805
        $form = new FormValidator('move_to', 'post', api_get_self().'?'.api_get_cidreq());
5806
5807
        // Form title
5808
        $form->addElement('hidden', 'move_file', $move_file);
5809
5810
        $options = array();
5811
5812
        // Group documents cannot be uploaded in the root
5813
        if ($group_dir == '') {
5814
            if ($curdirpath != '/') {
5815
                $options['/'] = get_lang('Documents');
5816
            }
5817
5818
            if (is_array($folders)) {
5819
                foreach ($folders as & $folder) {
5820
                    // Hide some folders
5821
                    if ($folder == '/HotPotatoes_files' ||
5822
                        $folder == '/certificates' ||
5823
                        basename($folder) == 'css'
5824
                    ) {
5825
                        continue;
5826
                    }
5827
                    // Admin setting for Hide/Show the folders of all users
5828 View Code Duplication
                    if (api_get_setting('show_users_folders') == 'false' &&
5829
                        (strstr($folder, '/shared_folder') || strstr($folder, 'shared_folder_session_'))
5830
                    ) {
5831
                        continue;
5832
                    }
5833
5834
                    // Admin setting for Hide/Show Default folders to all users
5835 View Code Duplication
                    if (api_get_setting('show_default_folders') == 'false' &&
5836
                        (
5837
                            $folder == '/images' ||
5838
                            $folder == '/flash' ||
5839
                            $folder == '/audio' ||
5840
                            $folder == '/video' ||
5841
                            strstr($folder, '/images/gallery') ||
5842
                            $folder == '/video/flv'
5843
                        )
5844
                    ) {
5845
                        continue;
5846
                    }
5847
5848
                    // Admin setting for Hide/Show chat history folder
5849
                    if (api_get_setting('show_chat_folder') == 'false' &&
5850
                        $folder == '/chat_files') {
5851
                        continue;
5852
                    }
5853
5854
                    // You cannot move a file to:
5855
                    // 1. current directory
5856
                    // 2. inside the folder you want to move
5857
                    // 3. inside a subfolder of the folder you want to move
5858
                    if (($curdirpath != $folder) &&
5859
                        ($folder != $move_file) &&
5860
                        (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5861
                    ) {
5862
                        $path_displayed = $folder;
5863
                        // If document title is used, we have to display titles instead of real paths...
5864
                        $path_displayed = DocumentManager::get_titles_of_path($folder);
5865
5866
                        if (empty($path_displayed)) {
5867
                            $path_displayed = get_lang('Untitled');
5868
                        }
5869
                        $options[$folder] = $path_displayed;
5870
                    }
5871
                }
5872
            }
5873
        } else {
5874
            foreach ($folders as $folder) {
5875
                if (($curdirpath != $folder) &&
5876
                    ($folder != $move_file) &&
5877
                    (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5878
                ) {
5879
                    // Cannot copy dir into his own subdir
5880
                    $path_displayed = DocumentManager::get_titles_of_path($folder);
5881
                    $display_folder = substr($path_displayed, strlen($group_dir));
5882
                    $display_folder = ($display_folder == '') ? get_lang('Documents') : $display_folder;
5883
                    //$form .= '<option value="'.$folder.'">'.$display_folder.'</option>';
5884
                    $options[$folder] = $display_folder;
5885
                }
5886
            }
5887
        }
5888
        $form->addElement('select', 'move_to', get_lang('MoveTo'), $options);
5889
        $form->addButtonNext(get_lang('MoveElement'), 'move_file_submit');
5890
        return $form->returnForm();
5891
    }
5892
5893
    /**
5894
     * Gets the path translated with title of docs and folders
5895
     * @param string $path the real path
5896
     * @return the path which should be displayed
5897
     */
5898
    public static function get_titles_of_path($path)
5899
    {
5900
        global $tmp_folders_titles;
5901
        $course_id = api_get_course_int_id();
5902
        $nb_slashes = substr_count($path, '/');
5903
        $current_slash_pos = 0;
5904
        $path_displayed = '';
5905
        for ($i = 0; $i < $nb_slashes; $i++) {
5906
            // For each folder of the path, retrieve title.
5907
            $current_slash_pos = strpos($path, '/', $current_slash_pos + 1);
5908
            $tmp_path = substr($path, strpos($path, '/', 0), $current_slash_pos);
5909
5910
            if (empty($tmp_path)) {
5911
                // If empty, then we are in the final part of the path
5912
                $tmp_path = $path;
5913
            }
5914
5915
            if (!empty($tmp_folders_titles[$tmp_path])) {
5916
                // If this path has soon been stored here we don't need a new query
5917
                $path_displayed .= $tmp_folders_titles[$tmp_path];
5918
            } else {
5919
                $sql = 'SELECT title FROM ' . Database::get_course_table(TABLE_DOCUMENT) . '
5920
                    WHERE c_id = ' . $course_id . ' AND path LIKE BINARY "' . $tmp_path . '"';
5921
                $rs = Database::query($sql);
5922
                $tmp_title = '/' . Database::result($rs, 0, 0);
5923
                $path_displayed .= $tmp_title;
5924
                $tmp_folders_titles[$tmp_path] = $tmp_title;
5925
            }
5926
        }
5927
        return $path_displayed;
5928
    }
5929
5930
    /**
5931
     * Creates form that asks for the directory name.
5932
     * @return string	html-output text for the form
5933
     */
5934
    public static function create_dir_form($dirId)
5935
    {
5936
        global $document_id;
5937
        $form = new FormValidator('create_dir_form', 'post', api_get_self().'?'.api_get_cidreq());
5938
        $form->addElement('hidden', 'create_dir', 1);
5939
        $form->addElement('hidden', 'dir_id', intval($document_id));
5940
        $form->addElement('hidden', 'id', intval($dirId));
5941
        $form->addElement('header', get_lang('CreateDir'));
5942
        $form->addText('dirname', get_lang('NewDir'), array('autofocus' => 'autofocus'));
5943
        $form->addButtonCreate(get_lang('CreateFolder'));
5944
5945
        return $form->returnForm();
5946
5947
    }
5948
5949
    /**
5950
     * Checks whether the user is in shared folder
5951
     * @return return bool Return true when user is into shared folder
5952
     */
5953
    public static function is_shared_folder($curdirpath, $current_session_id)
5954
    {
5955
        $clean_curdirpath = Security::remove_XSS($curdirpath);
5956
        if ($clean_curdirpath == '/shared_folder') {
5957
            return true;
5958
        } elseif ($clean_curdirpath == '/shared_folder_session_' . $current_session_id) {
5959
            return true;
5960
        } else {
5961
            return false;
5962
        }
5963
    }
5964
5965
    /**
5966
     * Checks whether the user is into any user shared folder
5967
     * @return return bool Return true when user is in any user shared folder
5968
     */
5969
    public static function is_any_user_shared_folder($path, $current_session_id)
5970
    {
5971
        $clean_path = Security::remove_XSS($path);
5972
        if (strpos($clean_path, 'shared_folder/sf_user_')) {
5973
            return true;
5974
        } elseif (strpos($clean_path, 'shared_folder_session_' . $current_session_id . '/sf_user_')) {
5975
            return true;
5976
        } else {
5977
            return false;
5978
        }
5979
    }
5980
5981
    /**
5982
     * Checks whether the user is into his shared folder or into a subfolder
5983
     * @return bool Return true when user is in his user shared folder or into a subfolder
5984
     */
5985
    public static function is_my_shared_folder($user_id, $path, $current_session_id)
5986
    {
5987
        $clean_path = Security::remove_XSS($path) . '/';
5988
        //for security does not remove the last slash
5989
        $main_user_shared_folder = '/shared_folder\/sf_user_' . $user_id . '\//';
5990
        //for security does not remove the last slash
5991
        $main_user_shared_folder_session = '/shared_folder_session_' . $current_session_id . '\/sf_user_' . $user_id . '\//';
5992
5993
        if (preg_match($main_user_shared_folder, $clean_path)) {
5994
            return true;
5995
        } elseif (preg_match($main_user_shared_folder_session, $clean_path)) {
5996
            return true;
5997
        } else {
5998
            return false;
5999
        }
6000
    }
6001
6002
    /**
6003
     * Check if the file name or folder searched exist
6004
     * @return bool Return true when exist
6005
     */
6006
    public static function search_keyword($document_name, $keyword)
6007
    {
6008
        if (api_strripos($document_name, $keyword) !== false) {
6009
            return true;
6010
        } else {
6011
            return false;
6012
        }
6013
    }
6014
6015
    /**
6016
     * Checks whether a document can be previewed by using the browser.
6017
     * @param string $file_extension    The filename extension of the document (it must be in lower case).
6018
     * @return bool                     Returns TRUE or FALSE.
6019
     */
6020
    public static function is_browser_viewable($file_extension)
6021
    {
6022
        static $allowed_extensions = array(
6023
            'htm', 'html', 'xhtml',
6024
            'gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff',
6025
            'pdf', 'svg', 'swf',
6026
            'txt', 'log',
6027
            'mp4', 'ogg', 'ogv', 'ogx', 'mpg', 'mpeg', 'mov', 'avi', 'webm', 'wmv',
6028
            'mp3', 'oga', 'wav', 'au', 'wma', 'mid', 'kar'
6029
        );
6030
6031
        /*
6032
          //TODO: make a admin swich to strict mode
6033
          1. global default $allowed_extensions only: 'htm', 'html', 'xhtml', 'gif', 'jpg', 'jpeg', 'png', 'bmp', 'txt', 'log'
6034
          if (in_array($file_extension, $allowed_extensions)) { // Assignment + a logical check.
6035
          return true;
6036
          }
6037
          2. check native support
6038
          3. check plugins: quicktime, mediaplayer, vlc, acrobat, flash, java
6039
         */
6040
6041
        if (!($result = in_array($file_extension, $allowed_extensions))) { // Assignment + a logical check.
6042
            return false;
6043
        }
6044
        //check native support (Explorer, Opera, Firefox, Chrome, Safari)
6045
6046
        if ($file_extension == "pdf") {
6047
            return api_browser_support('pdf');
6048
        } elseif ($file_extension == "mp3") {
6049
            return api_browser_support('mp3');
6050
        } elseif ($file_extension == "mp4") {
6051
            return api_browser_support('mp4');
6052
        } elseif ($file_extension == "ogg" || $file_extension == "ogx" || $file_extension == "ogv" || $file_extension == "oga") {
6053
            return api_browser_support('ogg');
6054
        } elseif ($file_extension == "svg") {
6055
            return api_browser_support('svg');
6056
        } elseif ($file_extension == "mpg" || $file_extension == "mpeg") {
6057
            return api_browser_support('mpg');
6058
        } elseif ($file_extension == "mov") {
6059
            return api_browser_support('mov');
6060
        } elseif ($file_extension == "wav") {
6061
            return api_browser_support('wav');
6062
        } elseif ($file_extension == "mid" || $file_extension == "kar") {
6063
            return api_browser_support('mid');
6064
        } elseif ($file_extension == "avi") {
6065
            return api_browser_support('avi');
6066
        } elseif ($file_extension == "wma") {
6067
            return api_browser_support('wma');
6068
        } elseif ($file_extension == "wmv") {
6069
            return api_browser_support('wmv');
6070
        } elseif ($file_extension == "tif" || $file_extension == "tiff") {
6071
            return api_browser_support('tif');
6072
        } elseif ($file_extension == "mov") {
6073
            return api_browser_support('mov');
6074
        } elseif ($file_extension == "au") {
6075
            return api_browser_support('au');
6076
        } elseif ($file_extension == "webm") {
6077
            return api_browser_support('webm');
6078
        }
6079
        return $result;
6080
    }
6081
6082
    /**
6083
     * @param array $courseInfo
6084
     * @param int $sessionId
6085
     *
6086
     * @return array
6087
     */
6088
    public static function getDeletedDocuments($courseInfo, $sessionId = 0)
6089
    {
6090
        $table = Database::get_course_table(TABLE_DOCUMENT);
6091
        $courseId = $courseInfo['real_id'];
6092
        $sessionCondition = api_get_session_condition($sessionId);
6093
        $sql = "SELECT * FROM $table
6094
                WHERE
6095
                  path LIKE '%DELETED%' AND
6096
                  c_id = $courseId
6097
                  $sessionCondition
6098
                ORDER BY path
6099
        ";
6100
6101
        $result = Database::query($sql);
6102
        $files = array();
6103
        while ($document = Database::fetch_array($result, 'ASSOC')) {
6104
            $files[] = $document;
6105
        }
6106
6107
        return $files;
6108
    }
6109
6110
    /**
6111
     * @param int $id
6112
     * @param array $courseInfo
6113
     * @param int $sessionId
6114
     *
6115
     * @return array
6116
     */
6117
    public static function getDeletedDocument($id, $courseInfo, $sessionId = 0)
6118
    {
6119
        if (empty($courseInfo)) {
6120
            return false;
6121
        }
6122
6123
        $table = Database::get_course_table(TABLE_DOCUMENT);
6124
        $courseId = $courseInfo['real_id'];
6125
        $sessionCondition = api_get_session_condition($sessionId);
6126
        $sql = "SELECT * FROM $table
6127
                WHERE
6128
                  path LIKE '%DELETED%' AND
6129
                  id = $id AND
6130
                  c_id = $courseId
6131
                  $sessionCondition
6132
                LIMIT 1
6133
        ";
6134
        $result = Database::query($sql);
6135
        if (Database::num_rows($result)) {
6136
            $result = Database::fetch_array($result, 'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
6137
6138
            return $result;
6139
        }
6140
6141
        return array();
6142
    }
6143
6144
    /**
6145
     * @param int $id
6146
     * @param array $courseInfo
6147
     * @param int $sessionId
6148
     * @return bool
6149
     */
6150
    public static function purgeDocument($id, $courseInfo, $sessionId = 0)
6151
    {
6152
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6153 View Code Duplication
        if (!empty($document)) {
6154
            $path = $document['path'];
6155
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6156
            my_delete($coursePath.$path);
6157
            // Hard delete.
6158
            self::deleteDocumentFromDb($id, $courseInfo, $sessionId, true);
6159
6160
            return true;
6161
        }
6162
        return false;
6163
    }
6164
6165
    /**
6166
     * @param array $courseInfo
6167
     * @param int $sessionId
6168
     */
6169
    public static function purgeDocuments($courseInfo, $sessionId)
6170
    {
6171
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6172
        foreach ($files as $file) {
6173
            self::purgeDocument($file['id'], $courseInfo, $sessionId);
6174
        }
6175
    }
6176
6177
    /**
6178
     * @param int $id
6179
     * @param array $courseInfo
6180
     * @param int $sessionId
6181
     * @return bool
6182
     */
6183
    public static function downloadDeletedDocument($id, $courseInfo, $sessionId)
6184
    {
6185
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6186 View Code Duplication
        if (!empty($document)) {
6187
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6188
6189
            if (Security::check_abs_path($coursePath.$document['path'], $coursePath)) {
6190
                self::file_send_for_download($coursePath.$document['path']);
6191
                exit;
6192
            }
6193
        }
6194
    }
6195
6196
    /**
6197
     * @param array $courseInfo
6198
     * @param int $sessionId
6199
     *
6200
     * @return bool
6201
     */
6202
    public static function downloadAllDeletedDocument($courseInfo, $sessionId)
6203
    {
6204
        // Zip library for creation of the zip file.
6205
        require api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
6206
6207
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6208
6209
        if (empty($files)) {
6210
            return false;
6211
        }
6212
6213
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
6214
6215
        // Creating a ZIP file.
6216
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
6217
        $zip = new PclZip($tempZipFile);
6218
        foreach ($files as $file) {
6219
            $zip->add(
6220
                $coursePath.$file['path'],
6221
                PCLZIP_OPT_REMOVE_PATH,
6222
                $coursePath
6223
            );
6224
        }
6225
6226 View Code Duplication
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
6227
            DocumentManager::file_send_for_download($tempZipFile, true);
6228
            @unlink($tempZipFile);
6229
            exit;
6230
        }
6231
    }
6232
6233
    /**
6234
     *
6235
     * Delete documents from a session in a course.
6236
     * @param array $courseInfo
6237
     * @param int $sessionId
6238
     *
6239
     * @return bool
6240
     */
6241
    public function deleteDocumentsFromSession($courseInfo, $sessionId)
6242
    {
6243
        if (empty($courseInfo)) {
6244
            return false;
6245
        }
6246
6247
        if (empty($sessionId)) {
6248
            return false;
6249
        }
6250
6251
        $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
6252
        $documentTable = Database::get_course_table(TABLE_DOCUMENT);
6253
6254
        $conditionSession = api_get_session_condition($sessionId, true, false, 'd.session_id');
6255
        $courseId = $courseInfo['real_id'];
6256
6257
        // get invisible folders
6258
        $sql = "SELECT DISTINCT d.id, path
6259
                FROM $itemPropertyTable i
6260
                INNER JOIN $documentTable d
6261
                ON (i.c_id = d.c_id)
6262
                WHERE
6263
                    d.id = i.ref AND
6264
                    i.tool = '" . TOOL_DOCUMENT . "'
6265
                    $conditionSession AND
6266
                    i.c_id = $courseId AND
6267
                    d.c_id = $courseId ";
6268
6269
        $result = Database::query($sql);
6270
        $documents = Database::store_result($result, 'ASSOC');
6271
        if ($documents) {
6272
            $course_dir = $courseInfo['directory'] . '/document';
6273
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
6274
            $base_work_dir = $sys_course_path . $course_dir;
6275
6276
            foreach ($documents as $document) {
6277
                $documentId = $document['id'];
6278
                DocumentManager::delete_document(
6279
                    $courseInfo,
6280
                    null,
6281
                    $base_work_dir,
6282
                    $sessionId,
6283
                    $documentId
6284
                );
6285
            }
6286
        }
6287
6288
        $sql = "DELETE FROM $documentTable
6289
                WHERE c_id = $courseId AND session_id = $sessionId";
6290
        Database::query($sql);
6291
6292
        $sql = "DELETE FROM $itemPropertyTable
6293
                WHERE c_id = $courseId AND session_id = $sessionId AND tool = '".TOOL_DOCUMENT."'";
6294
        Database::query($sql);
6295
    }
6296
}
6297