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

DocumentManager::is_shared_folder()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 0
loc 11
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
            // Comented to let courses content to be cached in order to improve performance:
368
            //header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
369
            //header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
370
371
            // Commented to avoid double caching declaration when playing with IE and HTTPS
372
            //header('Cache-Control: no-cache, must-revalidate');
373
            //header('Pragma: no-cache');
374
            switch ($content_type) {
375 View Code Duplication
                case 'text/html':
376
                    if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
377
                        $content_type .= '; charset=UTF-8';
378
                    } else {
379
                        $encoding = @api_detect_encoding_html(file_get_contents($full_file_name));
380
                        if (!empty($encoding)) {
381
                            $content_type .= '; charset=' . $encoding;
382
                        }
383
                    }
384
                    break;
385 View Code Duplication
                case 'text/plain':
386
                    if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
387
                        $content_type .= '; charset=UTF-8';
388
                    } else {
389
                        $encoding = @api_detect_encoding(strip_tags(file_get_contents($full_file_name)));
390
                        if (!empty($encoding)) {
391
                            $content_type .= '; charset=' . $encoding;
392
                        }
393
                    }
394
                    break;
395
                case 'application/vnd.dwg':
396
                case 'application/vnd.dwf':
397
                    header('Content-type: application/octet-stream');
398
                    break;
399
            }
400
            header('Content-type: ' . $content_type);
401
            header('Content-Length: ' . $len);
402
            $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
403 View Code Duplication
            if (strpos($user_agent, 'msie')) {
404
                header('Content-Disposition: ; filename= ' . $filename);
405
            } else {
406
                header('Content-Disposition: inline; filename= ' . $filename);
407
            }
408
409
            if ($fixLinksHttpToHttps) {
410
                $content = file_get_contents($full_file_name);
411
                $content = str_replace(
412
                    array('http%3A%2F%2F', 'http://'),
413
                    array('https%3A%2F%2F', 'https://'),
414
                    $content
415
                );
416
                echo $content;
417
            } else {
418
                readfile($full_file_name);
419
            }
420
421
            return true;
422
        }
423
    }
424
425
    /**
426
     * This function streams a string to the client for download.
427
     * You have to ensure that the calling script then stops processing (exit();)
428
     * otherwise it may cause subsequent use of the page to want to download
429
     * other pages in php rather than interpreting them.
430
     *
431
     * @param string $full_string The string contents
432
     * @param boolean $forced Whether "save" mode is forced (or opening directly authorized)
433
     * @param string $name The name of the file in the end (including extension)
434
     *
435
     * @return false if file doesn't exist, true if stream succeeded
436
     */
437
    public static function string_send_for_download($full_string, $forced = false, $name = '')
438
    {
439
        $filename = $name;
440
        $len = strlen($full_string);
441
442
        if ($forced) {
443
            //force the browser to save the file instead of opening it
444
445
            header('Content-type: application/octet-stream');
446
            //header('Content-Type: application/force-download');
447
            header('Content-length: ' . $len);
448 View Code Duplication
            if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
449
                header('Content-Disposition: filename= ' . $filename);
450
            } else {
451
                header('Content-Disposition: attachment; filename= ' . $filename);
452
            }
453
            if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
454
                header('Pragma: ');
455
                header('Cache-Control: ');
456
                header('Cache-Control: public'); // IE cannot download from sessions without a cache
457
            }
458
            header('Content-Description: ' . $filename);
459
            header('Content-transfer-encoding: binary');
460
            echo $full_string;
461
462
            return true;
463
            //You have to ensure that the calling script then stops processing (exit();)
464
            //otherwise it may cause subsequent use of the page to want to download
465
            //other pages in php rather than interpreting them.
466
        } else {
467
            //no forced download, just let the browser decide what to do according to the mimetype
468
469
            $content_type = self::file_get_mime_type($filename);
470
            header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
471
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
472
            header('Cache-Control: no-cache, must-revalidate');
473
            header('Pragma: no-cache');
474
            switch ($content_type) {
475
                case 'text/html':
476
                    $encoding = @api_detect_encoding_html($full_string);
477
                    if (!empty($encoding)) {
478
                        $content_type .= '; charset=' . $encoding;
479
                    }
480
                    break;
481
                case 'text/plain':
482
                    $encoding = @api_detect_encoding(strip_tags($full_string));
483
                    if (!empty($encoding)) {
484
                        $content_type .= '; charset=' . $encoding;
485
                    }
486
                    break;
487
            }
488
            header('Content-type: ' . $content_type);
489
            header('Content-Length: ' . $len);
490
            $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
491 View Code Duplication
            if (strpos($user_agent, 'msie')) {
492
                header('Content-Disposition: ; filename= ' . $filename);
493
            } else {
494
                header('Content-Disposition: inline; filename= ' . $filename);
495
            }
496
            echo($full_string);
497
            //You have to ensure that the calling script then stops processing (exit();)
498
            //otherwise it may cause subsequent use of the page to want to download
499
            //other pages in php rather than interpreting them.
500
            return true;
501
        }
502
    }
503
504
    /**
505
     * Session folder filters
506
     *
507
     * @param string $path
508
     * @param int    $sessionId
509
     *
510
     * @return null|string
511
     */
512
    public static function getSessionFolderFilters($path, $sessionId)
513
    {
514
        $sessionId = intval($sessionId);
515
        $condition = null;
516
517
        if (!empty($sessionId)) {
518
            // Chat folder filter
519
            if ($path == '/chat_files') {
520
                $condition .= " AND (docs.session_id = '$sessionId') ";
521
            }
522
            // share_folder filter
523
            $condition .= " AND docs.path != '/shared_folder' ";
524
        }
525
526
        return $condition;
527
    }
528
529
    /**
530
     * Fetches all document data for the given user/group
531
     *
532
     * @param array $_course
533
     * @param string $path
534
     * @param int $to_group_id iid
535
     * @param int $to_user_id
536
     * @param boolean $can_see_invisible
537
     * @param boolean $search
538
     * @param int $sessionId
539
     * @return array with all document data
540
     */
541
    public static function get_all_document_data(
542
        $_course,
543
        $path = '/',
544
        $to_group_id = 0,
545
        $to_user_id = null,
546
        $can_see_invisible = false,
547
        $search = false,
548
        $sessionId = 0
549
    ) {
550
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
551
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
552
553
        $userGroupFilter = '';
554
        if (!is_null($to_user_id)) {
555
            $to_user_id = intval($to_user_id);
556
            $userGroupFilter = "last.to_user_id = $to_user_id";
557
            if (empty($to_user_id)) {
558
                $userGroupFilter = " (last.to_user_id = 0 OR last.to_user_id IS NULL) ";
559
            }
560
        } else {
561
            $to_group_id = intval($to_group_id);
562
            $userGroupFilter = "last.to_group_id = $to_group_id";
563
            if (empty($to_group_id)) {
564
                $userGroupFilter = "( last.to_group_id = 0 OR last.to_group_id IS NULL) ";
565
            }
566
        }
567
568
        // Escape underscores in the path so they don't act as a wildcard
569
        $originalPath = $path;
570
        $path = str_replace('_', '\_', $path);
571
572
        $visibility_bit = ' <> 2';
573
574
        // The given path will not end with a slash, unless it's the root '/'
575
        // so no root -> add slash
576
        $added_slash = $path == '/' ? '' : '/';
577
578
        // Condition for the session
579
        $sessionId = $sessionId ?: api_get_session_id();
580
        $condition_session = " AND (last.session_id = '$sessionId' OR (last.session_id = '0' OR last.session_id IS NULL) )";
581
        $condition_session .= self::getSessionFolderFilters($originalPath, $sessionId);
582
583
        $sharedCondition = null;
584 View Code Duplication
        if ($originalPath == '/shared_folder') {
585
            $students = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
586
            if (!empty($students)) {
587
                $conditionList = array();
588
                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...
589
                    $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
590
                }
591
                $sharedCondition .= ' AND docs.path IN ("' . implode('","', $conditionList) . '")';
592
            }
593
        }
594
595
        $sql = "SELECT
596
                    docs.id,
597
                    docs.filetype,
598
                    docs.path,
599
                    docs.title,
600
                    docs.comment,
601
                    docs.size,
602
                    docs.readonly,
603
                    docs.session_id,
604
                    last.session_id item_property_session_id,
605
                    last.lastedit_date,
606
                    last.visibility,
607
                    last.insert_user_id
608
                FROM $TABLE_ITEMPROPERTY AS last
609
                INNER JOIN $TABLE_DOCUMENT AS docs
610
                ON (
611
                    docs.id = last.ref AND
612
                    docs.c_id = last.c_id
613
                )
614
                WHERE                                
615
                    last.tool = '".TOOL_DOCUMENT."' AND 
616
                    docs.c_id = {$_course['real_id']} AND
617
                    last.c_id = {$_course['real_id']} AND
618
                    docs.path LIKE '" . Database::escape_string($path . $added_slash.'%'). "' AND
619
                    docs.path NOT LIKE '" . Database::escape_string($path . $added_slash.'%/%')."' AND
620
                    docs.path NOT LIKE '%_DELETED_%' AND
621
                    $userGroupFilter AND
622
                    last.visibility $visibility_bit
623
                    $condition_session
624
                    $sharedCondition
625
                ";
626
        $result = Database::query($sql);
627
628
        $doc_list = array();
629
        $document_data = array();
630
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
631
        $isCoach = api_is_coach();
632
        if ($result !== false && Database::num_rows($result) != 0) {
633
            while ($row = Database::fetch_array($result, 'ASSOC')) {
634
                if ($isCoach) {
635
                    // Looking for course items that are invisible to hide it in the session
636
                    if (in_array($row['id'], array_keys($doc_list))) {
637
                        if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
638
                            $doc_list[$row['id']]['session_id'] == 0
639
                        ) {
640
                            if ($doc_list[$row['id']]['visibility'] == 0) {
641
                                unset($document_data[$row['id']]);
642
                                continue;
643
                            }
644
                        }
645
                    }
646
                    $doc_list[$row['id']] = $row;
647
                }
648
649
                if (!$isCoach && !$is_allowed_to_edit) {
650
                    $doc_list[] = $row;
651
                }
652
653
                if ($row['filetype'] == 'file' &&
654
                    pathinfo($row['path'], PATHINFO_EXTENSION) == 'html'
655
                ) {
656
                    // Templates management
657
                    $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
658
                    $sql = "SELECT id FROM $table_template
659
                            WHERE
660
                                course_code = '" . $_course['code'] . "' AND
661
                                user_id = '".api_get_user_id()."' AND
662
                                ref_doc = '".$row['id']."'";
663
                    $template_result = Database::query($sql);
664
                    $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
665
                }
666
                $row['basename'] = basename($row['path']);
667
                // Just filling $document_data.
668
                $document_data[$row['id']] = $row;
669
            }
670
671
            // Only for the student we filter the results see BT#1652
672
            if (!$isCoach && !$is_allowed_to_edit) {
673
                $ids_to_remove = array();
674
                $my_repeat_ids = $temp = array();
675
676
                // Selecting repeated ids
677
                foreach ($doc_list as $row) {
678
                    if (in_array($row['id'], array_keys($temp))) {
679
                        $my_repeat_ids[] = $row['id'];
680
                    }
681
                    $temp[$row['id']] = $row;
682
                }
683
684
                //@todo use the DocumentManager::is_visible function
685
                // Checking visibility in a session
686
                foreach ($my_repeat_ids as $id) {
687
                    foreach ($doc_list as $row) {
688
                        if ($id == $row['id']) {
689 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
690
                                $delete_repeated[$id] = true;
691
                            }
692 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
693
                                $delete_repeated[$id] = true;
694
                            }
695
                        }
696
                    }
697
                }
698
699
                foreach ($doc_list as $key => $row) {
700
                    if (in_array($row['visibility'], array('0', '2')) &&
701
                        !in_array($row['id'], $my_repeat_ids)
702
                    ) {
703
                        $ids_to_remove[] = $row['id'];
704
                        unset($doc_list[$key]);
705
                    }
706
                }
707
708
                foreach ($document_data as $row) {
709
                    if (in_array($row['id'], $ids_to_remove)) {
710
                        unset($document_data[$row['id']]);
711
                    }
712
                    if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
713
                        unset($document_data[$row['id']]);
714
                    }
715
                }
716
717
                // Checking parents visibility.
718
                $final_document_data = array();
719
                foreach ($document_data as $row) {
720
                    $is_visible = DocumentManager::check_visibility_tree(
721
                        $row['id'],
722
                        $_course['code'],
723
                        $sessionId,
724
                        api_get_user_id(),
725
                        $to_group_id
726
                    );
727
                    if ($is_visible) {
728
                        $final_document_data[$row['id']] = $row;
729
                    }
730
                }
731
            } else {
732
                $final_document_data = $document_data;
733
            }
734
735
            return $final_document_data;
736
        } else {
737
            return false;
738
        }
739
    }
740
741
    /**
742
     * Gets the paths of all folders in a course
743
     * can show all folders (except for the deleted ones) or only visible ones
744
     *
745
     * @param array $_course
746
     * @param int $groupIid iid
747
     * @param boolean $can_see_invisible
748
     * @param boolean $getInvisibleList
749
     * @param string $path current path
750
     *
751
     * @return array with paths
752
     */
753
    public static function get_all_document_folders(
754
        $_course,
755
        $groupIid = 0,
756
        $can_see_invisible = false,
757
        $getInvisibleList = false,
758
        $path = ''
759
    ) {
760
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
761
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
762
        $groupIid = intval($groupIid);
763
        $document_folders = array();
764
765
        $students = CourseManager::get_user_list_from_course_code(
766
            $_course['code'],
767
            api_get_session_id()
768
        );
769
770
        $conditionList = array();
771
        if (!empty($students)) {
772
            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...
773
                $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
774
            }
775
        }
776
777
        $groupCondition = " last.to_group_id = $groupIid";
778
        if (empty($groupIid)) {
779
            $groupCondition = " (last.to_group_id = 0 OR last.to_group_id IS NULL)";
780
        }
781
782
        $show_users_condition = '';
783
        if (api_get_setting('show_users_folders') === 'false') {
784
            $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
785
        }
786
787
        if ($can_see_invisible) {
788
            // condition for the session
789
            $session_id = api_get_session_id();
790
            //$condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
791
792
            $session_id = $session_id ?: api_get_session_id();
793
            $condition_session = " AND (last.session_id = '$session_id' OR (last.session_id = '0' OR last.session_id IS NULL) )";
794
            $condition_session .= self::getSessionFolderFilters($path, $session_id);
795
796
            if ($groupIid <> 0) {
797
                $sql = "SELECT DISTINCT docs.id, path
798
                       FROM $TABLE_ITEMPROPERTY  AS last
799
                       INNER JOIN $TABLE_DOCUMENT  AS docs
800
                       ON (
801
                            docs.id = last.ref AND
802
                            docs.c_id = last.c_id                            
803
                       )
804
                       WHERE
805
                            last.tool = '" . TOOL_DOCUMENT . "' AND
806
                            last.c_id = {$_course['real_id']} AND
807
                            docs.c_id = {$_course['real_id']} AND
808
                            docs.filetype = 'folder' AND
809
                            $groupCondition AND
810
                            docs.path NOT LIKE '%shared_folder%' AND
811
                            docs.path NOT LIKE '%_DELETED_%' AND
812
                            last.visibility <> 2                            
813
                            $condition_session ";
814
            } else {
815
                $sql = "SELECT DISTINCT docs.id, path
816
                        FROM $TABLE_ITEMPROPERTY  AS last
817
                        INNER JOIN $TABLE_DOCUMENT  AS docs
818
                        ON (
819
                            docs.id = last.ref AND                            
820
                            docs.c_id = last.c_id
821
                        )
822
                        WHERE
823
                            last.tool = '" . TOOL_DOCUMENT . "' AND
824
                            last.c_id = {$_course['real_id']} AND
825
                            docs.c_id = {$_course['real_id']} AND
826
                            docs.filetype = 'folder' AND
827
                            docs.path NOT LIKE '%_DELETED_%' AND
828
                            $groupCondition AND
829
                            last.visibility <> 2
830
                            $show_users_condition 
831
                            $condition_session 
832
                        ";
833
            }
834
            $result = Database::query($sql);
835
836
            if ($result && Database::num_rows($result) != 0) {
837
                while ($row = Database::fetch_array($result, 'ASSOC')) {
838
                    if (DocumentManager::is_folder_to_avoid($row['path'])) {
839
                        continue;
840
                    }
841
842
                    if (strpos($row['path'], '/shared_folder/') !== false) {
843
                        if (!in_array($row['path'], $conditionList)) {
844
                            continue;
845
                        }
846
                    }
847
848
                    $document_folders[$row['id']] = $row['path'];
849
                }
850
851
                if (!empty($document_folders)) {
852
                    natsort($document_folders);
853
                }
854
                return $document_folders;
855
            } else {
856
                return false;
857
            }
858
        } else {
859
            // No invisible folders
860
            // Condition for the session
861
            $session_id = api_get_session_id();
862
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
863
864
            $visibilityCondition = 'last.visibility = 1';
865
            $fileType = "docs.filetype = 'folder' AND";
866
            if ($getInvisibleList) {
867
                $visibilityCondition = 'last.visibility = 0';
868
                $fileType = '';
869
            }
870
871
            //get visible folders
872
            $sql = "SELECT DISTINCT docs.id, path
873
                    FROM
874
                    $TABLE_ITEMPROPERTY AS last 
875
                    INNER JOIN $TABLE_DOCUMENT AS docs
876
                        ON (docs.id = last.ref AND last.c_id = docs.c_id)
877
                    WHERE
878
                        $fileType
879
                        last.tool = '" . TOOL_DOCUMENT . "' AND
880
                        $groupCondition AND
881
                        $visibilityCondition
882
                        $show_users_condition
883
                        $condition_session AND
884
                        last.c_id = {$_course['real_id']}  AND
885
                        docs.c_id = {$_course['real_id']} ";
886
887
            $result = Database::query($sql);
888
889
            $visibleFolders = array();
890 View Code Duplication
            while ($row = Database::fetch_array($result, 'ASSOC')) {
891
                $visibleFolders[$row['id']] = $row['path'];
892
            }
893
894
            if ($getInvisibleList) {
895
                return $visibleFolders;
896
            }
897
898
            // Condition for the session
899
            $session_id = api_get_session_id();
900
            $condition_session = api_get_session_condition(
901
                $session_id,
902
                true,
903
                false,
904
                'docs.session_id'
905
            );
906
907
            //get invisible folders
908
            $sql = "SELECT DISTINCT docs.id, path
909
                    FROM $TABLE_ITEMPROPERTY AS last 
910
                    INNER JOIN $TABLE_DOCUMENT AS docs
911
                    ON (docs.id = last.ref AND last.c_id = docs.c_id)
912
                    WHERE                        
913
                        docs.filetype = 'folder' AND
914
                        last.tool = '" . TOOL_DOCUMENT . "' AND
915
                        $groupCondition AND
916
                        last.visibility = 0 $condition_session AND
917
                        last.c_id = {$_course['real_id']} AND
918
                        docs.c_id = {$_course['real_id']} ";
919
            $result = Database::query($sql);
920
            $invisibleFolders = array();
921
922
            while ($row = Database::fetch_array($result, 'ASSOC')) {
923
                //get visible folders in the invisible ones -> they are invisible too
924
                $sql = "SELECT DISTINCT docs.id, path
925
                        FROM $TABLE_ITEMPROPERTY AS last 
926
                        INNER JOIN $TABLE_DOCUMENT AS docs
927
                        ON (docs.id = last.ref AND last.c_id = docs.c_id)
928
                        WHERE                            
929
                            docs.path LIKE '" . Database::escape_string($row['path'].'/%') . "' AND
930
                            docs.filetype = 'folder' AND
931
                            last.tool = '" . TOOL_DOCUMENT . "' AND
932
                            $groupCondition AND
933
                            last.visibility = 1 $condition_session AND
934
                            last.c_id = {$_course['real_id']} AND
935
                            docs.c_id = {$_course['real_id']}  ";
936
                $folder_in_invisible_result = Database::query($sql);
937
                while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
938
                    $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
939
                }
940
            }
941
942
            // If both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
943
            if (is_array($visibleFolders) && is_array($invisibleFolders)) {
944
                $document_folders = array_diff($visibleFolders, $invisibleFolders);
945
                natsort($document_folders);
946
                return $document_folders;
947
            } elseif (is_array($visibleFolders)) {
948
                natsort($visibleFolders);
949
                return $visibleFolders;
950
            } else {
951
                //no visible folders found
952
                return false;
953
            }
954
        }
955
    }
956
957
    /**
958
     * This check if a document has the readonly property checked, then see if the user
959
     * is the owner of this file, if all this is true then return true.
960
     *
961
     * @param array  $_course
962
     * @param int    $user_id id of the current user
963
     * @param string $file path stored in the database (if not defined, $documentId must be used)
964
     * @param int    $document_id in case you dont have the file path ,
965
     *                insert the id of the file here and leave $file in blank ''
966
     * @param bool $to_delete
967
     * @param int $sessionId
968
     * @return boolean true/false
969
     * */
970
    public static function check_readonly(
971
        $_course,
972
        $user_id,
973
        $file = null,
974
        $document_id = '',
975
        $to_delete = false,
976
        $sessionId = null,
977
        $documentId = null
978
    ) {
979
980
        if (empty($sessionId)) {
981
            $sessionId = api_get_session_id();
982
        } else {
983
            $sessionId = intval($sessionId);
984
        }
985
986
        if (empty($document_id) || !is_numeric($document_id)) {
987
            $document_id = self::get_document_id($_course, $file, $sessionId);
988
        } else {
989
            $document_id = intval($document_id);
990
        }
991
992
        $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
993
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
994
        $course_id = $_course['real_id'];
995
996
        if ($to_delete) {
997
            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 987 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...
998
                if (!empty($file)) {
999
                    $path = Database::escape_string($file);
1000
                    // Check
1001
                    $sql = "SELECT td.id, readonly, tp.insert_user_id
1002
                            FROM $TABLE_DOCUMENT td 
1003
                            INNER JOIN $TABLE_PROPERTY tp
1004
                            ON (td.c_id = tp.c_id AND tp.ref= td.id)
1005
                            WHERE
1006
                                td.c_id = $course_id AND
1007
                                tp.c_id = $course_id AND
1008
                                td.session_id = $sessionId AND                                
1009
                                (path='" . $path . "' OR path LIKE BINARY '" . $path . "/%' ) ";
1010
                    // Get all id's of documents that are deleted
1011
                    $what_to_check_result = Database::query($sql);
1012
1013
                    if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
1014
                        // file with readonly set to 1 exist?
1015
                        $readonly_set = false;
1016
                        while ($row = Database::fetch_array($what_to_check_result)) {
1017
                            //query to delete from item_property table
1018
                            if ($row['readonly'] == 1) {
1019
                                if (!($row['insert_user_id'] == $user_id)) {
1020
                                    $readonly_set = true;
1021
                                    break;
1022
                                }
1023
                            }
1024
                        }
1025
1026
                        if ($readonly_set) {
1027
                            return true;
1028
                        }
1029
                    }
1030
                }
1031
                return false;
1032
            }
1033
        }
1034
1035
        if (!empty($document_id)) {
1036
            $sql = "SELECT a.insert_user_id, b.readonly
1037
                   FROM $TABLE_PROPERTY a 
1038
                   INNER JOIN $TABLE_DOCUMENT b
1039
                   ON (a.c_id = b.c_id AND a.ref= b.id)
1040
                   WHERE
1041
            			a.c_id = $course_id AND
1042
                        b.c_id = $course_id AND
1043
            			a.ref = $document_id 
1044
                    LIMIT 1";
1045
            $result = Database::query($sql);
1046
            $doc_details = Database ::fetch_array($result, 'ASSOC');
1047
1048
            if ($doc_details['readonly'] == 1) {
1049
                return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
1050
            }
1051
        }
1052
        return false;
1053
    }
1054
1055
    /**
1056
     * This check if a document is a folder or not
1057
     * @param array  $_course
1058
     * @param int    $document_id of the item
1059
     * @return boolean true/false
1060
     * */
1061
    public static function is_folder($_course, $document_id)
1062
    {
1063
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1064
        $course_id = $_course['real_id'];
1065
        $document_id = intval($document_id);
1066
        $sql = "SELECT filetype FROM $TABLE_DOCUMENT
1067
                WHERE c_id = $course_id AND id= $document_id";
1068
        $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...
1069
1070
        return $result['filetype'] == 'folder';
1071
    }
1072
1073
    /**
1074
     * @param int $document_id
1075
     * @param array $course_info
1076
     * @param int $session_id
1077
     * @param bool $remove_content_from_db
1078
     */
1079
    public static function deleteDocumentFromDb(
1080
        $document_id,
1081
        $course_info = array(),
1082
        $session_id = 0,
1083
        $remove_content_from_db = false
1084
    ) {
1085
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1086
        $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
1087
1088
        // Deleting from the DB
1089
        $user_id = api_get_user_id();
1090
        $document_id = intval($document_id);
1091
1092
        if (empty($course_info)) {
1093
            $course_info = api_get_course_info();
1094
        }
1095
1096
        if (empty($session_id)) {
1097
            $session_id = api_get_session_id();
1098
        }
1099
1100
        // Soft DB delete
1101
        api_item_property_update(
1102
            $course_info,
1103
            TOOL_DOCUMENT,
1104
            $document_id,
1105
            'delete',
1106
            $user_id,
1107
            null,
1108
            null,
1109
            null,
1110
            null,
1111
            $session_id
1112
        );
1113
        self::delete_document_from_search_engine($course_info['code'], $document_id);
1114
        self::unset_document_as_template($document_id, $course_info['code'], $user_id);
1115
1116
        //Hard DB delete
1117
        if ($remove_content_from_db) {
1118
            $sql = "DELETE FROM $TABLE_ITEMPROPERTY
1119
                    WHERE
1120
                        c_id = {$course_info['real_id']} AND
1121
                        ref = ".$document_id." AND
1122
                        tool='".TOOL_DOCUMENT."'";
1123
            Database::query($sql);
1124
1125
            $sql = "DELETE FROM $TABLE_DOCUMENT
1126
                    WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
1127
            Database::query($sql);
1128
        }
1129
    }
1130
1131
    /**
1132
     * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
1133
     * Files/folders that are inside a deleted folder get visibility 2
1134
     *
1135
     * @param array $_course
1136
     * @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...
1137
     * @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...
1138
     * @param int   $sessionId The ID of the session, if any
1139
     * @param int   $documentId The document id, if available
1140
     * @param int $groupId iid
1141
     * @return boolean true/false
1142
     * @todo now only files/folders in a folder get visibility 2, we should rename them too.
1143
     * @todo We should be able to get rid of this later when using only documentId (check further usage)
1144
     */
1145
    public static function delete_document(
1146
        $_course,
1147
        $path = null,
1148
        $base_work_dir = null,
1149
        $sessionId = null,
1150
        $documentId = null,
1151
        $groupId = 0
1152
    ) {
1153
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1154
1155
        if (empty($groupId)) {
1156
            $groupId = api_get_group_id();
1157
        } else {
1158
            $groupId = intval($groupId);
1159
        }
1160
1161
        if (empty($sessionId)) {
1162
            $sessionId = api_get_session_id();
1163
        } else {
1164
            $sessionId = intval($sessionId);
1165
        }
1166
1167
        $course_id = $_course['real_id'];
1168
1169
        if (empty($course_id)) {
1170
            return false;
1171
        }
1172
1173
        if (empty($base_work_dir)) {
1174
            return false;
1175
        }
1176
1177
        if (empty($documentId)) {
1178
            $documentId = self::get_document_id($_course, $path, $sessionId);
1179
            $docInfo = self::get_document_data_by_id(
1180
                $documentId,
0 ignored issues
show
Security Bug introduced by
It seems like $documentId defined by self::get_document_id($_course, $path, $sessionId) on line 1178 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...
1181
                $_course['code'],
1182
                false,
1183
                $sessionId
1184
            );
1185
            $path = $docInfo['path'];
1186 View Code Duplication
        } else {
1187
            $docInfo = self::get_document_data_by_id(
1188
                $documentId,
1189
                $_course['code'],
1190
                false,
1191
                $sessionId
1192
            );
1193
            if (empty($docInfo)) {
1194
                return false;
1195
            }
1196
            $path = $docInfo['path'];
1197
        }
1198
1199
        $documentId = intval($documentId);
1200
1201
        if (empty($path) || empty($docInfo) || empty($documentId)) {
1202
            return false;
1203
        }
1204
1205
        $itemInfo = api_get_item_property_info(
1206
            $_course['real_id'],
1207
            TOOL_DOCUMENT,
1208
            $documentId,
1209
            $sessionId,
1210
            $groupId
1211
        );
1212
1213
        if (empty($itemInfo)) {
1214
            return false;
1215
        }
1216
1217
        // File was already deleted.
1218
        if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
1219
            $itemInfo['lastedit_type'] == 'delete' ||
1220
            $itemInfo['visibility'] == 2
1221
        ) {
1222
            return false;
1223
        }
1224
1225
        // Filtering by group.
1226
        if ($itemInfo['to_group_id'] != $groupId) {
1227
            return false;
1228
        }
1229
1230
        $document_exists_in_disk = file_exists($base_work_dir.$path);
1231
        $new_path = $path.'_DELETED_'.$documentId;
1232
1233
        $file_deleted_from_db = false;
1234
        $file_deleted_from_disk = false;
1235
        $file_renamed_from_disk = false;
1236
1237
        if ($documentId) {
1238
            // Deleting doc from the DB.
1239
            self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1240
            // Checking
1241
            // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
1242
            $file_deleted_from_db = true;
1243
        }
1244
1245
        // Looking for children.
1246
        if ($docInfo['filetype'] == 'folder') {
1247
            $cleanPath = Database::escape_string($path);
1248
1249
            // Deleted files inside this folder.
1250
            $sql = "SELECT id FROM $TABLE_DOCUMENT
1251
                    WHERE
1252
                        c_id = $course_id AND
1253
                        session_id = $sessionId AND
1254
                        path LIKE BINARY '".$cleanPath."/%'";
1255
1256
            // Get all id's of documents that are deleted.
1257
            $result = Database::query($sql);
1258
1259
            if ($result && Database::num_rows($result) != 0) {
1260
                // Recursive delete.
1261
                while ($row = Database::fetch_array($result)) {
1262
                    self::delete_document(
1263
                        $_course,
1264
                        null,
1265
                        $base_work_dir,
1266
                        $sessionId,
1267
                        $row['id'],
1268
                        $groupId
1269
                    );
1270
                }
1271
            }
1272
        }
1273
1274
        if ($document_exists_in_disk) {
1275
            if (api_get_setting('permanently_remove_deleted_files') === 'true') {
1276
                // Delete documents, do it like this so metadata gets deleted too
1277
                my_delete($base_work_dir.$path);
1278
                // Hard delete.
1279
                self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
1280
                $file_deleted_from_disk = true;
1281
            } else {
1282
                // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
1283
1284
                if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
1285
                    if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
1286
                        $new_path = Database::escape_string($new_path);
1287
1288
                        $sql = "UPDATE $TABLE_DOCUMENT
1289
                                SET path = '".$new_path."'
1290
                                WHERE
1291
                                    c_id = $course_id AND
1292
                                    session_id = $sessionId AND
1293
                                    id = ".$documentId;
1294
                        Database::query($sql);
1295
1296
                        // Soft delete.
1297
                        self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1298
1299
                        // Change path of sub folders and documents in database.
1300
                        $old_item_path = $docInfo['path'];
1301
                        $new_item_path = $new_path.substr($old_item_path, strlen($path));
1302
                        $new_item_path = Database::escape_string($new_item_path);
1303
1304
                        $sql = "UPDATE $TABLE_DOCUMENT
1305
                                SET path = '".$new_item_path."'
1306
                                WHERE
1307
                                    c_id = $course_id AND
1308
                                    session_id = $sessionId AND
1309
                                    id = ".$documentId;
1310
                        Database::query($sql);
1311
1312
                        $file_renamed_from_disk = true;
1313
                    } else {
1314
                        // Couldn't rename - file permissions problem?
1315
                        error_log(
1316
                            __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
1317
                            0
1318
                        );
1319
                    }
1320
                }
1321
            }
1322
        }
1323
        // Checking inconsistency
1324
        //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').')');
1325
        if ($file_deleted_from_db && $file_deleted_from_disk ||
1326
            $file_deleted_from_db && $file_renamed_from_disk
1327
        ) {
1328
            return true;
1329
        } else {
1330
            //Something went wrong
1331
            //The file or directory isn't there anymore (on the filesystem)
1332
            // This means it has been removed externally. To prevent a
1333
            // blocking error from happening, we drop the related items from the
1334
            // item_property and the document table.
1335
            error_log(
1336
                __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',
1337
                0
1338
            );
1339
            return false;
1340
        }
1341
    }
1342
1343
    /**
1344
     * Removes documents from search engine database
1345
     *
1346
     * @param string $course_id Course code
1347
     * @param int $document_id Document id to delete
1348
     */
1349 View Code Duplication
    public static function delete_document_from_search_engine($course_id, $document_id)
1350
    {
1351
        // remove from search engine if enabled
1352
        if (api_get_setting('search_enabled') === 'true') {
1353
            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
1354
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1355
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1356
            $res = Database::query($sql);
1357
            if (Database::num_rows($res) > 0) {
1358
                $row2 = Database::fetch_array($res);
1359
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
1360
                $di = new ChamiloIndexer();
1361
                $di->remove_document((int) $row2['search_did']);
1362
            }
1363
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1364
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1365
            Database::query($sql);
1366
1367
            // remove terms from db
1368
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
1369
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
1370
        }
1371
    }
1372
1373
    /**
1374
     * Gets the id of a document with a given path
1375
     *
1376
     * @param array $courseInfo
1377
     * @param string $path
1378
     * @param int $sessionId
1379
     * @return int id of document / false if no doc found
1380
     */
1381
    public static function get_document_id($courseInfo, $path, $sessionId = null)
1382
    {
1383
        $table = Database :: get_course_table(TABLE_DOCUMENT);
1384
        $courseId = $courseInfo['real_id'];
1385
1386
        if (!isset($sessionId)) {
1387
            $sessionId = api_get_session_id();
1388
        } else {
1389
            $sessionId = intval($sessionId);
1390
        }
1391
1392
        $path = Database::escape_string($path);
1393
        if (!empty($courseId) && !empty($path)) {
1394
            $sql = "SELECT id FROM $table
1395
                    WHERE
1396
                        c_id = $courseId AND
1397
                        path LIKE BINARY '$path' AND
1398
                        session_id = $sessionId
1399
                    LIMIT 1";
1400
1401
            $result = Database::query($sql);
1402
            if (Database::num_rows($result)) {
1403
                $row = Database::fetch_array($result);
1404
1405
                return intval($row['id']);
1406
            }
1407
        }
1408
1409
        return false;
1410
    }
1411
1412
    /**
1413
     * Gets the document data with a given id
1414
     *
1415
     * @param int $id Document Id (id field in c_document table)
1416
     * @param string $course_code Course code
1417
     * @param bool $load_parents load folder parents.
1418
     * @param int $session_id The session ID,
1419
     * 0 if requires context *out of* session, and null to use global context
1420
     * @return array document content
1421
     */
1422
    public static function get_document_data_by_id(
1423
        $id,
1424
        $course_code,
1425
        $load_parents = false,
1426
        $session_id = null
1427
    ) {
1428
        $course_info = api_get_course_info($course_code);
1429
        $course_id = $course_info['real_id'];
1430
1431
        if (empty($course_info)) {
1432
            return false;
1433
        }
1434
1435
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
1436
        $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
1437
        $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
1438
        $id = intval($id);
1439
1440
        $sessionCondition = api_get_session_condition($session_id, true, true);
1441
1442
        $sql = "SELECT * FROM $TABLE_DOCUMENT
1443
                WHERE c_id = $course_id $sessionCondition AND id = $id";
1444
1445
        $result = Database::query($sql);
1446
        if ($result && Database::num_rows($result) == 1) {
1447
            $row = Database::fetch_array($result, 'ASSOC');
1448
1449
            //@todo need to clarify the name of the URLs not nice right now
1450
            $url_path = urlencode($row['path']);
1451
            $path = str_replace('%2F', '/', $url_path);
1452
            $pathinfo = pathinfo($row['path']);
1453
1454
            $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
1455
            $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
1456
            $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1457
            $row['absolute_path_from_document'] = '/document' . $row['path'];
1458
            $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
1459
            $row['direct_url'] = $www . $path;
1460
            $row['basename'] = basename($row['path']);
1461
1462
            if (dirname($row['path']) == '.') {
1463
                $row['parent_id'] = '0';
1464
            } else {
1465
                $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
1466
            }
1467
            $parents = array();
1468
1469
            //Use to generate parents (needed for the breadcrumb)
1470
            //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
1471
1472
            if ($load_parents) {
1473
                $dir_array = explode('/', $row['path']);
1474
                $dir_array = array_filter($dir_array);
1475
                $array_len = count($dir_array) + 1;
1476
                $real_dir = '';
1477
1478
                for ($i = 1; $i < $array_len; $i++) {
1479
                    $real_dir .= '/' . (isset($dir_array[$i]) ? $dir_array[$i] : '');
1480
                    $parent_id = self::get_document_id($course_info, $real_dir);
1481
                    if ($session_id != 0 && empty($parent_id)) {
1482
                        $parent_id = self::get_document_id($course_info, $real_dir, 0);
1483
                    }
1484
                    if (!empty($parent_id)) {
1485
                        $sub_document_data = self::get_document_data_by_id(
1486
                            $parent_id,
1487
                            $course_code,
1488
                            false,
1489
                            $session_id
1490
                        );
1491
                        if ($session_id != 0 and !$sub_document_data) {
1492
                            $sub_document_data = self::get_document_data_by_id(
1493
                                $parent_id,
1494
                                $course_code,
1495
                                false,
1496
                                0
1497
                            );
1498
                        }
1499
                        //@todo add visibility here
1500
                        $parents[] = $sub_document_data;
1501
                    }
1502
                }
1503
            }
1504
            $row['parents'] = $parents;
1505
1506
            return $row;
1507
        }
1508
1509
        return false;
1510
    }
1511
1512
    /**
1513
     * Allow to set a specific document as a new template for CKeditor
1514
     * for a particular user in a particular course
1515
     *
1516
     * @param string $title
1517
     * @param string $description
1518
     * @param int $document_id_for_template the document id
1519
     * @param string $course_code
1520
     * @param int $user_id
1521
     * @return bool
1522
     */
1523
    public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
1524
    {
1525
        // Database table definition
1526
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1527
        $params = [
1528
            'title' => $title,
1529
            'description' => $description,
1530
            'course_code' => $course_code,
1531
            'user_id' => $user_id,
1532
            'ref_doc' => $document_id_for_template,
1533
            'image' => $image,
1534
        ];
1535
        Database::insert($table_template, $params);
1536
        return true;
1537
    }
1538
1539
    /**
1540
     * Unset a document as template
1541
     *
1542
     * @param int $document_id
1543
     * @param string $course_code
1544
     * @param int $user_id
1545
     */
1546
    public static function unset_document_as_template($document_id, $course_code, $user_id)
1547
    {
1548
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1549
        $course_code = Database::escape_string($course_code);
1550
        $user_id = intval($user_id);
1551
        $document_id = intval($document_id);
1552
1553
        $sql = 'SELECT id FROM ' . $table_template . '
1554
                WHERE
1555
                    course_code="' . $course_code . '" AND
1556
                    user_id="' . $user_id . '" AND
1557
                    ref_doc="' . $document_id . '"';
1558
        $result = Database::query($sql);
1559
        $template_id = Database::result($result, 0, 0);
1560
1561
        my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
1562
1563
        $sql = 'DELETE FROM ' . $table_template . '
1564
                WHERE
1565
                    course_code="' . $course_code . '" AND
1566
                    user_id="' . $user_id . '" AND
1567
                    ref_doc="' . $document_id . '"';
1568
1569
        Database::query($sql);
1570
    }
1571
1572
    /**
1573
     * Return true if the documentpath have visibility=1 as
1574
     * item_property (you should use the is_visible_by_id)
1575
     *
1576
     * @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...
1577
     * @param array  $course the _course array info of the document's course
1578
     * @param int
1579
     * @param string
1580
     * @return bool
1581
     */
1582
    public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
1583
    {
1584
        $docTable = Database::get_course_table(TABLE_DOCUMENT);
1585
        $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
1586
1587
        $course_id = $course['real_id'];
1588
        //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
1589
1590
        $session_id = intval($session_id);
1591
        $condition = "AND d.session_id IN  ('$session_id', '0') ";
1592
        // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
1593
1594
        /*
1595
          When using hotpotatoes files, a new html files are generated
1596
          in the hotpotatoes folder to display the test.
1597
          The genuine html file is copied to math4.htm(user_id).t.html
1598
          Images files are not copied, and keep same name.
1599
          To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
1600
          In this case, we have to remove (user_id).t.html to check the visibility of the file
1601
          For images, we just check the path of the image file.
1602
1603
          Exemple of hotpotatoes folder :
1604
          A.jpg
1605
          maths4-consigne.jpg
1606
          maths4.htm
1607
          maths4.htm1.t.html
1608
          maths4.htm52.t.html
1609
          maths4.htm654.t.html
1610
          omega.jpg
1611
          theta.jpg
1612
         */
1613
1614
        if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
1615
            $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
1616
        }
1617
1618
        if (!in_array($file_type, array('file', 'folder'))) {
1619
            $file_type = 'file';
1620
        }
1621
        $doc_path = Database::escape_string($doc_path).'/';
1622
1623
        $sql = "SELECT visibility
1624
                FROM $docTable d
1625
                INNER JOIN $propTable ip
1626
                ON (d.id = ip.ref AND d.c_id = ip.c_id)
1627
        		WHERE
1628
        		    d.c_id  = $course_id AND 
1629
        		    ip.c_id = $course_id AND
1630
        		    ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
1631
        			filetype = '$file_type' AND
1632
        			locate(concat(path,'/'), '$doc_path')=1
1633
                ";
1634
1635
        $result = Database::query($sql);
1636
        $is_visible = false;
1637 View Code Duplication
        if (Database::num_rows($result) > 0) {
1638
            $row = Database::fetch_array($result, 'ASSOC');
1639
            if ($row['visibility'] == 1) {
1640
                $is_visible = api_is_allowed_in_course() || api_is_platform_admin();
1641
            }
1642
        }
1643
1644
        /* improved protection of documents viewable directly through the url:
1645
            incorporates the same protections of the course at the url of
1646
            documents:
1647
            access allowed for the whole world Open, access allowed for
1648
            users registered on the platform Private access, document accessible
1649
            only to course members (see the Users list), Completely closed;
1650
            the document is only accessible to the course admin and
1651
            teaching assistants.*/
1652
        //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
1653
        return $is_visible;
1654
    }
1655
1656
    /**
1657
     * Return true if user can see a file
1658
     *
1659
     * @param   int     document id
1660
     * @param   array   course info
1661
     * @param   int
1662
     * @param   int
1663
     * @param bool
1664
     * @return  bool
1665
     */
1666
    public static function is_visible_by_id(
1667
        $doc_id,
1668
        $course_info,
1669
        $session_id,
1670
        $user_id,
1671
        $admins_can_see_everything = true,
1672
        $userIsSubscribed = null
1673
    ) {
1674
        $user_in_course = false;
1675
1676
        //1. Checking the course array
1677
        if (empty($course_info)) {
1678
            $course_info = api_get_course_info();
1679
            if (empty($course_info)) {
1680
                return false;
1681
            }
1682
        }
1683
1684
        $doc_id = intval($doc_id);
1685
        $session_id = intval($session_id);
1686
1687
        //2. Course and Session visibility are handle in local.inc.php/global.inc.php
1688
        //3. Checking if user exist in course/session
1689
        if ($session_id == 0) {
1690
            if (is_null($userIsSubscribed)) {
1691
                $userIsSubscribed = CourseManager::is_user_subscribed_in_course(
1692
                    $user_id,
1693
                    $course_info['code']
1694
                );
1695
            }
1696
1697
            if ($userIsSubscribed === true || api_is_platform_admin()) {
1698
                $user_in_course = true;
1699
            }
1700
1701
            // Check if course is open then we can consider that the student is registered to the course
1702
            if (isset($course_info) &&
1703
                in_array(
1704
                    $course_info['visibility'],
1705
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
1706
                )
1707
            ) {
1708
                $user_in_course = true;
1709
            }
1710 View Code Duplication
        } else {
1711
            $user_status = SessionManager::get_user_status_in_course_session(
1712
                $user_id,
1713
                $course_info['real_id'],
1714
                $session_id
1715
            );
1716
1717
            if (in_array($user_status, array('0', '2', '6'))) {
1718
                //is true if is an student, course session teacher or coach
1719
                $user_in_course = true;
1720
            }
1721
1722
            if (api_is_platform_admin()) {
1723
                $user_in_course = true;
1724
            }
1725
        }
1726
1727
        // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
1728
        if ($user_in_course) {
1729
            // 4.1 Checking document visibility for a Course
1730
            if ($session_id == 0) {
1731
                $item_info = api_get_item_property_info(
1732
                    $course_info['real_id'],
1733
                    'document',
1734
                    $doc_id,
1735
                    0
1736
                );
1737
1738
                if (isset($item_info['visibility'])) {
1739
                    // True for admins if document exists
1740
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1741
                        return true;
1742
                    }
1743
                    if ($item_info['visibility'] == 1) {
1744
                        return true;
1745
                    }
1746
                }
1747
            } else {
1748
                // 4.2 Checking document visibility for a Course in a Session
1749
                $item_info = api_get_item_property_info(
1750
                    $course_info['real_id'],
1751
                    'document',
1752
                    $doc_id,
1753
                    0
1754
                );
1755
1756
                $item_info_in_session = api_get_item_property_info(
1757
                    $course_info['real_id'],
1758
                    'document',
1759
                    $doc_id,
1760
                    $session_id
1761
                );
1762
1763
                // True for admins if document exists
1764
                if (isset($item_info['visibility'])) {
1765
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1766
                        return true;
1767
                    }
1768
                }
1769
1770
                if (isset($item_info_in_session['visibility'])) {
1771
                    if ($item_info_in_session['visibility'] == 1) {
1772
                        return true;
1773
                    }
1774
                } else {
1775
                    if ($item_info['visibility'] == 1) {
1776
                        return true;
1777
                    }
1778
                }
1779
            }
1780
        } elseif ($admins_can_see_everything && api_is_platform_admin()) {
1781
            return true;
1782
        }
1783
        return false;
1784
    }
1785
1786
    /**
1787
     * Allow attach a certificate to a course
1788
     * @param string $course_id
1789
     * @param int $document_id
1790
     * @param int $session_id
1791
     * @return void
1792
     */
1793
    public static function attach_gradebook_certificate($course_id, $document_id, $session_id = 0)
1794
    {
1795
        $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1796
        $session_id = intval($session_id);
1797
        if (empty($session_id)) {
1798
            $session_id = api_get_session_id();
1799
        }
1800
1801 View Code Duplication
        if (empty($session_id)) {
1802
            $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
1803
        } elseif ($session_id > 0) {
1804
            $sql_session = 'AND session_id=' . intval($session_id);
1805
        } else {
1806
            $sql_session = '';
1807
        }
1808
        $sql = 'UPDATE ' . $tbl_category . ' SET document_id="' . intval($document_id) . '"
1809
                WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
1810
        Database::query($sql);
1811
    }
1812
1813
    /**
1814
     * get the document id of default certificate
1815
     * @param string $course_id
1816
     * @param int $session_id
1817
     *
1818
     * @return int The default certificate id
1819
     */
1820
    public static function get_default_certificate_id($course_id, $session_id = 0)
1821
    {
1822
        $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1823
        $session_id = intval($session_id);
1824
        if (empty($session_id)) {
1825
            $session_id = api_get_session_id();
1826
        }
1827
1828 View Code Duplication
        if (empty($session_id)) {
1829
            $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
1830
        } elseif ($session_id > 0) {
1831
            $sql_session = 'AND session_id=' . intval($session_id);
1832
        } else {
1833
            $sql_session = '';
1834
        }
1835
        $sql = 'SELECT document_id FROM ' . $tbl_category . '
1836
                WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
1837
1838
        $rs = Database::query($sql);
1839
        $num = Database::num_rows($rs);
1840
        if ($num == 0) {
1841
            return null;
1842
        }
1843
        $row = Database::fetch_array($rs);
1844
1845
        return $row['document_id'];
1846
    }
1847
1848
    /**
1849
     * allow replace user info in file html
1850
     * @param int $user_id
1851
     * @param string $course_code
1852
     * @param int $sessionId
1853
     * @param bool $is_preview
1854
     * @return string The html content of the certificate
1855
     */
1856
    public static function replace_user_info_into_html($user_id, $course_code, $sessionId, $is_preview = false)
1857
    {
1858
        $user_id = intval($user_id);
1859
        $course_info = api_get_course_info($course_code);
1860
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
1861
        $course_id = $course_info['real_id'];
1862
1863
        $document_id = self::get_default_certificate_id(
1864
            $course_code,
1865
            $sessionId
1866
        );
1867
1868
        $my_content_html = null;
1869
        if ($document_id) {
1870
            $sql = "SELECT path FROM $tbl_document
1871
                    WHERE c_id = $course_id AND id = $document_id";
1872
            $rs = Database::query($sql);
1873
            $new_content = '';
1874
            $all_user_info = array();
1875
            if (Database::num_rows($rs)) {
1876
                $row = Database::fetch_array($rs);
1877
                $filepath = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1878
                if (is_file($filepath)) {
1879
                    $my_content_html = file_get_contents($filepath);
1880
                }
1881
                $all_user_info = self::get_all_info_to_certificate($user_id, $course_code, $is_preview);
1882
1883
                $info_to_be_replaced_in_content_html = $all_user_info[0];
1884
                $info_to_replace_in_content_html = $all_user_info[1];
1885
                $new_content = str_replace(
1886
                    $info_to_be_replaced_in_content_html,
1887
                    $info_to_replace_in_content_html,
1888
                    $my_content_html
1889
                );
1890
            }
1891
1892
            return array(
1893
                'content' => $new_content,
1894
                'variables' => $all_user_info,
1895
            );
1896
        }
1897
        return array();
1898
    }
1899
1900
    /**
1901
     * Return all content to replace and all content to be replace
1902
     * @param int $user_id
1903
     * @param int $course_id
1904
     * @param bool $is_preview
1905
     * @return array
1906
     */
1907
    public static function get_all_info_to_certificate($user_id, $course_id, $is_preview = false)
1908
    {
1909
        $info_list = array();
1910
        $user_id = intval($user_id);
1911
1912
        $course_info = api_get_course_info($course_id);
1913
1914
        //info portal
1915
        $organization_name = api_get_setting('Institution');
1916
        $portal_name = api_get_setting('siteName');
1917
1918
        // Extra user data information
1919
        $extra_user_info_data = UserManager::get_extra_user_data(
1920
            $user_id,
1921
            false,
1922
            false,
1923
            false,
1924
            true
1925
        );
1926
1927
        // get extra fields
1928
        $extraField = new ExtraField('user');
1929
        $extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
1930
1931
        //Student information
1932
        $user_info = api_get_user_info($user_id);
1933
        $first_name = $user_info['firstname'];
1934
        $last_name = $user_info['lastname'];
1935
        $official_code = $user_info['official_code'];
1936
1937
        //Teacher information
1938
        $info_teacher_id = UserManager::get_user_id_of_course_admin_or_session_admin($course_info);
1939
        $teacher_info = api_get_user_info($info_teacher_id);
1940
        $teacher_first_name = $teacher_info['firstname'];
1941
        $teacher_last_name = $teacher_info['lastname'];
1942
1943
        // info gradebook certificate
1944
        $info_grade_certificate = UserManager::get_info_gradebook_certificate($course_id, $user_id);
1945
1946
        $date_certificate = $info_grade_certificate['created_at'];
1947
        $date_long_certificate = '';
1948
1949
        $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
1950
        if (!empty($date_certificate)) {
1951
            $date_long_certificate = api_convert_and_format_date($date_certificate);
1952
            $date_no_time = api_convert_and_format_date($date_certificate, DATE_FORMAT_LONG_NO_DAY);
1953
        }
1954
1955
        if ($is_preview) {
1956
            $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
1957
            $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
1958
        }
1959
1960
        $url = api_get_path(WEB_PATH) . 'certificates/index.php?id=' . $info_grade_certificate['id'];
1961
1962
        $externalStyleFile = api_get_path(SYS_CSS_PATH) . 'themes/' . api_get_visual_theme() . '/certificate.css';
1963
        $externalStyle = '';
1964
1965
        if (is_file($externalStyleFile)) {
1966
            $externalStyle = file_get_contents($externalStyleFile);
1967
        }
1968
1969
        //replace content
1970
        $info_to_replace_in_content_html = array(
1971
            $first_name,
1972
            $last_name,
1973
            $organization_name,
1974
            $portal_name,
1975
            $teacher_first_name,
1976
            $teacher_last_name,
1977
            $official_code,
1978
            $date_long_certificate,
1979
            $date_no_time,
1980
            $course_id,
1981
            $course_info['name'],
1982
            $info_grade_certificate['grade'],
1983
            $url,
1984
            '<a href="' . $url . '" target="_blank">' . get_lang('CertificateOnlineLink') . '</a>',
1985
            '((certificate_barcode))',
1986
            $externalStyle
1987
        );
1988
1989
        $info_to_be_replaced_in_content_html = array('((user_firstname))',
1990
            '((user_lastname))',
1991
            '((gradebook_institution))',
1992
            '((gradebook_sitename))',
1993
            '((teacher_firstname))',
1994
            '((teacher_lastname))',
1995
            '((official_code))',
1996
            '((date_certificate))',
1997
            '((date_certificate_no_time))',
1998
            '((course_code))',
1999
            '((course_title))',
2000
            '((gradebook_grade))',
2001
            '((certificate_link))',
2002
            '((certificate_link_html))',
2003
            '((certificate_barcode))',
2004
            '((external_style))'
2005
        );
2006
2007
        if (!empty($extraFields)) {
2008
            foreach ($extraFields as $extraField) {
2009
                $valueExtra = isset($extra_user_info_data[$extraField['variable']]) ? $extra_user_info_data[$extraField['variable']] : '';
2010
                $info_to_be_replaced_in_content_html[] = '((' . strtolower($extraField['variable']) . '))';
2011
                $info_to_replace_in_content_html[] = $valueExtra;
2012
            }
2013
        }
2014
2015
        $info_list[] = $info_to_be_replaced_in_content_html;
2016
        $info_list[] = $info_to_replace_in_content_html;
2017
2018
        return $info_list;
2019
    }
2020
2021
    /**
2022
     * Remove default certificate
2023
     * @param string $course_id The course code
2024
     * @param int $default_certificate_id The document id of the default certificate
2025
     * @return void
2026
     */
2027
    public static function remove_attach_certificate($course_id, $default_certificate_id)
2028
    {
2029
        if (empty($default_certificate_id)) {
2030
            return false;
2031
        }
2032
2033
        $default_certificate = self::get_default_certificate_id($course_id);
2034
        if ((int) $default_certificate == (int) $default_certificate_id) {
2035
            $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
2036
            $session_id = api_get_session_id();
2037 View Code Duplication
            if ($session_id == 0 || is_null($session_id)) {
2038
                $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
2039
            } elseif ($session_id > 0) {
2040
                $sql_session = 'AND session_id=' . intval($session_id);
2041
            } else {
2042
                $sql_session = '';
2043
            }
2044
2045
            $sql = 'UPDATE ' . $tbl_category . ' SET document_id = null
2046
                    WHERE
2047
                        course_code = "' . Database::escape_string($course_id) . '" AND
2048
                        document_id="' . $default_certificate_id . '" ' . $sql_session;
2049
            Database::query($sql);
2050
        }
2051
    }
2052
2053
    /**
2054
     * Create directory certificate
2055
     * @param array $courseInfo
2056
     * @return void
2057
     */
2058
    public static function create_directory_certificate_in_course($courseInfo)
2059
    {
2060
        if (!empty($courseInfo)) {
2061
            $to_group_id = 0;
2062
            $to_user_id = null;
2063
            $course_dir = $courseInfo['path'] . "/document/";
2064
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
2065
            $base_work_dir = $sys_course_path . $course_dir;
2066
            $base_work_dir_test = $base_work_dir . 'certificates';
2067
            $dir_name = '/certificates';
2068
            $post_dir_name = get_lang('CertificatesFiles');
2069
            $visibility_command = 'invisible';
2070
2071
            $id = self::get_document_id_of_directory_certificate();
2072
2073
            if (empty($id)) {
2074
                create_unexisting_directory(
2075
                    $courseInfo,
2076
                    api_get_user_id(),
2077
                    api_get_session_id(),
2078
                    $to_group_id,
2079
                    $to_user_id,
2080
                    $base_work_dir,
2081
                    $dir_name,
2082
                    $post_dir_name,
2083
                    null,
2084
                    false
2085
                );
2086
2087
                $id = self::get_document_id_of_directory_certificate();
2088
2089
                if (empty($id)) {
2090
                    $id = add_document(
2091
                        $courseInfo,
2092
                        $dir_name,
2093
                        'folder',
2094
                        0,
2095
                        $post_dir_name,
2096
                        null,
2097
                        0,
2098
                        true,
2099
                        $to_group_id
2100
                    );
2101
                }
2102
2103
                if (!empty($id)) {
2104
                    api_item_property_update(
2105
                        $courseInfo,
2106
                        TOOL_DOCUMENT,
2107
                        $id,
2108
                        $visibility_command,
2109
                        api_get_user_id()
2110
                    );
2111
                }
2112
            }
2113
        }
2114
    }
2115
2116
    /**
2117
     * Get the document id of the directory certificate
2118
     * @return int The document id of the directory certificate
2119
     */
2120
    public static function get_document_id_of_directory_certificate()
2121
    {
2122
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
2123
        $course_id = api_get_course_int_id();
2124
        $sql = "SELECT id FROM $tbl_document 
2125
                WHERE c_id = $course_id AND path='/certificates' ";
2126
        $rs = Database::query($sql);
2127
        $row = Database::fetch_array($rs);
2128
        return $row['id'];
2129
    }
2130
2131
    /**
2132
     * Check if a directory given is for certificate
2133
     * @param string $dir path of directory
2134
     * @return bool  true if is a certificate or false otherwise
2135
     */
2136
    public static function is_certificate_mode($dir)
2137
    {
2138
        // I'm in the certification module?
2139
        $is_certificate_mode = false;
2140
        $is_certificate_array = explode('/', $dir);
2141
        array_shift($is_certificate_array);
2142
        if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
2143
            $is_certificate_mode = true;
2144
        }
2145
        return $is_certificate_mode;
2146
    }
2147
2148
    /**
2149
     * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
2150
     * This allows for a better SCORM export or replace urls inside content html from copy course
2151
     * The list will generally include pictures, flash objects, java applets, or any other
2152
     * stuff included in the source of the current item. The current item is expected
2153
     * to be an HTML file or string html. If it is not, then the function will return and empty list.
2154
     * @param	string  source html (content or path)
2155
     * @param	bool  	is file or string html
2156
     * @param	string	type (one of the app tools) - optional (otherwise takes the current item's type)
2157
     * @param	int		level of recursivity we're in
2158
     * @return	array	List of file paths. An additional field containing 'local' or 'remote' helps determine
2159
     * if the file should be copied into the zip or just linked
2160
     */
2161
    public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
2162
    {
2163
        $max = 5;
2164
        $attributes = array();
2165
        $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars', 'poster');
2166
        $explode_attributes = array('flashvars' => 'file');
2167
        $abs_path = '';
2168
2169
        if ($recursivity > $max) {
2170
            return array();
2171
        }
2172
2173
        if (!isset($type)) {
2174
            $type = TOOL_DOCUMENT;
2175
        }
2176
2177
        if (!$is_file) {
2178
            $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
2179
        } else {
2180
            if (is_file($source_html)) {
2181
                $abs_path = $source_html;
2182
                //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
2183
                $info = pathinfo($abs_path);
2184
                $ext = $info['extension'];
2185
                switch (strtolower($ext)) {
2186
                    case 'html':
2187
                    case 'htm':
2188
                    case 'shtml':
2189
                    case 'css':
2190
                        $file_content = file_get_contents($abs_path);
2191
                        //get an array of attributes from the HTML source
2192
                        $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
2193
                        break;
2194
                    default:
2195
                        break;
2196
                }
2197
            } else {
2198
                return false;
2199
            }
2200
        }
2201
2202
        $files_list = array();
2203
2204
        switch ($type) {
2205
            case TOOL_DOCUMENT:
2206
            case TOOL_QUIZ:
2207
            case 'sco':
2208
                foreach ($wanted_attributes as $attr) {
2209
                    if (isset($attributes[$attr])) {
2210
                        //find which kind of path these are (local or remote)
2211
                        $sources = $attributes[$attr];
2212
                        foreach ($sources as $source) {
2213
                            //skip what is obviously not a resource
2214
                            if (strpos($source, '+this.')) {
2215
                                continue; //javascript code - will still work unaltered
2216
                            }
2217
                            if (strpos($source, '.') === false) {
2218
                                continue; //no dot, should not be an external file anyway
2219
                            }
2220
                            if (strpos($source, 'mailto:')) {
2221
                                continue; //mailto link
2222
                            }
2223
                            if (strpos($source, ';') && !strpos($source, '&amp;')) {
2224
                                continue; //avoid code - that should help
2225
                            }
2226
2227 View Code Duplication
                            if ($attr == 'value') {
2228
                                if (strpos($source, 'mp3file')) {
2229
                                    $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
2230
                                    $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
2231
                                    if (substr($mp3file, 0, 1) == '/') {
2232
                                        $files_list[] = array($mp3file, 'local', 'abs');
2233
                                    } else {
2234
                                        $files_list[] = array($mp3file, 'local', 'rel');
2235
                                    }
2236
                                } elseif (strpos($source, 'flv=') === 0) {
2237
                                    $source = substr($source, 4);
2238
                                    if (strpos($source, '&') > 0) {
2239
                                        $source = substr($source, 0, strpos($source, '&'));
2240
                                    }
2241
                                    if (strpos($source, '://') > 0) {
2242
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2243
                                            //we found the current portal url
2244
                                            $files_list[] = array($source, 'local', 'url');
2245
                                        } else {
2246
                                            //we didn't find any trace of current portal
2247
                                            $files_list[] = array($source, 'remote', 'url');
2248
                                        }
2249
                                    } else {
2250
                                        $files_list[] = array($source, 'local', 'abs');
2251
                                    }
2252
                                    /* skipping anything else to avoid two entries
2253
                                    (while the others can have sub-files in their url, flv's can't)*/
2254
                                    continue;
2255
                                }
2256
                            }
2257
                            if (strpos($source, '://') > 0) {
2258
                                //cut at '?' in a URL with params
2259
                                if (strpos($source, '?') > 0) {
2260
                                    $second_part = substr($source, strpos($source, '?'));
2261
                                    if (strpos($second_part, '://') > 0) {
2262
                                        //if the second part of the url contains a url too, treat the second one before cutting
2263
                                        $pos1 = strpos($second_part, '=');
2264
                                        $pos2 = strpos($second_part, '&');
2265
                                        $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
2266 View Code Duplication
                                        if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
2267
                                            //we found the current portal url
2268
                                            $files_list[] = array($second_part, 'local', 'url');
2269
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2270
                                            if (count($in_files_list) > 0) {
2271
                                                $files_list = array_merge($files_list, $in_files_list);
2272
                                            }
2273
                                        } else {
2274
                                            //we didn't find any trace of current portal
2275
                                            $files_list[] = array($second_part, 'remote', 'url');
2276
                                        }
2277 View Code Duplication
                                    } elseif (strpos($second_part, '=') > 0) {
2278
                                        if (substr($second_part, 0, 1) === '/') {
2279
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2280
                                            $files_list[] = array($second_part, 'local', 'abs');
2281
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2282
                                            if (count($in_files_list) > 0) {
2283
                                                $files_list = array_merge($files_list, $in_files_list);
2284
                                            }
2285
                                        } 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...
2286
                                            //link is relative but going back in the hierarchy
2287
                                            $files_list[] = array($second_part, 'local', 'rel');
2288
                                            //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
2289
                                            //$new_abs_path = realpath($dir.'/'.$second_part);
2290
                                            $dir = '';
2291
                                            if (!empty($abs_path)) {
2292
                                                $dir = dirname($abs_path) . '/';
2293
                                            }
2294
                                            $new_abs_path = realpath($dir . $second_part);
2295
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2296
                                            if (count($in_files_list) > 0) {
2297
                                                $files_list = array_merge($files_list, $in_files_list);
2298
                                            }
2299
                                        } else {
2300
                                            //no starting '/', making it relative to current document's path
2301
                                            if (substr($second_part, 0, 2) == './') {
2302
                                                $second_part = substr($second_part, 2);
2303
                                            }
2304
                                            $files_list[] = array($second_part, 'local', 'rel');
2305
                                            $dir = '';
2306
                                            if (!empty($abs_path)) {
2307
                                                $dir = dirname($abs_path) . '/';
2308
                                            }
2309
                                            $new_abs_path = realpath($dir . $second_part);
2310
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2311
                                            if (count($in_files_list) > 0) {
2312
                                                $files_list = array_merge($files_list, $in_files_list);
2313
                                            }
2314
                                        }
2315
                                    }
2316
                                    //leave that second part behind now
2317
                                    $source = substr($source, 0, strpos($source, '?'));
2318
                                    if (strpos($source, '://') > 0) {
2319 View Code Duplication
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2320
                                            //we found the current portal url
2321
                                            $files_list[] = array($source, 'local', 'url');
2322
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2323
                                            if (count($in_files_list) > 0) {
2324
                                                $files_list = array_merge($files_list, $in_files_list);
2325
                                            }
2326
                                        } else {
2327
                                            //we didn't find any trace of current portal
2328
                                            $files_list[] = array($source, 'remote', 'url');
2329
                                        }
2330 View Code Duplication
                                    } else {
2331
                                        //no protocol found, make link local
2332
                                        if (substr($source, 0, 1) === '/') {
2333
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2334
                                            $files_list[] = array($source, 'local', 'abs');
2335
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2336
                                            if (count($in_files_list) > 0) {
2337
                                                $files_list = array_merge($files_list, $in_files_list);
2338
                                            }
2339
                                        } 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...
2340
                                            $files_list[] = array($source, 'local', 'rel');
2341
                                            $dir = '';
2342
                                            if (!empty($abs_path)) {
2343
                                                $dir = dirname($abs_path) . '/';
2344
                                            }
2345
                                            $new_abs_path = realpath($dir . $source);
2346
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2347
                                            if (count($in_files_list) > 0) {
2348
                                                $files_list = array_merge($files_list, $in_files_list);
2349
                                            }
2350
                                        } else {
2351
                                            //no starting '/', making it relative to current document's path
2352
                                            if (substr($source, 0, 2) == './') {
2353
                                                $source = substr($source, 2);
2354
                                            }
2355
                                            $files_list[] = array($source, 'local', 'rel');
2356
                                            $dir = '';
2357
                                            if (!empty($abs_path)) {
2358
                                                $dir = dirname($abs_path) . '/';
2359
                                            }
2360
                                            $new_abs_path = realpath($dir . $source);
2361
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2362
                                            if (count($in_files_list) > 0) {
2363
                                                $files_list = array_merge($files_list, $in_files_list);
2364
                                            }
2365
                                        }
2366
                                    }
2367
                                }
2368
                                //found some protocol there
2369 View Code Duplication
                                if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2370
                                    //we found the current portal url
2371
                                    $files_list[] = array($source, 'local', 'url');
2372
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2373
                                    if (count($in_files_list) > 0) {
2374
                                        $files_list = array_merge($files_list, $in_files_list);
2375
                                    }
2376
                                } else {
2377
                                    //we didn't find any trace of current portal
2378
                                    $files_list[] = array($source, 'remote', 'url');
2379
                                }
2380 View Code Duplication
                            } else {
2381
                                //no protocol found, make link local
2382
                                if (substr($source, 0, 1) === '/') {
2383
                                    //link starts with a /, making it absolute (relative to DocumentRoot)
2384
                                    $files_list[] = array($source, 'local', 'abs');
2385
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2386
                                    if (count($in_files_list) > 0) {
2387
                                        $files_list = array_merge($files_list, $in_files_list);
2388
                                    }
2389
                                } elseif (strpos($source, '..') === 0) {
2390
                                    //link is relative but going back in the hierarchy
2391
                                    $files_list[] = array($source, 'local', 'rel');
2392
                                    $dir = '';
2393
                                    if (!empty($abs_path)) {
2394
                                        $dir = dirname($abs_path) . '/';
2395
                                    }
2396
                                    $new_abs_path = realpath($dir . $source);
2397
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2398
                                    if (count($in_files_list) > 0) {
2399
                                        $files_list = array_merge($files_list, $in_files_list);
2400
                                    }
2401
                                } else {
2402
                                    //no starting '/', making it relative to current document's path
2403
                                    if (substr($source, 0, 2) == './') {
2404
                                        $source = substr($source, 2);
2405
                                    }
2406
                                    $files_list[] = array($source, 'local', 'rel');
2407
                                    $dir = '';
2408
                                    if (!empty($abs_path)) {
2409
                                        $dir = dirname($abs_path) . '/';
2410
                                    }
2411
                                    $new_abs_path = realpath($dir . $source);
2412
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2413
                                    if (count($in_files_list) > 0) {
2414
                                        $files_list = array_merge($files_list, $in_files_list);
2415
                                    }
2416
                                }
2417
                            }
2418
                        }
2419
                    }
2420
                }
2421
                break;
2422
            default: //ignore
2423
                break;
2424
        }
2425
2426
        $checked_files_list = array();
2427
        $checked_array_list = array();
2428
2429
        if (count($files_list) > 0) {
2430 View Code Duplication
            foreach ($files_list as $idx => $file) {
2431
                if (!empty($file[0])) {
2432
                    if (!in_array($file[0], $checked_files_list)) {
2433
                        $checked_files_list[] = $files_list[$idx][0];
2434
                        $checked_array_list[] = $files_list[$idx];
2435
                    }
2436
                }
2437
            }
2438
        }
2439
2440
        return $checked_array_list;
2441
    }
2442
2443
    /**
2444
     * Parses the HTML attributes given as string.
2445
     *
2446
     * @param    string  HTML attribute string
2447
     * @param	 array	 List of attributes that we want to get back
2448
     * @param    array
2449
     * @return   array   An associative array of attributes
2450
     * @author 	 Based on a function from the HTML_Common2 PEAR module     *
2451
     */
2452
    public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
2453
    {
2454
        $attributes = array();
2455
        $regs = array();
2456
        $reduced = false;
2457
        if (count($wanted) > 0) {
2458
            $reduced = true;
2459
        }
2460
        try {
2461
            //Find all occurences of something that looks like a URL
2462
            // The structure of this regexp is:
2463
            // (find protocol) then
2464
            // (optionally find some kind of space 1 or more times) then
2465
            // find (either an equal sign or a bracket) followed by an optional space
2466
            // followed by some text without quotes (between quotes itself or not)
2467
            // then possible closing brackets if we were in the opening bracket case
2468
            // OR something like @import()
2469
            $res = preg_match_all(
2470
                '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
2471
                // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
2472
                // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
2473
                '([ \n\t\r]+)?(' .
2474
                // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
2475
                '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
2476
                '|' .
2477
                // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
2478
                '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
2479
                '))' .
2480
                '|' .
2481
                // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
2482
                '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
2483
                $attrString,
2484
                $regs
2485
            );
2486
        } catch (Exception $e) {
2487
            error_log('Caught exception: ' . $e->getMessage(), 0);
2488
        }
2489
        if ($res) {
2490
            for ($i = 0; $i < count($regs[1]); $i++) {
2491
                $name = trim($regs[3][$i]);
2492
                $check = trim($regs[0][$i]);
2493
                $value = trim($regs[10][$i]);
2494 View Code Duplication
                if (empty($value) and !empty($regs[13][$i])) {
2495
                    $value = $regs[13][$i];
2496
                }
2497 View Code Duplication
                if (empty($name) && !empty($regs[16][$i])) {
2498
                    $name = '@import';
2499
                    $value = trim($regs[16][$i]);
2500
                }
2501
                if (!empty($name)) {
2502
                    if (!$reduced OR in_array(strtolower($name), $wanted)) {
2503
                        if ($name == $check) {
2504
                            $attributes[strtolower($name)][] = strtolower($name);
2505
                        } else {
2506 View Code Duplication
                            if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
2507
                                $value = substr($value, 1, -1);
2508
                            }
2509
2510
                            if ($value == 'API.LMSGetValue(name') {
2511
                                $value = 'API.LMSGetValue(name)';
2512
                            }
2513
                            //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
2514
                            if (isset($explode_variables[$name])) {
2515
                                $value_modified = str_replace('&amp;', '&', $value);
2516
                                $value_array = explode('&', $value_modified);
2517
                                foreach ($value_array as $item) {
2518
                                    list($key, $item_value) = explode('=', $item);
2519
                                    if ($key == $explode_variables[$name]) {
2520
                                        $attributes[strtolower($name)][] = $item_value;
2521
                                    }
2522
                                }
2523
                            }
2524
                            $attributes[strtolower($name)][] = $value;
2525
                        }
2526
                    }
2527
                }
2528
            }
2529
        }
2530
2531
        return $attributes;
2532
    }
2533
2534
    /**
2535
     * Replace urls inside content html from a copy course
2536
     * @param string $content_html
2537
     * @param string $origin_course_code
2538
     * @param string $destination_course_directory
2539
     * @param string $origin_course_path_from_zip
2540
     * @param string $origin_course_info_path
2541
     *
2542
     * @return string	new content html with replaced urls or return false if content is not a string
2543
     */
2544
    public static function replace_urls_inside_content_html_from_copy_course(
2545
        $content_html,
2546
        $origin_course_code,
2547
        $destination_course_directory,
2548
        $origin_course_path_from_zip = null,
2549
        $origin_course_info_path = null
2550
    ) {
2551
        if (empty($content_html)) {
2552
            return false;
2553
        }
2554
2555
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2556
        $orig_course_info = api_get_course_info($origin_course_code);
2557
2558
        // Course does not exist in the current DB probably this came from a zip file?
2559
        if (empty($orig_course_info)) {
2560
            if (!empty($origin_course_path_from_zip)) {
2561
                $orig_course_path = $origin_course_path_from_zip.'/';
2562
                $orig_course_info_path = $origin_course_info_path;
2563
            }
2564
        } else {
2565
            $orig_course_path = api_get_path(SYS_COURSE_PATH).$orig_course_info['path'] . '/';
2566
            $orig_course_info_path = $orig_course_info['path'];
2567
        }
2568
2569
        $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
2570
        $destination_course_info = api_get_course_info($destination_course_code);
2571
        $dest_course_path = api_get_path(SYS_COURSE_PATH) . $destination_course_directory . '/';
2572
        $dest_course_path_rel = api_get_path(REL_COURSE_PATH) . $destination_course_directory . '/';
2573
2574
        $user_id = api_get_user_id();
2575
2576
        if (!empty($orig_source_html)) {
2577
            foreach ($orig_source_html as $source) {
2578
2579
                // Get information about source url
2580
                $real_orig_url = $source[0]; // url
2581
                $scope_url = $source[1];   // scope (local, remote)
2582
                $type_url = $source[2]; // type (rel, abs, url)
2583
2584
                // Get path and query from origin url
2585
                $orig_parse_url = parse_url($real_orig_url);
2586
                $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
2587
                $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
2588
2589
                // Replace origin course code by destination course code from origin url query
2590
                $dest_url_query = '';
2591
2592
                if (!empty($real_orig_query)) {
2593
                    $dest_url_query = '?' . $real_orig_query;
2594
                    if (strpos($dest_url_query, $origin_course_code) !== false) {
2595
                        $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2596
                    }
2597
                }
2598
2599
                if ($scope_url == 'local') {
2600
                    if ($type_url == 'abs' || $type_url == 'rel') {
2601
                        $document_file = strstr($real_orig_path, 'document');
2602
2603
                        if (strpos($real_orig_path, $document_file) !== false) {
2604
                            $origin_filepath = $orig_course_path.$document_file;
2605
                            $destination_filepath = $dest_course_path.$document_file;
2606
2607
                            // copy origin file inside destination course
2608
                            if (file_exists($origin_filepath)) {
2609
                                $filepath_dir = dirname($destination_filepath);
2610
2611 View Code Duplication
                                if (!is_dir($filepath_dir)) {
2612
                                    $perm = api_get_permissions_for_new_directories();
2613
                                    $result = @mkdir($filepath_dir, $perm, true);
2614
                                    if ($result) {
2615
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
2616
2617
                                        //Add to item properties to the new folder
2618
                                        $doc_id = add_document(
2619
                                            $destination_course_info,
2620
                                            $filepath_to_add,
2621
                                            'folder',
2622
                                            0,
2623
                                            basename($filepath_to_add)
2624
                                        );
2625
                                        api_item_property_update(
2626
                                            $destination_course_info,
2627
                                            TOOL_DOCUMENT,
2628
                                            $doc_id,
2629
                                            'FolderCreated',
2630
                                            $user_id,
2631
                                            null,
2632
                                            null,
2633
                                            null,
2634
                                            null
2635
                                        );
2636
                                    }
2637
                                }
2638
2639 View Code Duplication
                                if (!file_exists($destination_filepath)) {
2640
                                    $result = @copy($origin_filepath, $destination_filepath);
2641
                                    if ($result) {
2642
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
2643
                                        $size = filesize($destination_filepath);
2644
2645
                                        // Add to item properties to the file
2646
                                        $doc_id = add_document(
2647
                                            $destination_course_info,
2648
                                            $filepath_to_add,
2649
                                            'file',
2650
                                            $size,
2651
                                            basename($filepath_to_add)
2652
                                        );
2653
                                        api_item_property_update(
2654
                                            $destination_course_info,
2655
                                            TOOL_DOCUMENT,
2656
                                            $doc_id,
2657
                                            'FolderCreated',
2658
                                            $user_id,
2659
                                            null,
2660
                                            null,
2661
                                            null,
2662
                                            null
2663
                                        );
2664
                                    }
2665
                                }
2666
                            }
2667
2668
                            // Replace origin course path by destination course path.
2669
                            if (strpos($content_html, $real_orig_url) !== false) {
2670
                                $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
2671
2672
                                //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
2673
                                // See BT#7780
2674
                                $destination_url = $dest_course_path_rel . $document_file . $dest_url_query;
2675
2676
                                // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
2677
                                if (strpos($real_orig_path, $origin_course_code) === false) {
2678
                                    $url_course_path = $real_orig_path;
2679
                                    $destination_url = $real_orig_path;
2680
                                }
2681
                                $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2682
                            }
2683
                        }
2684
2685
                        // replace origin course code by destination course code  from origin url
2686
                        if (strpos($real_orig_url, '?') === 0) {
2687
                            $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
2688
                            $content_html = str_replace($real_orig_url, $dest_url, $content_html);
2689
                        }
2690
                    }
2691
                }
2692
            }
2693
        }
2694
2695
        return $content_html;
2696
    }
2697
2698
    /**
2699
     * Replace urls inside content html when moving a file
2700
     * @todo this code is only called in document.php but is commented
2701
     * @param string     content html
2702
     * @param string     origin
2703
     * @param string     destination
2704
     * @return string    new content html with replaced urls or return false if content is not a string
2705
     */
2706
    public function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
2707
    {
2708 View Code Duplication
        if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
2709
            $original = $original_path . $file_name;
2710
        } else {
2711
            $original = $original_path . '/' . $file_name;
2712
        }
2713 View Code Duplication
        if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
2714
            $destination = $destiny_path . $file_name;
2715
        } else {
2716
            $destination = $destiny_path . '/' . $file_name;
2717
        }
2718
        $original_count = count(explode('/', $original));
2719
        $destination_count = count(explode('/', $destination));
2720
        if ($original_count == $destination_count) {
2721
            //Nothing to change
2722
            return true;
2723
        }
2724
        if ($original_count > $destination_count) {
2725
            $mode = 'outside';
2726
        } else {
2727
            $mode = 'inside';
2728
        }
2729
        //We do not select the $original_path becayse the file was already moved
2730
        $content_html = file_get_contents($destiny_path . '/' . $file_name);
2731
        $destination_file = $destiny_path . '/' . $file_name;
2732
2733
        $pre_original = strstr($original_path, 'document');
2734
        $pre_destin = strstr($destiny_path, 'document');
2735
        $pre_original = substr($pre_original, 8, strlen($pre_original));
2736
        $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
2737
2738
        $levels = count(explode('/', $pre_destin)) - 1;
2739
        $link_to_add = '';
2740
        for ($i = 1; $i <= $levels; $i++) {
2741
            $link_to_add .= '../';
2742
        }
2743
2744
        if ($pre_original == '/') {
2745
            $pre_original = '';
2746
        }
2747
2748
        if ($pre_destin == '/') {
2749
            $pre_destin = '';
2750
        }
2751
2752
        if ($pre_original != '') {
2753
            $pre_original = '..' . $pre_original . '/';
2754
        }
2755
2756
        if ($pre_destin != '') {
2757
            $pre_destin = '..' . $pre_destin . '/';
2758
        }
2759
2760
        $levels = explode('/', $pre_original);
2761
        $count_pre_destination_levels = 0;
2762
        foreach ($levels as $item) {
2763
            if (!empty($item) && $item != '..') {
2764
                $count_pre_destination_levels++;
2765
            }
2766
        }
2767
        $count_pre_destination_levels--;
2768
        //$count_pre_destination_levels = count() - 3;
2769
        if ($count_pre_destination_levels == 0) {
2770
            $count_pre_destination_levels = 1;
2771
        }
2772
        //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
2773
        $pre_remove = '';
2774
        for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
2775
            $pre_remove .='..\/';
2776
        }
2777
2778
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2779
2780
        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...
2781
2782
            // get information about source url
2783
            $real_orig_url = $source[0];   // url
2784
            $scope_url = $source[1];   // scope (local, remote)
2785
            $type_url = $source[2];   // tyle (rel, abs, url)
2786
            // Get path and query from origin url
2787
            $orig_parse_url = parse_url($real_orig_url);
2788
            $real_orig_path = $orig_parse_url['path'];
2789
            $real_orig_query = $orig_parse_url['query'];
2790
2791
            // Replace origin course code by destination course code from origin url query
2792
            /*
2793
              $dest_url_query = '';
2794
              if (!empty($real_orig_query)) {
2795
              $dest_url_query = '?'.$real_orig_query;
2796
              if (strpos($dest_url_query,$origin_course_code) !== false) {
2797
              $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2798
              }
2799
              } */
2800
2801
            if ($scope_url == 'local') {
2802
                if ($type_url == 'abs' || $type_url == 'rel') {
2803
                    $document_file = strstr($real_orig_path, 'document');
2804
2805
                    if (strpos($real_orig_path, $document_file) !== false) {
2806
                        echo 'continue1';
2807
                        continue;
2808
                    } else {
2809
                        $real_orig_url_temp = '';
2810
                        if ($mode == 'inside') {
2811
                            $real_orig_url_temp = str_replace('../', '', $real_orig_url);
2812
                            $destination_url = $link_to_add . $real_orig_url_temp;
2813
                        } else {
2814
                            $real_orig_url_temp = $real_orig_url;
2815
2816
                            $destination_url = preg_replace("/" . $pre_remove . "/", '', $real_orig_url, 1);
2817
                        }
2818
                        if ($real_orig_url == $destination_url) {
2819
                            //echo 'continue2';
2820
                            continue;
2821
                        }
2822
                        $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2823
                    }
2824
                } else {
2825
                    echo 'continue3';
2826
                    continue;
2827
                }
2828
            }
2829
        }
2830
        $return = file_put_contents($destination, $content_html);
2831
        return $return;
2832
    }
2833
2834
    /**
2835
     * @param int $document_id
2836
     * @param string $course_code
2837
     */
2838
    public static function export_to_pdf($document_id, $course_code)
2839
    {
2840
        $course_data = api_get_course_info($course_code);
2841
        $document_data = self::get_document_data_by_id($document_id, $course_code);
2842
        $file_path = api_get_path(SYS_COURSE_PATH) . $course_data['path'] . '/document' . $document_data['path'];
2843
        $pdf = new PDF('A4-L', 'L');
2844
        $pdf->html_to_pdf($file_path, $document_data['title'], $course_code);
2845
    }
2846
2847
    /**
2848
     * Uploads a document
2849
     *
2850
     * @param array $files the $_FILES variable
2851
     * @param string $path
2852
     * @param string $title
2853
     * @param string $comment
2854
     * @param int $unzip unzip or not the file
2855
     * @param string $if_exists overwrite, rename or warn (default)
2856
     * @param bool $index_document index document (search xapian module)
2857
     * @param bool $show_output print html messages
2858
     * @param string $fileKey
2859
     * @param bool $treat_spaces_as_hyphens
2860
     *
2861
     * @return array|bool
2862
     */
2863
    public static function upload_document(
2864
        $files,
2865
        $path,
2866
        $title = null,
2867
        $comment = null,
2868
        $unzip = 0,
2869
        $if_exists = null,
2870
        $index_document = false,
2871
        $show_output = false,
2872
        $fileKey = 'file',
2873
        $treat_spaces_as_hyphens = true
2874
    ) {
2875
        $course_info = api_get_course_info();
2876
        $sessionId = api_get_session_id();
2877
        $course_dir = $course_info['path'] . '/document';
2878
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
2879
        $base_work_dir = $sys_course_path . $course_dir;
2880
2881
        $group_properties = GroupManager::get_group_properties(api_get_group_id());
2882
        $groupIid = isset($group_properties['iid']) ? $group_properties['iid'] : 0;
2883
2884
        if (isset($files[$fileKey])) {
2885
            $upload_ok = process_uploaded_file($files[$fileKey], $show_output);
2886
2887
            if ($upload_ok) {
2888
                $new_path = handle_uploaded_document(
2889
                    $course_info,
2890
                    $files[$fileKey],
2891
                    $base_work_dir,
2892
                    $path,
2893
                    api_get_user_id(),
2894
                    $groupIid,
2895
                    null,
2896
                    $unzip,
2897
                    $if_exists,
2898
                    $show_output,
2899
                    false,
2900
                    null,
2901
                    $sessionId,
2902
                    $treat_spaces_as_hyphens
2903
                );
2904
2905
                // Showing message when sending zip files
2906
                if ($new_path === true && $unzip == 1) {
2907
                    if ($show_output) {
2908
                        Display::display_confirmation_message(
0 ignored issues
show
Deprecated Code introduced by
The method Display::display_confirmation_message() has been deprecated with message: use Display::addFlash with Display::return_message

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2909
                            get_lang('UplUploadSucceeded').'<br />',
2910
                            false
2911
                        );
2912
                    }
2913
2914
                    return [
2915
                        'title' => $path,
2916
                        'url' => $path,
2917
                    ];
2918
                }
2919
2920
                if ($new_path) {
2921
                    $documentId = DocumentManager::get_document_id(
2922
                        $course_info,
2923
                        $new_path,
0 ignored issues
show
Bug introduced by
It seems like $new_path defined by handle_uploaded_document...reat_spaces_as_hyphens) on line 2888 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...
2924
                        $sessionId
2925
                    );
2926
2927
                    if (!empty($documentId)) {
2928
                        $table_document = Database::get_course_table(TABLE_DOCUMENT);
2929
                        $params = array();
2930
                        /*if ($if_exists == 'rename') {
2931
                            // Remove prefix
2932
                            $suffix = DocumentManager::getDocumentSuffix(
2933
                                $course_info,
2934
                                $sessionId,
2935
                                api_get_group_id()
2936
                            );
2937
                            $new_path = basename($new_path);
2938
                            $new_path = str_replace($suffix, '', $new_path);
2939
                            error_log('renamed');
2940
                            error_log($new_path);
2941
                            $params['title'] = get_document_title($new_path);
2942
                        } else {
2943
                            if (!empty($title)) {
2944
                                $params['title'] = get_document_title($title);
2945
                            } else {
2946
                                $params['title'] = get_document_title($files['file']['name']);
2947
                            }
2948
                        }*/
2949
2950
                        if (!empty($title)) {
2951
                            $params['title'] = $title;
2952
                        }
2953
2954
                        if (!empty($comment)) {
2955
                            $params['comment'] = trim($comment);
2956
                        }
2957
2958
                        Database::update(
2959
                            $table_document,
2960
                            $params,
2961
                            array(
2962
                                'id = ? AND c_id = ? ' => array(
2963
                                    $documentId,
2964
                                    $course_info['real_id']
2965
                                )
2966
                            )
2967
                        );
2968
                    }
2969
2970
                    if ($index_document) {
2971
                        self::index_document(
2972
                            $documentId,
2973
                            $course_info['code'],
2974
                            null,
2975
                            $_POST['language'],
2976
                            $_REQUEST,
2977
                            $if_exists
2978
                        );
2979
                    }
2980
2981 View Code Duplication
                    if (!empty($documentId) && is_numeric($documentId)) {
2982
                        $documentData = self::get_document_data_by_id(
2983
                            $documentId,
2984
                            $course_info['code'],
2985
                            false,
2986
                            $sessionId
2987
                        );
2988
2989
                        return $documentData;
2990
                    }
2991
                }
2992
            }
2993
        }
2994
2995
        return false;
2996
    }
2997
2998
    /**
2999
     * Obtains the text inside the file with the right parser
3000
     */
3001
    public static function get_text_content($doc_path, $doc_mime)
3002
    {
3003
        // TODO: review w$ compatibility
3004
        // Use usual exec output lines array to store stdout instead of a temp file
3005
        // because we need to store it at RAM anyway before index on ChamiloIndexer object
3006
        $ret_val = null;
3007
        switch ($doc_mime) {
3008
            case 'text/plain':
3009
                $handle = fopen($doc_path, 'r');
3010
                $output = array(fread($handle, filesize($doc_path)));
3011
                fclose($handle);
3012
                break;
3013
            case 'application/pdf':
3014
                exec("pdftotext $doc_path -", $output, $ret_val);
3015
                break;
3016
            case 'application/postscript':
3017
                $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
3018
                exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
3019
                if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
3020
                    return false;
3021
                }
3022
                exec("pdftotext $temp_file -", $output, $ret_val);
3023
                unlink($temp_file);
3024
                break;
3025
            case 'application/msword':
3026
                exec("catdoc $doc_path", $output, $ret_val);
3027
                break;
3028
            case 'text/html':
3029
                exec("html2text $doc_path", $output, $ret_val);
3030
                break;
3031
            case 'text/rtf':
3032
                // Note: correct handling of code pages in unrtf
3033
                // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
3034
                exec("unrtf --text $doc_path", $output, $ret_val);
3035
                if ($ret_val == 127) { // command not found
3036
                    return false;
3037
                }
3038
                // Avoid index unrtf comments
3039
                if (is_array($output) && count($output) > 1) {
3040
                    $parsed_output = array();
3041
                    foreach ($output as & $line) {
3042
                        if (!preg_match('/^###/', $line, $matches)) {
3043
                            if (!empty($line)) {
3044
                                $parsed_output[] = $line;
3045
                            }
3046
                        }
3047
                    }
3048
                    $output = $parsed_output;
3049
                }
3050
                break;
3051
            case 'application/vnd.ms-powerpoint':
3052
                exec("catppt $doc_path", $output, $ret_val);
3053
                break;
3054
            case 'application/vnd.ms-excel':
3055
                exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
3056
                break;
3057
        }
3058
3059
        $content = '';
3060
        if (!is_null($ret_val)) {
3061
            if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
3062
                return false;
3063
            }
3064
        }
3065
        if (isset($output)) {
3066
            foreach ($output as & $line) {
3067
                $content .= $line . "\n";
3068
            }
3069
            return $content;
3070
        } else {
3071
            return false;
3072
        }
3073
    }
3074
3075
    /**
3076
     * Calculates the total size of all documents in a course
3077
     *
3078
     * @author Bert vanderkimpen
3079
     * @param  int $course_id
3080
     * @param  int $group_id (to calculate group document space)
3081
     * @param  int $session_id
3082
     *
3083
     * @return int total size
3084
     */
3085
    public static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
3086
    {
3087
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3088
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
3089
3090
        if (isset($course_id)) {
3091
            $course_id = intval($course_id);
3092
        } else {
3093
            $course_id = api_get_course_int_id();
3094
        }
3095
3096
        $group_condition = null;
3097
        if (isset($group_id)) {
3098
            $group_id = intval($group_id);
3099
            $group_condition = " AND props.to_group_id='" . $group_id . "' ";
3100
        }
3101
3102
        $session_condition = null;
3103
        if (isset($session_id)) {
3104
            $session_id = intval($session_id);
3105
            $session_condition = " AND props.session_id='" . $session_id . "' ";
3106
        }
3107
3108
        $sql = "SELECT SUM(size)
3109
                FROM $TABLE_ITEMPROPERTY AS props
3110
                INNER JOIN $TABLE_DOCUMENT AS docs
3111
                ON (docs.id = props.ref AND props.c_id = docs.c_id)
3112
                WHERE
3113
                    props.c_id 	= $course_id AND
3114
                    docs.c_id 	= $course_id AND
3115
                    props.tool 	= '" . TOOL_DOCUMENT . "' AND
3116
                    props.visibility <> 2
3117
                    $group_condition
3118
                    $session_condition
3119
                ";
3120
        $result = Database::query($sql);
3121
3122
        if ($result && Database::num_rows($result) != 0) {
3123
            $row = Database::fetch_row($result);
3124
            return $row[0];
3125
        } else {
3126
            return 0;
3127
        }
3128
    }
3129
3130
    /**
3131
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3132
     */
3133
    public static function display_quota($course_quota, $already_consumed_space)
3134
    {
3135
        $course_quota_m = round($course_quota / 1048576);
3136
        $already_consumed_space_m = round($already_consumed_space / 1048576);
3137
3138
        $message = get_lang('MaximumAllowedQuota') . ' <strong>' . $course_quota_m . ' megabyte</strong>.<br />';
3139
        $message .= get_lang('CourseCurrentlyUses') . ' <strong>' . $already_consumed_space_m . ' megabyte</strong>.<br />';
3140
3141
        $percentage = round(($already_consumed_space / $course_quota * 100), 1);
3142
3143
        $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
3144
3145
        // Decide where to place percentage in graph
3146
        if ($percentage >= 50) {
3147
            $text_in_filled = '&nbsp;' . $other_percentage . '%';
3148
            $text_in_unfilled = '';
3149
        } else {
3150
            $text_in_unfilled = '&nbsp;' . $other_percentage . '%';
3151
            $text_in_filled = '';
3152
        }
3153
3154
        // Decide the background colour of the graph
3155
        if ($percentage < 65) {
3156
            $colour = '#00BB00';        // Safe - green
3157
        } elseif ($percentage < 90) {
3158
            $colour = '#ffd400';        // Filling up - yelloworange
3159
        } else {
3160
            $colour = '#DD0000';        // Full - red
3161
        }
3162
3163
        // This is used for the table width: a table of only 100 pixels looks too small
3164
        $visual_percentage = 4 * $percentage;
3165
        $visual_other_percentage = 4 * $other_percentage;
3166
3167
        $message .= get_lang('PercentageQuotaInUse') . ': <strong>' . $percentage . '%</strong>.<br />' .
3168
            get_lang('PercentageQuotaFree') . ': <strong>' . $other_percentage . '%</strong>.<br />';
3169
3170
        $show_percentage = '&nbsp;' . $percentage . '%';
3171
        $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">' .
3172
            '<div style="width:' . $percentage . '%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>' .
3173
            '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">' . $show_percentage . '</span></div>';
3174
        echo $message;
3175
    }
3176
3177
    /**
3178
     * Display the document quota in a simple way
3179
     *
3180
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3181
     */
3182
    public static function display_simple_quota($course_quota, $already_consumed_space)
3183
    {
3184
        $course_quota_m = round($course_quota / 1048576);
3185
        $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
3186
        $percentage = $already_consumed_space / $course_quota * 100;
3187
        $percentage = round($percentage, 1);
3188
        $message = get_lang('YouAreCurrentlyUsingXOfYourX');
3189
        $message = sprintf($message, $already_consumed_space_m, $percentage . '%', $course_quota_m . ' ');
3190
3191
        return Display::div($message, array('id' => 'document_quota'));
3192
    }
3193
3194
    /**
3195
     * Checks if there is enough place to add a file on a directory
3196
     * on the base of a maximum directory size allowed
3197
     *
3198
     * @author Bert Vanderkimpen
3199
     * @param  int $file_size size of the file in byte
3200
     * @param  int $max_dir_space maximum size
3201
     * @return boolean true if there is enough space, false otherwise
3202
     *
3203
     * @see enough_space() uses  documents_total_space() function
3204
     */
3205
    public static function enough_space($file_size, $max_dir_space)
3206
    {
3207
        if ($max_dir_space) {
3208
            $already_filled_space = self::documents_total_space();
3209
            if (($file_size + $already_filled_space) > $max_dir_space) {
3210
                return false;
3211
            }
3212
        }
3213
        return true;
3214
    }
3215
3216
    /**
3217
     * @param array $params count, url, extension
3218
     * @return string
3219
     */
3220
    public static function generate_jplayer_jquery($params = array())
3221
    {
3222
        $js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
3223
3224
        $js = '
3225
            $("#jquery_jplayer_' . $params['count'] . '").jPlayer({
3226
                ready: function() {
3227
                    $(this).jPlayer("setMedia", {
3228
                        ' . $params['extension'] . ' : "' . $params['url'] . '"
3229
                    });
3230
                },
3231
                play: function() { // To avoid both jPlayers playing together.
3232
                    $(this).jPlayer("pauseOthers");
3233
                },
3234
                //errorAlerts: true,
3235
                //warningAlerts: true,
3236
                swfPath: "' . $js_path . 'jquery-jplayer/jplayer/",
3237
                //supplied: "m4a, oga, mp3, ogg, wav",
3238
                supplied: "' . $params['extension'] . '",
3239
                wmode: "window",
3240
                solution: "flash, html",  // Do not change this setting
3241
                cssSelectorAncestor: "#jp_container_' . $params['count'] . '",
3242
            });  	 ' . "\n\n";
3243
3244
        return $js;
3245
    }
3246
3247
    /**
3248
     *
3249
     * Shows a play icon next to the document title in the document list
3250
     * @param int
3251
     * @param string
3252
     * @return string	html content
3253
     */
3254
    public static function generate_media_preview($i, $type = 'simple')
3255
    {
3256
        $i = intval($i);
3257
        $extra_controls = $progress = '';
3258
        if ($type == 'advanced') {
3259
            $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
3260
                                <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
3261
                                <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
3262
            $progress = '<div class="jp-progress">
3263
                                <div class="jp-seek-bar">
3264
                                    <div class="jp-play-bar"></div>
3265
                                </div>
3266
                            </div>';
3267
        }
3268
3269
        //Shows only the play button
3270
        $html = '<div id="jquery_jplayer_' . $i . '" class="jp-jplayer"></div>
3271
                <div id="jp_container_' . $i . '" class="jp-audio">
3272
                    <div class="jp-type-single">
3273
                        <div class="jp-gui jp-interface">
3274
                            <ul class="jp-controls">
3275
                                <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
3276
                                <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
3277
                                ' . $extra_controls . '
3278
                            </ul>
3279
                            ' . $progress . '
3280
                        </div>
3281
                    </div>
3282
                </div>';
3283
        //<div id="jplayer_inspector_'.$i.'"></div>
3284
        return $html;
3285
    }
3286
3287
    /**
3288
     * @param array $document_data
3289
     * @return string
3290
     */
3291
    public static function generate_video_preview($document_data = array())
3292
    {
3293
        //<button class="jp-video-play-icon" role="button" tabindex="0">play</button>
3294
        $html = '
3295
        <div id="jp_container_1" class="jp-video center-block" role="application" aria-label="media player">
3296
            <div class="jp-type-single">
3297
                <div id="jquery_jplayer_1" class="jp-jplayer"></div>
3298
                <div class="jp-gui">
3299
                    <div class="jp-video-play">
3300
                    </div>
3301
                    <div class="jp-interface">
3302
                        <div class="jp-progress">
3303
                            <div class="jp-seek-bar">
3304
                                <div class="jp-play-bar"></div>
3305
                            </div>
3306
                        </div>
3307
                        <div class="jp-current-time" role="timer" aria-label="time">&nbsp;</div>
3308
                        <div class="jp-duration" role="timer" aria-label="duration">&nbsp;</div>
3309
                        <div class="jp-controls-holder">
3310
                          <div class="jp-controls">
3311
                            <button class="jp-play" role="button" tabindex="0">play</button>
3312
                            <button class="jp-stop" role="button" tabindex="0">stop</button>
3313
                          </div>
3314
                          <div class="jp-volume-controls">
3315
                            <button class="jp-mute" role="button" tabindex="0">mute</button>
3316
                            <button class="jp-volume-max" role="button" tabindex="0">max volume</button>
3317
                            <div class="jp-volume-bar">
3318
                                <div class="jp-volume-bar-value"></div>
3319
                            </div>
3320
                          </div>
3321
                          <div class="jp-toggles">
3322
                            <button class="jp-repeat" role="button" tabindex="0">repeat</button>
3323
                            <button class="jp-full-screen" role="button" tabindex="0">full screen</button>
3324
                          </div>
3325
                        </div>
3326
                        <div class="jp-details">
3327
                          <div class="jp-title" aria-label="title">&nbsp;</div>
3328
                        </div>
3329
                    </div>
3330
                </div>
3331
                <div class="jp-no-solution">
3332
                    <span>' . get_lang('UpdateRequire') . '</span>
3333
                    ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile") . '
3334
                </div>
3335
            </div>
3336
        </div>';
3337
        return $html;
3338
    }
3339
3340
    /**
3341
     * @param array $course_info
3342
     * @param bool $lp_id
3343
     * @param string $target
3344
     * @param int $session_id
3345
     * @param bool $add_move_button
3346
     * @param string $filter_by_folder
3347
     * @param string $overwrite_url
3348
     * @param bool $showInvisibleFiles
3349
     * @param bool $showOnlyFolders
3350
     * @param int $folderId
3351
     * @return string
3352
     */
3353
    public static function get_document_preview(
3354
        $course_info,
3355
        $lp_id = false,
3356
        $target = '',
3357
        $session_id = 0,
3358
        $add_move_button = false,
3359
        $filter_by_folder = null,
3360
        $overwrite_url = null,
3361
        $showInvisibleFiles = false,
3362
        $showOnlyFolders = false,
3363
        $folderId = false
3364
    ) {
3365
        if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
3366
            return '';
3367
        }
3368
3369
        $overwrite_url = Security::remove_XSS($overwrite_url);
3370
        $user_id = api_get_user_id();
3371
        $user_in_course = false;
3372
3373
        if (api_is_platform_admin()) {
3374
            $user_in_course = true;
3375
        }
3376
3377
        if (!$user_in_course) {
3378
            if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
3379
                $user_in_course = true;
3380
            }
3381
        }
3382
3383
        // Condition for the session
3384
        $session_id = intval($session_id);
3385
3386
        if (!$user_in_course) {
3387
            if (empty($session_id)) {
3388
                if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
3389
                    $user_in_course = true;
3390
                }
3391
                // Check if course is open then we can consider that the student is registered to the course
3392
                if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
3393
                    $user_in_course = true;
3394
                }
3395 View Code Duplication
            } else {
3396
                $user_status = SessionManager::get_user_status_in_course_session(
3397
                    $user_id,
3398
                    $course_info['real_id'],
3399
                    $session_id
3400
                );
3401
                //is true if is an student, course session teacher or coach
3402
                if (in_array($user_status, array('0', '2', '6'))) {
3403
                    $user_in_course = true;
3404
                }
3405
            }
3406
        }
3407
3408
        $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
3409
        $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
3410
        $condition_session = " AND (last.session_id = '$session_id' OR last.session_id = '0' OR last.session_id IS NULL)";
3411
3412
        $add_folder_filter = null;
3413
        if (!empty($filter_by_folder)) {
3414
            $add_folder_filter = " AND docs.path LIKE '" . Database::escape_string($filter_by_folder) . "%'";
3415
        }
3416
3417
        // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
3418
        $lp_visibility_condition = null;
3419
        if ($lp_id) {
3420
            // $lp_visibility_condition = " OR filetype='folder'";
3421
            if ($showInvisibleFiles) {
3422
                $lp_visibility_condition .= ' OR last.visibility = 0';
3423
            }
3424
        }
3425
3426
        $showOnlyFoldersCondition = null;
3427
        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...
3428
            //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
3429
        }
3430
3431
        $folderCondition = " AND docs.path LIKE '/%' ";
3432
3433
        if (!api_is_allowed_to_edit()) {
3434
            $protectedFolders = self::getProtectedFolderFromStudent();
3435
            foreach ($protectedFolders as $folder) {
3436
                $folderCondition .= " AND docs.path NOT LIKE '$folder' ";
3437
            }
3438
        }
3439
3440
        $parentData = [];
3441
        if ($folderId !== false) {
3442
            $parentData = self::get_document_data_by_id($folderId, $course_info['code'], false, $session_id);
3443
            if (!empty($parentData)) {
3444
                $cleanedPath = $parentData['path'];
3445
                $num = substr_count($cleanedPath, '/');
3446
3447
                $notLikeCondition = null;
3448
                for ($i = 1; $i <= $num; $i++) {
3449
                    $repeat = str_repeat('/%', $i+1);
3450
                    $notLikeCondition .= " AND docs.path NOT LIKE '".Database::escape_string($cleanedPath.$repeat)."' ";
3451
                }
3452
3453
                $folderCondition = " AND
3454
                    docs.id <> $folderId AND
3455
                    docs.path LIKE '".$cleanedPath."/%'
3456
                    $notLikeCondition
3457
                ";
3458
            } else {
3459
                $folderCondition = " AND
3460
                docs.filetype = 'file' ";
3461
            }
3462
        }
3463
3464
        $levelCondition = null;
3465
        if ($folderId === false) {
3466
            $levelCondition = " AND docs.path NOT LIKE'/%/%'";
3467
        }
3468
3469
        $sql = "SELECT DISTINCT last.visibility, docs.*
3470
                FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
3471
                ON (docs.id = last.ref AND docs.c_id = last.c_id)
3472
                WHERE
3473
                    docs.path NOT LIKE '%_DELETED_%' AND
3474
                    last.tool = '" . TOOL_DOCUMENT . "' $condition_session AND
3475
                    (last.visibility = '1' $lp_visibility_condition) AND
3476
                    last.visibility <> 2 AND
3477
                    docs.c_id = {$course_info['real_id']} AND
3478
                    last.c_id = {$course_info['real_id']}
3479
                    $showOnlyFoldersCondition
3480
                    $folderCondition
3481
                    $levelCondition
3482
                    $add_folder_filter
3483
                ORDER BY docs.filetype DESC, docs.title ASC";
3484
3485
        $res_doc = Database::query($sql);
3486
        $resources = Database::store_result($res_doc, 'ASSOC');
3487
3488
        $return = '';
3489
        if ($lp_id) {
3490
            if ($folderId === false) {
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...
3491
                /*$return .= '<div class="lp_resource_element">';
3492
                $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
3493
                $return .= Display::url(
3494
                    get_lang('CreateTheDocument'),
3495
                    api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
3496
                );
3497
                $return .= '</div>';*/
3498
            }
3499
        } else {
3500
            $return .= Display::div(
3501
                Display::url(
3502
                    Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
3503
                    ' javascript:void(0);',
3504
                    array('id' => 'close_div_' . $course_info['real_id'] . '_' . $session_id, 'class' => 'close_div')
3505
                ),
3506
                array('style' => 'position:absolute;right:10px')
3507
            );
3508
        }
3509
3510
        // If you want to debug it, I advise you to do "echo" on the eval statements.
3511
        $newResources = array();
3512
3513
        if (!empty($resources) && $user_in_course) {
3514
            foreach ($resources as $resource) {
3515
                $is_visible = self::is_visible_by_id(
3516
                    $resource['id'],
3517
                    $course_info,
3518
                    $session_id,
3519
                    api_get_user_id()
3520
                );
3521
3522
                if ($showInvisibleFiles == false) {
3523
                    if (!$is_visible) {
3524
                        continue;
3525
                    }
3526
                }
3527
3528
                $newResources[] = $resource;
3529
            }
3530
        }
3531
3532
        $label = get_lang('Documents');
3533
3534
        $documents = [];
3535
        if ($folderId === false) {
3536
            $documents[$label] = array(
3537
                'id' => 0,
3538
                'files' => $newResources
3539
            );
3540
        } else {
3541
            if (is_array($parentData)) {
3542
                $documents[$parentData['title']] = array(
3543
                    'id' => intval($folderId),
3544
                    'files' => $newResources
3545
                );
3546
            }
3547
        }
3548
3549
        $write_result = self::write_resources_tree(
3550
            $course_info,
3551
            $session_id,
3552
            $documents,
3553
            $lp_id,
3554
            $target,
3555
            $add_move_button,
3556
            $overwrite_url,
3557
            $folderId
3558
        );
3559
3560
        $return .= $write_result;
3561
        if ($lp_id == false) {
3562
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
3563
            $return .= "<script>
3564
            $('.doc_folder').click(function() {
3565
                var realId = this.id;
3566
                var my_id = this.id.split('_')[2];
3567
                var tempId = 'temp_'+my_id;
3568
                $('#res_'+my_id).show();
3569
3570
                var tempDiv = $('#'+realId).find('#'+tempId);
3571
                if (tempDiv.length == 0) {
3572
                    $.ajax({
3573
                        async: false,
3574
                        type: 'GET',
3575
                        url:  '".$url."',
3576
                        data: 'folder_id='+my_id,
3577
                        success: function(data) {
3578
                            $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
3579
                        }
3580
                    });
3581
                }
3582
            });
3583
3584
            $('.close_div').click(function() {
3585
                var course_id = this.id.split('_')[2];
3586
                var session_id = this.id.split('_')[3];
3587
                $('#document_result_'+course_id+'_'+session_id).hide();
3588
                $('.lp_resource').remove();
3589
                $('.document_preview_container').html('');
3590
            });
3591
3592
            </script>";
3593 View Code Duplication
        } else {
3594
            //For LPs
3595
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
3596
            $return .= "<script>
3597
3598
            function testResources(id, img) {
3599
                var numericId = id.split('_')[1];
3600
                var parentId = 'doc_id_'+numericId;
3601
                var tempId = 'temp_'+numericId;
3602
                var image = $('#'+img);
3603
3604
                if (image.hasClass('open')) {
3605
                    image.removeClass('open');
3606
                    image.attr('src', '" . Display::returnIconPath('nolines_plus.gif')."');
3607
                    $('#'+id).show();
3608
                    $('#'+tempId).hide();
3609
                } else {
3610
                    image.addClass('open');
3611
                    image.attr('src', '" . Display::returnIconPath('nolines_minus.gif') . "');
3612
                    $('#'+id).hide();
3613
                    $('#'+tempId).show();
3614
3615
                    var tempDiv = $('#'+parentId).find('#'+tempId);
3616
                    if (tempDiv.length == 0) {
3617
                        $.ajax({
3618
                            type: 'GET',
3619
                            async: false,
3620
                            url:  '".$url."',
3621
                            data: 'folder_id='+numericId,
3622
                            success: function(data) {
3623
                                tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
3624
                            }
3625
                        });
3626
                    }
3627
                }
3628
            }
3629
            </script>";
3630
        }
3631
3632
        if (!$user_in_course) {
3633
            $return = '';
3634
        }
3635
3636
        return $return;
3637
    }
3638
3639
    /**
3640
     * @param array $course_info
3641
     * @param int $session_id
3642
     * @param array $resource
3643
     * @param int $lp_id
3644
     * @param bool $add_move_button
3645
     * @param string $target
3646
     * @param string $overwrite_url
3647
     * @return null|string
3648
     */
3649
    private static function parseFile(
3650
        $course_info,
3651
        $session_id,
3652
        $resource,
3653
        $lp_id,
3654
        $add_move_button,
3655
        $target,
3656
        $overwrite_url
3657
    ) {
3658
        $img_sys_path = api_get_path(SYS_CODE_PATH) . 'img/';
3659
        $web_code_path = api_get_path(WEB_CODE_PATH);
3660
3661
        $documentId = $resource['id'];
3662
        $path = $resource['path'];
3663
3664
        if (empty($path)) {
3665
            $num = 0;
3666
        } else {
3667
            $num = substr_count($path, '/') - 1;
3668
        }
3669
3670
        // It's a file.
3671
        $icon = choose_image($path);
3672
        $position = strrpos($icon, '.');
3673
        $icon = substr($icon, 0, $position) . '_small.gif';
3674
        $my_file_title = $resource['title'];
3675
        $visibility = $resource['visibility'];
3676
3677
        // If title is empty we try to use the path
3678
        if (empty($my_file_title)) {
3679
            $my_file_title = basename($path);
3680
        }
3681
3682
        // Show the "image name" not the filename of the image.
3683
        if ($lp_id) {
3684
            // LP URL
3685
            $url = api_get_path(WEB_CODE_PATH) . 'lp/lp_controller.php?'.api_get_cidreq().'&amp;action=add_item&amp;type=' . TOOL_DOCUMENT . '&amp;file=' . $documentId . '&amp;lp_id=' . $lp_id;
3686 View Code Duplication
            if (!empty($overwrite_url)) {
3687
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId.'';
3688
            }
3689
        } else {
3690
            // Direct document URL
3691
            $url = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
3692 View Code Duplication
            if (!empty($overwrite_url)) {
3693
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId;
3694
            }
3695
        }
3696
3697
        $img = Display::returnIconPath($icon);
3698
        if (!file_exists($img_sys_path . $icon)) {
3699
            $img = Display::returnIconPath('default_small.gif');
3700
        }
3701
3702
        $link = Display::url(
3703
            '<img alt="" src="' . $img . '" title="" />&nbsp;' . $my_file_title, $url,
3704
            array('target' => $target, 'class' => 'moved')
3705
        );
3706
3707
        $directUrl = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
3708
3709
        $link .= Display::url(
3710
            Display::return_icon('preview_view.png', get_lang('Preview')),
3711
            $directUrl,
3712
            ['target' => '_blank']
3713
        );
3714
3715
        $visibilityClass = null;
3716
        if ($visibility == 0) {
3717
            $visibilityClass = ' text-muted ';
3718
        }
3719
        $return = null;
3720
3721
        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...
3722
            $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3723
        } else {
3724
            $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3725
        }
3726
3727
        $return .= '<div class="item_data" style="margin-left:' . ($num  * 5 ) . 'px;margin-right:5px;">';
3728
3729 View Code Duplication
        if ($add_move_button) {
3730
            $return .= '<a class="moved" href="#">';
3731
            $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
3732
            $return .= '</a> ';
3733
        }
3734
        $return .= $link;
3735
        $return .= '</div></li>';
3736
3737
        return $return;
3738
    }
3739
3740
    /**
3741
     * @param int $folderId
3742
     * @param array $resource
3743
     * @param int $lp_id
3744
     * @return null|string
3745
     */
3746
    private static function parseFolder($folderId, $resource, $lp_id)
3747
    {
3748
        $title = isset($resource['title']) ? $resource['title'] : null;
3749
        $path = isset($resource['path']) ? $resource['path'] : null;
3750
3751
        if (empty($path)) {
3752
            $num = 0;
3753
        } else {
3754
            $num = substr_count($path, '/');
3755
        }
3756
3757
        // It's a folder.
3758
        //hide some folders
3759
        if (in_array($path,
3760
            array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
3761
            return null;
3762
        } elseif (preg_match('/_groupdocs/', $path)) {
3763
            return null;
3764
        } elseif (preg_match('/sf_user_/', $path)) {
3765
            return null;
3766
        } elseif (preg_match('/shared_folder_session_/', $path)) {
3767
            return null;
3768
        }
3769
3770
        //trad some titles
3771
        /*
3772
        if ($key == 'images') {
3773
            $key = get_lang('Images');
3774
        } elseif ($key == 'gallery') {
3775
            $key = get_lang('Gallery');
3776
        } elseif ($key == 'flash') {
3777
            $key = get_lang('Flash');
3778
        } elseif ($key == 'audio') {
3779
            $key = get_lang('Audio');
3780
        } elseif ($key == 'video') {
3781
            $key = get_lang('Video');
3782
        }*/
3783
3784
        $onclick = '';
3785
3786
        // if in LP, hidden folder are displayed in grey
3787
        $folder_class_hidden = "";
3788
        if ($lp_id) {
3789
            if (isset($resource['visible']) && $resource['visible'] == 0) {
3790
                $folder_class_hidden = "doc_folder_hidden"; // in base.css
3791
            }
3792
            $onclick = 'onclick="javascript: testResources(\'res_' . $resource['id'] . '\',\'img_' . $resource['id'] . '\')"';
3793
        }
3794
        $return = null;
3795
3796
        if (empty($path)) {
3797
            $return = '<ul class="lp_resource">';
3798
        }
3799
3800
        $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_' . $resource['id'] . '"  style="margin-left:' . ($num * 18) . 'px; ">';
3801
3802
        $image = Display::returnIconPath('nolines_plus.gif');
3803
        if (empty($path)) {
3804
            $image = Display::returnIconPath('nolines_minus.gif');
3805
        }
3806
        $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'] . '" '.$onclick.'>';
3807
        $return .= Display::return_icon('lp_folder.gif').'&nbsp;';
3808
        $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
3809
        $return .= '</li>';
3810
3811
        if (empty($path)) {
3812
            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...
3813
                $return .= '<div id="res_' . $resource['id'] . '" >';
3814
            } else {
3815
                $return .= '<div id="res_' . $resource['id'] . '" style="display: none;" >';
3816
            }
3817
        }
3818
3819
        return $return;
3820
    }
3821
3822
    /**
3823
     * Generate and return an HTML list of resources based on a given array.
3824
     * This list is used to show the course creator a list of available resources to choose from
3825
     * when creating a learning path.
3826
     * @param array $course_info
3827
     * @param int $session_id
3828
     * @param array $documents
3829
     * @param bool $lp_id
3830
     * @param string $target
3831
     * @param bool $add_move_button
3832
     * @param string $overwrite_url
3833
     * @param int $folderId
3834
     *
3835
     * @return string
3836
     */
3837
    public static function write_resources_tree(
3838
        $course_info,
3839
        $session_id,
3840
        $documents,
3841
        $lp_id = false,
3842
        $target = '',
3843
        $add_move_button = false,
3844
        $overwrite_url = null,
3845
        $folderId = false
3846
    ) {
3847
        $return = '';
3848
3849
        if (!empty($documents)) {
3850
            foreach ($documents as $key => $resource) {
3851
                if (isset($resource['id']) && is_int($resource['id'])) {
3852
                    $mainFolderResource = array(
3853
                        'id' => $resource['id'],
3854
                        'title' => $key,
3855
                    );
3856
3857
                    if ($folderId === false) {
3858
                        $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
3859
                    }
3860
3861
                    if (isset($resource['files'])) {
3862
                        $return .= self::write_resources_tree(
3863
                            $course_info,
3864
                            $session_id,
3865
                            $resource['files'],
3866
                            $lp_id,
3867
                            $target,
3868
                            $add_move_button,
3869
                            $overwrite_url
3870
                        );
3871
                    }
3872
                    $return .= '</div>';
3873
                    $return .= '</ul>';
3874
                } else {
3875
                    if ($resource['filetype'] == 'folder') {
3876
                        $return .= self::parseFolder($folderId, $resource, $lp_id);
0 ignored issues
show
Bug introduced by
It seems like $folderId defined by parameter $folderId on line 3845 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...
3877
                    } else {
3878
                        $return .= self::parseFile(
3879
                            $course_info,
3880
                            $session_id,
3881
                            $resource,
3882
                            $lp_id,
3883
                            $add_move_button,
3884
                            $target,
3885
                            $overwrite_url
3886
                        );
3887
                    }
3888
                }
3889
            }
3890
        }
3891
3892
        return $return;
3893
    }
3894
3895
    /**
3896
     * @param int $doc_id
3897
     * @param string $course_code
3898
     * @param int $session_id
3899
     * @param int $user_id
3900
     * @param int $groupId iid
3901
     * @return bool
3902
     */
3903
    public static function check_visibility_tree(
3904
        $doc_id,
3905
        $course_code,
3906
        $session_id,
3907
        $user_id,
3908
        $groupId = 0
3909
    ) {
3910
        $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
3911
        if ($session_id != 0 && !$document_data) {
3912
            $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
3913
        }
3914
3915
        if (!empty($document_data)) {
3916
            // If admin or course teacher, allow anyway
3917
            if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
3918
                return true;
3919
            }
3920
            $course_info = api_get_course_info($course_code);
3921
            if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
3922
                if (!empty($groupId)) {
3923
                    return true;
3924
                }
3925
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3926
                return $visible;
3927
            } else {
3928
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3929
3930
                if (!$visible) {
3931
                    return false;
3932
                } else {
3933
                    return self::check_visibility_tree(
3934
                        $document_data['parent_id'],
3935
                        $course_code,
3936
                        $session_id,
3937
                        $user_id,
3938
                        $groupId
3939
                    );
3940
                }
3941
            }
3942
        } else {
3943
            return false;
3944
        }
3945
    }
3946
3947
    /**
3948
     * Index a given document.
3949
     * @param   int     Document ID inside its corresponding course
3950
     * @param   string  Course code
3951
     * @param   int     Session ID (not used yet)
3952
     * @param   string  Language of document's content (defaults to course language)
3953
     * @param   array   Array of specific fields (['code'=>'value',...])
3954
     * @param   string  What to do if the file already exists (default or overwrite)
3955
     * @param   bool    When set to true, this runs the indexer without actually saving anything to any database
3956
     * @return  bool    Returns true on presumed success, false on failure
3957
     */
3958
    public static function index_document(
3959
        $docid,
3960
        $course_code,
3961
        $session_id = 0,
3962
        $lang = 'english',
3963
        $specific_fields_values = array(),
3964
        $if_exists = '',
3965
        $simulation = false
3966
    ) {
3967
        if (api_get_setting('search_enabled') !== 'true') {
3968
            return false;
3969
        }
3970
        if (empty($docid) or $docid != intval($docid)) {
3971
            return false;
3972
        }
3973
        if (empty($session_id)) {
3974
            $session_id = api_get_session_id();
3975
        }
3976
        $course_info = api_get_course_info($course_code);
3977
        $course_dir = $course_info['path'] . '/document';
3978
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
3979
        $base_work_dir = $sys_course_path . $course_dir;
3980
3981
        $course_id = $course_info['real_id'];
3982
        $table_document = Database::get_course_table(TABLE_DOCUMENT);
3983
3984
        $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
3985
        $result = Database::query($qry);
3986
        if (Database::num_rows($result) == 1) {
3987
            $row = Database::fetch_array($result);
3988
            $doc_path = api_get_path(SYS_COURSE_PATH) . $course_dir . $row['path'];
3989
            //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
3990
            // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
3991
            $doc_mime = mime_content_type($doc_path);
3992
            $allowed_mime_types = self::file_get_mime_type(true);
3993
3994
            // 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
3995
            if (empty($doc_mime)) {
3996
                $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
3997
                $extensions = preg_split("/[\/\\.]/", $doc_path);
3998
                $doc_ext = strtolower($extensions[count($extensions) - 1]);
3999
                if (in_array($doc_ext, $allowed_extensions)) {
4000
                    switch ($doc_ext) {
4001
                        case 'ppt':
4002
                        case 'pps':
4003
                            $doc_mime = 'application/vnd.ms-powerpoint';
4004
                            break;
4005
                        case 'xls':
4006
                            $doc_mime = 'application/vnd.ms-excel';
4007
                            break;
4008
                    }
4009
                }
4010
            }
4011
4012
            //@todo move this nightmare in a search controller or something like that!!! J.M
4013
4014
            if (in_array($doc_mime, $allowed_mime_types)) {
4015
                $file_title = $row['title'];
4016
                $file_content = self::get_text_content($doc_path, $doc_mime);
4017
                $course_code = Database::escape_string($course_code);
4018
4019
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
4020
                require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
4021
4022
                $ic_slide = new IndexableChunk();
4023
                $ic_slide->addValue('title', $file_title);
4024
                $ic_slide->addCourseId($course_code);
4025
                $ic_slide->addToolId(TOOL_DOCUMENT);
4026
                $xapian_data = array(
4027
                    SE_COURSE_ID => $course_code,
4028
                    SE_TOOL_ID => TOOL_DOCUMENT,
4029
                    SE_DATA => array('doc_id' => $docid),
4030
                    SE_USER => api_get_user_id(),
4031
                );
4032
4033
                $ic_slide->xapian_data = serialize($xapian_data);
4034
                $di = new ChamiloIndexer();
4035
                $return = $di->connectDb(null, null, $lang);
4036
4037
                require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
4038
                $specific_fields = get_specific_field_list();
4039
4040
                // process different depending on what to do if file exists
4041
                /**
4042
                 * @TODO Find a way to really verify if the file had been
4043
                 * overwriten. Now all work is done at
4044
                 * handle_uploaded_document() and it's difficult to verify it
4045
                 */
4046
                if (!empty($if_exists) && $if_exists == 'overwrite') {
4047
                    // Overwrite the file on search engine
4048
                    // Actually, it consists on a delete of terms from db,
4049
                    // insert new ones, create a new search engine document,
4050
                    // and remove the old one
4051
                    // Get search_did
4052
                    $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4053
                    $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
4054
                    $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
4055
4056
                    $res = Database::query($sql);
4057
4058
                    if (Database::num_rows($res) > 0) {
4059
                        $se_ref = Database::fetch_array($res);
4060
                        if (!$simulation) {
4061
                            $di->remove_document($se_ref['search_did']);
4062
                        }
4063
                        $all_specific_terms = '';
4064
                        foreach ($specific_fields as $specific_field) {
4065
                            if (!$simulation) {
4066
                                delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
4067
                            }
4068
                            // Update search engine
4069
                            if (isset($specific_fields_values[$specific_field['code']])) {
4070
                                $sterms = trim($specific_fields_values[$specific_field['code']]);
4071
                            } else { //if the specific field is not defined, force an empty one
4072
                                $sterms = '';
4073
                            }
4074
                            $all_specific_terms .= ' ' . $sterms;
4075
                            $sterms = explode(',', $sterms);
4076
                            foreach ($sterms as $sterm) {
4077
                                $sterm = trim($sterm);
4078
                                if (!empty($sterm)) {
4079
                                    $ic_slide->addTerm($sterm, $specific_field['code']);
4080
                                    // updated the last param here from $value to $sterm without being sure - see commit15464
4081
                                    if (!$simulation) {
4082
                                        add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
4083
                                    }
4084
                                }
4085
                            }
4086
                        }
4087
                        // Add terms also to content to make terms findable by probabilistic search
4088
                        $file_content = $all_specific_terms . ' ' . $file_content;
4089
4090
                        if (!$simulation) {
4091
                            $ic_slide->addValue('content', $file_content);
4092
                            $di->addChunk($ic_slide);
4093
                            // Index and return a new search engine document id
4094
                            $did = $di->index();
4095
4096
                            if ($did) {
4097
                                // update the search_did on db
4098
                                $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4099
                                $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
4100
                                $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
4101
                                Database::query($sql);
4102
                            }
4103
                        }
4104
                    }
4105
                } else {
4106
                    // Add all terms
4107
                    $all_specific_terms = '';
4108 View Code Duplication
                    foreach ($specific_fields as $specific_field) {
4109
                        if (isset($specific_fields_values[$specific_field['code']])) {
4110
                            $sterms = trim($specific_fields_values[$specific_field['code']]);
4111
                        } else { //if the specific field is not defined, force an empty one
4112
                            $sterms = '';
4113
                        }
4114
                        $all_specific_terms .= ' ' . $sterms;
4115
                        if (!empty($sterms)) {
4116
                            $sterms = explode(',', $sterms);
4117
                            foreach ($sterms as $sterm) {
4118
                                if (!$simulation) {
4119
                                    $ic_slide->addTerm(trim($sterm), $specific_field['code']);
4120
                                    add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
4121
                                }
4122
                            }
4123
                        }
4124
                    }
4125
                    // Add terms also to content to make terms findable by probabilistic search
4126
                    $file_content = $all_specific_terms . ' ' . $file_content;
4127
                    if (!$simulation) {
4128
                        $ic_slide->addValue('content', $file_content);
4129
                        $di->addChunk($ic_slide);
4130
                        // Index and return search engine document id
4131
                        $did = $di->index();
4132
                        if ($did) {
4133
                            // Save it to db
4134
                            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4135
                            $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
4136
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
4137
                            $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
4138
                            Database::query($sql);
4139
                        } else {
4140
                            return false;
4141
                        }
4142
                    }
4143
                }
4144
            } else {
4145
                return false;
4146
            }
4147
        }
4148
        return true;
4149
    }
4150
4151
    /**
4152
     * @return array
4153
     */
4154
    public static function get_web_odf_extension_list()
4155
    {
4156
        return array('ods', 'odt', 'odp');
4157
    }
4158
4159
    /**
4160
     * Set of extension allowed to use Jodconverter
4161
     * @param $mode 'from'
4162
     *              'to'
4163
     *              'all'
4164
     * @param $format   'text'
4165
     *                  'spreadsheet'
4166
     *                  'presentation'
4167
     *                  'drawing'
4168
     *                  'all'
4169
     * @return array
4170
     */
4171
    public static function getJodconverterExtensionList($mode, $format)
4172
    {
4173
        $extensionList = array();
4174
        $extensionListFromText = array(
4175
            'odt',
4176
            'sxw',
4177
            'rtf',
4178
            'doc',
4179
            'docx',
4180
            'wpd',
4181
            'txt',
4182
        );
4183
        $extensionListToText = array(
4184
            'pdf',
4185
            'odt',
4186
            'sxw',
4187
            'rtf',
4188
            'doc',
4189
            'docx',
4190
            'txt',
4191
        );
4192
        $extensionListFromSpreadsheet = array(
4193
            'ods',
4194
            'sxc',
4195
            'xls',
4196
            'xlsx',
4197
            'csv',
4198
            'tsv',
4199
        );
4200
        $extensionListToSpreadsheet = array(
4201
            'pdf',
4202
            'ods',
4203
            'sxc',
4204
            'xls',
4205
            'xlsx',
4206
            'csv',
4207
            'tsv',
4208
        );
4209
        $extensionListFromPresentation = array(
4210
            'odp',
4211
            'sxi',
4212
            'ppt',
4213
            'pptx',
4214
        );
4215
        $extensionListToPresentation = array(
4216
            'pdf',
4217
            'swf',
4218
            'odp',
4219
            'sxi',
4220
            'ppt',
4221
            'pptx',
4222
        );
4223
        $extensionListFromDrawing = array('odg');
4224
        $extensionListToDrawing = array('svg', 'swf');
4225
4226
        if ($mode === 'from') {
4227 View Code Duplication
            if ($format === 'text') {
4228
                $extensionList = array_merge($extensionList, $extensionListFromText);
4229
            } elseif ($format === 'spreadsheet') {
4230
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4231
            } elseif ($format === 'presentation') {
4232
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4233
            } elseif ($format === 'drawing') {
4234
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4235
            } elseif ($format === 'all') {
4236
                $extensionList = array_merge($extensionList, $extensionListFromText);
4237
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4238
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4239
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4240
            }
4241 View Code Duplication
        } elseif ($mode === 'to') {
4242
            if ($format === 'text') {
4243
                $extensionList = array_merge($extensionList, $extensionListToText);
4244
            } elseif ($format === 'spreadsheet') {
4245
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4246
            } elseif ($format === 'presentation') {
4247
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4248
            } elseif ($format === 'drawing') {
4249
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4250
            } elseif ($format === 'all') {
4251
                $extensionList = array_merge($extensionList, $extensionListToText);
4252
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4253
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4254
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4255
            }
4256
        } elseif ($mode === 'all') {
4257
            if ($format === 'text') {
4258
                $extensionList = array_merge($extensionList, $extensionListFromText);
4259
                $extensionList = array_merge($extensionList, $extensionListToText);
4260
            } elseif ($format === 'spreadsheet') {
4261
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4262
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4263
            } elseif ($format === 'presentation') {
4264
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4265
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4266
            } elseif ($format === 'drawing') {
4267
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4268
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4269
            } elseif ($format === 'all') {
4270
                $extensionList = array_merge($extensionList, $extensionListFromText);
4271
                $extensionList = array_merge($extensionList, $extensionListToText);
4272
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4273
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4274
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4275
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4276
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4277
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4278
            }
4279
        }
4280
        return $extensionList;
4281
    }
4282
4283
    /**
4284
     * Get Format type list by extension and mode
4285
     * @param string $mode Mode to search format type list
4286
     * @example 'from'
4287
     * @example 'to'
4288
     * @param string $extension file extension to check file type
4289
     * @return array
4290
     */
4291
    public static function getFormatTypeListConvertor($mode = 'from', $extension)
4292
    {
4293
        $formatTypesList = array();
4294
        $formatTypes = array('text', 'spreadsheet', 'presentation', 'drawing');
4295
        foreach ($formatTypes as $formatType) {
4296
            if (
4297
            in_array(
4298
                $extension,
4299
                self::getJodconverterExtensionList($mode, $formatType)
4300
            )
4301
            ) {
4302
                $formatTypesList[] = $formatType;
4303
            }
4304
        }
4305
        return $formatTypesList;
4306
    }
4307
4308
    /**
4309
     * @param string $path
4310
     * @param bool $is_certificate_mode
4311
     * @return bool
4312
     */
4313
    public static function is_folder_to_avoid($path, $is_certificate_mode = false)
4314
    {
4315
        $foldersToAvoid = array(
4316
            '/HotPotatoes_files',
4317
            '/certificates',
4318
        );
4319
        $systemFolder = api_get_course_setting('show_system_folders');
4320
4321
        if ($systemFolder == 1) {
4322
            $foldersToAvoid = array();
4323
        }
4324
4325
        if (basename($path) == 'css') {
4326
            return true;
4327
        }
4328
4329
        if ($is_certificate_mode == false) {
4330
            //Certificate results
4331
            if (strstr($path, 'certificates')) {
4332
                return true;
4333
            }
4334
        }
4335
4336
        // Admin setting for Hide/Show the folders of all users
4337 View Code Duplication
        if (api_get_setting('show_users_folders') == 'false') {
4338
            $foldersToAvoid[] = '/shared_folder';
4339
4340
            if (strstr($path, 'shared_folder_session_')) {
4341
                return true;
4342
            }
4343
        }
4344
4345
        // Admin setting for Hide/Show Default folders to all users
4346
        if (api_get_setting('show_default_folders') == 'false') {
4347
            $foldersToAvoid[] = '/images';
4348
            $foldersToAvoid[] = '/flash';
4349
            $foldersToAvoid[] = '/audio';
4350
            $foldersToAvoid[] = '/video';
4351
        }
4352
4353
        // Admin setting for Hide/Show chat history folder
4354
        if (api_get_setting('show_chat_folder') == 'false') {
4355
            $foldersToAvoid[] = '/chat_files';
4356
        }
4357
4358
        if (is_array($foldersToAvoid)) {
4359
4360
            return in_array($path, $foldersToAvoid);
4361
        } else {
4362
4363
            return false;
4364
        }
4365
    }
4366
4367
    /**
4368
     * @return array
4369
     */
4370 View Code Duplication
    public static function get_system_folders()
4371
    {
4372
        return array(
4373
            '/certificates',
4374
            '/HotPotatoes_files',
4375
            '/chat_files',
4376
            '/images',
4377
            '/flash',
4378
            '/audio',
4379
            '/video',
4380
            '/shared_folder',
4381
            '/learning_path'
4382
        );
4383
    }
4384
4385
    /**
4386
     * @return array
4387
     */
4388
    public static function getProtectedFolderFromStudent()
4389
    {
4390
        return array(
4391
            '/certificates',
4392
            '/HotPotatoes_files',
4393
            '/chat_files',
4394
            '/shared_folder',
4395
            '/learning_path'
4396
        );
4397
    }
4398
4399
    /**
4400
     * @param string $courseCode
4401
     * @return string 'visible' or 'invisible' string
4402
     */
4403
    public static function getDocumentDefaultVisibility($courseCode)
4404
    {
4405
        $settings = api_get_setting('tool_visible_by_default_at_creation');
4406
        $defaultVisibility = 'visible';
4407
4408
        if (isset($settings['documents'])) {
4409
            $portalDefaultVisibility =  'invisible';
4410
            if ($settings['documents'] == 'true') {
4411
                $portalDefaultVisibility = 'visible';
4412
            }
4413
4414
            $defaultVisibility = $portalDefaultVisibility;
4415
        }
4416
4417
        if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
4418
            $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
4419
            if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
4420
                $defaultVisibility = $courseVisibility;
4421
            }
4422
        }
4423
        return $defaultVisibility;
4424
    }
4425
4426
    /**
4427
     * @param array $courseInfo
4428
     * @param int $id doc id
4429
     * @param string $visibility visible/invisible
4430
     * @param int $userId
4431
     */
4432
    public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
4433
    {
4434
        $sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
4435
4436
        if (!empty($sessionList)) {
4437
            foreach ($sessionList as $session) {
4438
                $sessionId = $session['id'];
4439
                api_item_property_update(
4440
                    $courseInfo,
4441
                    TOOL_DOCUMENT,
4442
                    $id,
4443
                    $visibility,
4444
                    $userId,
4445
                    null,
4446
                    null,
4447
                    null,
4448
                    null,
4449
                    $sessionId
4450
                );
4451
            }
4452
        }
4453
    }
4454
4455
    /**
4456
     * @param string $file
4457
     * @return string
4458
     */
4459
    public static function readNanogongFile($file)
4460
    {
4461
        $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
4462
        $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
4463
        $html .= '<param name="SoundFileURL" value="'.$file.'" />';
4464
        $html .= '<param name="ShowSaveButton" value="false" />';
4465
        $html .= '<param name="ShowTime" value="true" />';
4466
        $html .= '<param name="ShowRecordButton" value="false" />';
4467
        $html .= '</applet>';
4468
4469
        return $html;
4470
    }
4471
4472
    /**
4473
     * @param string $filePath
4474
     * @param string $path
4475
     * @param array $courseInfo
4476
     * @param int $sessionId
4477
     * @param string $whatIfFileExists overwrite|rename
4478
     * @param int $userId
4479
     * @param int $groupId
4480
     * @param int $toUserId
4481
     * @param string $comment
4482
     * @return bool|path
4483
     */
4484
    public static function addFileToDocumentTool(
4485
        $filePath,
4486
        $path,
4487
        $courseInfo,
4488
        $sessionId,
4489
        $userId,
4490
        $whatIfFileExists = 'overwrite',
4491
        $groupId = null,
4492
        $toUserId = null,
4493
        $comment = null
4494
    ) {
4495
        if (!file_exists($filePath)) {
4496
            return false;
4497
        }
4498
4499
        $fileInfo = pathinfo($filePath);
4500
4501
        $file = array(
4502
            'name' => $fileInfo['basename'],
4503
            'tmp_name' => $filePath,
4504
            'size' => filesize($filePath),
4505
            'from_file' => true
4506
        );
4507
4508
        $course_dir = $courseInfo['path'].'/document';
4509
        $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
4510
4511
        $filePath = handle_uploaded_document(
4512
            $courseInfo,
4513
            $file,
4514
            $baseWorkDir,
4515
            $path,
4516
            $userId,
4517
            $groupId,
4518
            $toUserId,
4519
            false,
4520
            $whatIfFileExists,
4521
            false,
4522
            false,
4523
            $comment,
4524
            $sessionId
4525
        );
4526
4527
        if ($filePath) {
4528
            return DocumentManager::get_document_id(
4529
                $courseInfo,
4530
                $filePath,
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by handle_uploaded_document..., $comment, $sessionId) on line 4511 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...
4531
                $sessionId
4532
            );
4533
        }
4534
        return false;
4535
    }
4536
4537
    /**
4538
     * Converts wav to mp3 file.
4539
     * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
4540
     * @param string $wavFile
4541
     * @param bool $removeWavFileIfSuccess
4542
     * @return bool
4543
     */
4544
    public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
4545
    {
4546
        if (file_exists($wavFile)) {
4547
            try {
4548
                $ffmpeg = \FFMpeg\FFMpeg::create();
4549
                $video = $ffmpeg->open($wavFile);
4550
4551
                $mp3File = str_replace('wav', 'mp3', $wavFile);
4552
                $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
4553
                if ($result && $removeWavFileIfSuccess) {
4554
                    unlink($wavFile);
4555
                }
4556
4557
                if (file_exists($mp3File)) {
4558
                    return $mp3File;
4559
                }
4560
            } catch (Exception $e) {
4561
                error_log($e->getMessage());
4562
                error_log($e->getPrevious()->getMessage());
4563
            }
4564
        }
4565
        return false;
4566
    }
4567
4568
    /**
4569
     * @param string $documentData wav document information
4570
     * @param array $courseInfo
4571
     * @param int $sessionId
4572
     * @param int $userId user that adds the document
4573
     * @param string $whatIfFileExists
4574
     * @param bool $deleteWavFile
4575
     *
4576
     * @return bool
4577
     */
4578
    public static function addAndConvertWavToMp3(
4579
        $documentData,
4580
        $courseInfo,
4581
        $sessionId,
4582
        $userId,
4583
        $whatIfFileExists = 'overwrite',
4584
        $deleteWavFile = false
4585
    ) {
4586
        if (empty($documentData)) {
4587
            return false;
4588
        }
4589
4590
        if (isset($documentData['absolute_path']) &&
4591
            file_exists($documentData['absolute_path'])
4592
        ) {
4593
            $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
4594
            error_log($mp3FilePath);
4595
4596
            if (!empty($mp3FilePath) && file_exists($mp3FilePath)) {
4597
4598
                $documentId = self::addFileToDocumentTool(
4599
                    $mp3FilePath,
4600
                    dirname($documentData['path']),
4601
                    $courseInfo,
4602
                    $sessionId,
4603
                    $userId,
4604
                    $whatIfFileExists,
4605
                    null,
4606
                    null,
4607
                    $documentData['comment']
4608
                );
4609
4610 View Code Duplication
                if (!empty($documentId)) {
4611
4612
                    if ($deleteWavFile) {
4613
                        $coursePath = $courseInfo['directory'].'/document';
4614
                        $documentPath = api_get_path(SYS_COURSE_PATH).$coursePath;
4615
                        self::delete_document(
4616
                            $courseInfo,
4617
                            null,
4618
                            $documentPath,
4619
                            $sessionId,
4620
                            $documentData['id']
4621
                        );
4622
                    }
4623
4624
                    return $documentId;
4625
                }
4626
            }
4627
        }
4628
4629
        return false;
4630
    }
4631
4632
    /**
4633
     * Sets
4634
     * @param string $file ($document_data['path'])
4635
     * @param string $file_url_sys
4636
     * @return string
4637
     */
4638
    public static function generateAudioTempFile($file, $file_url_sys)
4639
    {
4640
        //make temp audio
4641
        $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
4642
        if (!file_exists($temp_folder)) {
4643
            @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
4644
        }
4645
4646
        //make htaccess with allow from all, and file index.html into temp/audio
4647
        $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
4648 View Code Duplication
        if (!file_exists($htaccess)) {
4649
            $htaccess_content="order deny,allow\r\nallow from all\r\nOptions -Indexes";
4650
            $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
4651
            if ($fp) {
4652
                fwrite($fp, $htaccess_content);
4653
                fclose($fp);
4654
            }
4655
        }
4656
4657
        //encript temp name file
4658
        $name_crip = sha1(uniqid());//encript
4659
        $findext= explode(".", $file);
4660
        $extension = $findext[count($findext)-1];
4661
        $file_crip = $name_crip.'.'.$extension;
4662
4663
        //copy file to temp/audio directory
4664
        $from_sys = $file_url_sys;
4665
        $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4666
4667
        if (file_exists($from_sys)) {
4668
            copy($from_sys, $to_sys);
4669
        }
4670
4671
        //get  file from tmp directory
4672
        $_SESSION['temp_audio_nanogong'] = $to_sys;
4673
4674
        return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4675
    }
4676
4677
    /**
4678
     * Erase temp nanogong audio.
4679
     */
4680
    public static function removeGeneratedAudioTempFile()
4681
    {
4682 View Code Duplication
        if (isset($_SESSION['temp_audio_nanogong'])
4683
            && !empty($_SESSION['temp_audio_nanogong'])
4684
            && is_file($_SESSION['temp_audio_nanogong'])) {
4685
4686
            unlink($_SESSION['temp_audio_nanogong']);
4687
            unset($_SESSION['temp_audio_nanogong']);
4688
        }
4689
    }
4690
4691
    /**
4692
     * Check if the past is used in this course.
4693
     * @param array $courseInfo
4694
     * @param string $path
4695
     *
4696
     * @return array
4697
     */
4698
    public static function getDocumentByPathInCourse($courseInfo, $path)
4699
    {
4700
        $table = Database::get_course_table(TABLE_DOCUMENT);
4701
        $path = Database::escape_string($path);
4702
        $courseId = $courseInfo['real_id'];
4703
        if (empty($courseId)) {
4704
            return false;
4705
        }
4706
        $sql = "SELECT * FROM $table WHERE c_id = $courseId AND path = '$path'";
4707
        $result = Database::query($sql);
4708
        return Database::store_result($result, 'ASSOC');
4709
    }
4710
4711
    /**
4712
     * @param array $_course
4713
     * @return int
4714
     */
4715
    public static function createDefaultAudioFolder($_course)
4716
    {
4717
        if (!isset($_course['path'])) {
4718
            return false;
4719
        }
4720
4721
        $audioId = null;
4722
        $path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
4723
        if (!is_dir($path.'audio')) {
4724
            mkdir($path.'audio', api_get_permissions_for_new_directories());
4725
            $audioId = add_document($_course, '/audio', 'folder', 0, 'Audio');
4726
            api_item_property_update(
4727
                $_course,
4728
                TOOL_DOCUMENT,
4729
                $audioId,
4730
                'FolderCreated',
4731
                api_get_user_id(),
4732
                null,
4733
                null,
4734
                null,
4735
                null,
4736
                api_get_session_id()
4737
            );
4738
        }
4739
4740
        return $audioId;
4741
    }
4742
4743
    /**
4744
     * Generate a default certificate for a courses
4745
     *
4746
     * @global string $css CSS directory
4747
     * @global string $img_dir image directory
4748
     * @global string $default_course_dir Course directory
4749
     * @global string $js JS directory
4750
     * @param array $courseData The course info
4751
     * @param bool $fromBaseCourse
4752
     * @param int $sessionId
4753
     */
4754
    public static function generateDefaultCertificate($courseData, $fromBaseCourse = false, $sessionId = 0)
4755
    {
4756
        global $css, $img_dir, $default_course_dir, $js;
4757
        $codePath = api_get_path(REL_CODE_PATH);
4758
        $dir = '/certificates';
4759
4760
        $title = get_lang('DefaultCertificate');
4761
        $comment = null;
4762
4763
        $fileName = api_replace_dangerous_char($title);
4764
        $filePath = api_get_path(SYS_COURSE_PATH) . "{$courseData['path']}/document{$dir}";
4765
        $fileFullPath = "{$filePath}/{$fileName}.html";
4766
        $fileSize = 0;
4767
        $fileType = 'file';
4768
        $templateContent = file_get_contents(api_get_path(SYS_CODE_PATH).'gradebook/certificate_template/template.html');
4769
4770
        $search = array('{CSS}', '{IMG_DIR}', '{REL_CODE_PATH}', '{COURSE_DIR}');
4771
        $replace = array($css.$js, $img_dir, $codePath, $default_course_dir);
4772
4773
        $fileContent = str_replace($search, $replace, $templateContent);
4774
4775
        $saveFilePath = "{$dir}/{$fileName}.html";
4776
4777
        if (!is_dir($filePath)) {
4778
            mkdir($filePath, api_get_permissions_for_new_directories());
4779
        }
4780
4781
        if ($fromBaseCourse) {
4782
            $defaultCertificateId = self::get_default_certificate_id($courseData['code'], 0);
4783
4784
            if (!empty($defaultCertificateId)) {
4785
                // We have a certificate from the course base
4786
                $documentData = DocumentManager::get_document_data_by_id(
4787
                    $defaultCertificateId,
4788
                    $courseData['code'],
4789
                    false,
4790
                    0
4791
                );
4792
4793
                if ($documentData) {
4794
                    $fileContent = file_get_contents($documentData['absolute_path']);
4795
                }
4796
            }
4797
        }
4798
4799
        $defaultCertificateFile = $fp = @fopen($fileFullPath, 'w');
4800
4801
        if ($defaultCertificateFile != false) {
4802
            @fputs($defaultCertificateFile, $fileContent);
4803
            fclose($defaultCertificateFile);
4804
            chmod($fileFullPath, api_get_permissions_for_new_files());
4805
4806
            $fileSize = filesize($fileFullPath);
4807
        }
4808
4809
        $documentId = add_document(
4810
            $courseData,
4811
            $saveFilePath,
4812
            $fileType,
4813
            $fileSize,
4814
            $title,
4815
            $comment,
4816
            0,//$readonly = 0,
4817
            true, //$save_visibility = true,
4818
            null, //$group_id = null,
4819
            $sessionId
4820
        );
4821
4822
        api_item_property_update(
4823
            $courseData,
4824
            TOOL_DOCUMENT,
4825
            $documentId,
4826
            'DocumentAdded',
4827
            api_get_user_id(),
4828
            null,
4829
            null,
4830
            null,
4831
            null,
4832
            $sessionId
4833
        );
4834
4835
        $defaultCertificateId = self::get_default_certificate_id(
4836
            $courseData['code'],
4837
            $sessionId
4838
        );
4839
4840
        if (!isset($defaultCertificateId)) {
4841
            self::attach_gradebook_certificate($courseData['code'], $documentId, $sessionId);
4842
        }
4843
    }
4844
4845
    /**
4846
     * Update the document name
4847
     * @param int $documentId The document id
4848
     * @param string $newName The new name
4849
     */
4850
    public static function renameDocument($documentId, $newName)
4851
    {
4852
        $documentId = intval($documentId);
4853
        $newName = Database::escape_string($newName);
4854
4855
        $docuentTable = Database::get_course_table(TABLE_DOCUMENT);
4856
4857
        $values = array(
4858
            'title' => $newName
4859
        );
4860
4861
        $whereConditions = array(
4862
            'id = ?' => $documentId
4863
        );
4864
4865
        Database::update($docuentTable, $values, $whereConditions);
4866
    }
4867
4868
    /**
4869
     * Get folder/file suffix
4870
     *
4871
     * @param array $courseInfo
4872
     * @param int $sessionId
4873
     * @param int $groupId
4874
     *
4875
     * @return string
4876
     */
4877
    public static function getDocumentSuffix($courseInfo, $sessionId, $groupId)
4878
    {
4879
        // If no session or group, then no suffix.
4880
        if (empty($sessionId) && empty($groupId)) {
4881
4882
            return '';
4883
        }
4884
4885
        return '__'.intval($sessionId).'__'.intval($groupId);
4886
    }
4887
4888
    /**
4889
     * Fix a document name adding session id and group id
4890
     * Turns picture.jpg -> picture__1__2.jpg
4891
     * Where 1 = session id and 2 group id
4892
     * Of session id and group id are empty then the function returns:
4893
     * picture.jpg ->  picture.jpg
4894
     *
4895
     * @param string $name folder or file name
4896
     * @param string $type 'folder' or 'file'
4897
     * @param array $courseInfo
4898
     * @param int $sessionId
4899
     * @param int $groupId
4900
     *
4901
     * @return string
4902
     */
4903
    public static function fixDocumentName($name, $type, $courseInfo, $sessionId, $groupId)
4904
    {
4905
        $suffix = self::getDocumentSuffix($courseInfo, $sessionId, $groupId);
4906
4907
        switch ($type) {
4908
            case 'folder':
4909
                $name = $name.$suffix;
4910
                break;
4911
            case 'file':
4912
                $name = self::addSuffixToFileName($name, $suffix);
4913
                break;
4914
        }
4915
4916
        return $name;
4917
    }
4918
4919
    /**
4920
     * Add a suffix to a file Example:
4921
     * /folder/picture.jpg => to /folder/picture_this.jpg
4922
     * where "_this" is the suffix
4923
     * @param string $name
4924
     * @param string $suffix
4925
     * @return string
4926
     */
4927
    public static function addSuffixToFileName($name, $suffix)
4928
    {
4929
        $extension = pathinfo($name, PATHINFO_EXTENSION);
4930
        $fileName = pathinfo($name, PATHINFO_FILENAME);
4931
        $dir = pathinfo($name, PATHINFO_DIRNAME);
4932
4933
        if ($dir == '.') {
4934
            $dir = null;
4935
        }
4936
4937
        if (!empty($dir) && $dir != '/') {
4938
            $dir = $dir.'/';
4939
        }
4940
4941
        $name = $dir.$fileName.$suffix.'.'.$extension;
4942
4943
        return $name;
4944
    }
4945
4946
    /**
4947
     * Check if folder exist in the course base or in the session course
4948
     * @param string $folder Example: /folder/folder2
4949
     * @param array $courseInfo
4950
     * @param int $sessionId
4951
     * @param int $groupId group.id
4952
     *
4953
     * @return bool
4954
     */
4955 View Code Duplication
    public static function folderExists(
4956
        $folder,
4957
        $courseInfo,
4958
        $sessionId,
4959
        $groupId
4960
    ) {
4961
        $courseId = $courseInfo['real_id'];
4962
4963
        if (empty($courseId)) {
4964
            return false;
4965
        }
4966
4967
        $sessionId = intval($sessionId);
4968
        $folderWithSuffix = self::fixDocumentName(
4969
            $folder,
4970
            'folder',
4971
            $courseInfo,
4972
            $sessionId,
4973
            $groupId
4974
        );
4975
4976
        $folder = Database::escape_string($folder);
4977
        $folderWithSuffix = Database::escape_string($folderWithSuffix);
4978
4979
        // Check if pathname already exists inside document table
4980
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
4981
        $sql = "SELECT id, path FROM $tbl_document
4982
                WHERE
4983
                    filetype = 'folder' AND
4984
                    c_id = $courseId AND
4985
                    (path = '$folder' OR path = '$folderWithSuffix') AND
4986
                    (session_id = 0 OR session_id = $sessionId)
4987
        ";
4988
4989
        $rs = Database::query($sql);
4990
        if (Database::num_rows($rs)) {
4991
            return true;
4992
        }
4993
4994
        return false;
4995
    }
4996
4997
    /**
4998
     * Check if file exist in the course base or in the session course
4999
     * @param string $fileName Example: /folder/picture.jpg
5000
     * @param array $courseInfo
5001
     * @param int $sessionId
5002
     * @param int $groupId
5003
     *
5004
     * @return bool
5005
     */
5006 View Code Duplication
    public static function documentExists(
5007
        $fileName,
5008
        $courseInfo,
5009
        $sessionId,
5010
        $groupId
5011
    ) {
5012
        $courseId = $courseInfo['real_id'];
5013
5014
        if (empty($courseId)) {
5015
            return false;
5016
        }
5017
5018
        $sessionId = intval($sessionId);
5019
        $fileNameEscape = Database::escape_string($fileName);
5020
5021
        $fileNameWithSuffix = self::fixDocumentName(
5022
            $fileName,
5023
            'file',
5024
            $courseInfo,
5025
            $sessionId,
5026
            $groupId
5027
        );
5028
5029
        $fileNameWithSuffix = Database::escape_string($fileNameWithSuffix);
5030
5031
        // Check if pathname already exists inside document table
5032
        $table = Database::get_course_table(TABLE_DOCUMENT);
5033
        $sql = "SELECT id, path FROM $table
5034
                WHERE
5035
                    filetype = 'file' AND
5036
                    c_id = $courseId AND
5037
                    (
5038
                        path = '".$fileNameEscape."' OR
5039
                        path = '$fileNameWithSuffix'
5040
                    ) AND
5041
                    (session_id = 0 OR session_id = $sessionId)
5042
        ";
5043
        $rs = Database::query($sql);
5044
        if (Database::num_rows($rs)) {
5045
            return true;
5046
        }
5047
5048
        return false;
5049
    }
5050
5051
    /**
5052
     * Undo the suffix applied to a file example:
5053
     * turns picture__1__1.jpg to picture.jpg
5054
     * @param string $name
5055
     * @param int $courseId
5056
     * @param int $sessionId
5057
     * @param int $groupId
5058
     *
5059
     * @return string
5060
     */
5061
    public static function undoFixDocumentName(
5062
        $name,
5063
        $courseId,
5064
        $sessionId,
5065
        $groupId
5066
    ) {
5067
        if (empty($sessionId) && empty($groupId)) {
5068
            return $name;
5069
        }
5070
5071
        $suffix = self::getDocumentSuffix(
5072
            array('real_id' => $courseId),
5073
            $sessionId,
5074
            $groupId
5075
        );
5076
5077
        $name = str_replace($suffix, '', $name);
5078
5079
        return $name;
5080
    }
5081
5082
    /**
5083
     * @param string $path
5084
     * @param string $name
5085
     * @param array $courseInfo
5086
     * @param int $sessionId
5087
     * @param int $groupId
5088
     *
5089
     * @return string
5090
     */
5091
    public static function getUniqueFileName($path, $name, $courseInfo, $sessionId, $groupId)
5092
    {
5093
        $counter = 1;
5094
        $filePath = $path.$name;
5095
        $uniqueName = $name;
5096
        while ($documentExists = self::documentExists(
5097
            $filePath,
5098
            $courseInfo,
5099
            $sessionId,
5100
            $groupId
5101
        )) {
5102
            $uniqueName = self::addSuffixToFileName($name, '_' . $counter);
5103
            $filePath = $path . $uniqueName;
5104
            $counter++;
5105
        }
5106
5107
        return $uniqueName;
5108
    }
5109
5110
    /**
5111
     * Builds the form that enables the user to
5112
     * select a directory to browse/upload in
5113
     *
5114
     * @param array 	An array containing the folders we want to be able to select
5115
     * @param string	The current folder (path inside of the "document" directory, including the prefix "/")
5116
     * @param string	Group directory, if empty, prevents documents to be uploaded (because group documents cannot be uploaded in root)
5117
     * @param	boolean	Whether to change the renderer (this will add a template <span> to the QuickForm object displaying the form)
5118
5119
     * @return string html form
5120
     */
5121
    public static function build_directory_selector(
5122
        $folders,
5123
        $document_id,
5124
        $group_dir = '',
5125
        $change_renderer = false,
5126
        & $form = null,
5127
        $selectName = 'id'
5128
    ) {
5129
        $doc_table = Database::get_course_table(TABLE_DOCUMENT);
5130
        $course_id = api_get_course_int_id();
5131
        $folder_titles = array();
5132
5133
        if (is_array($folders)) {
5134
            $escaped_folders = array();
5135
            foreach ($folders as $key => & $val) {
5136
                $escaped_folders[$key] = Database::escape_string($val);
5137
            }
5138
            $folder_sql = implode("','", $escaped_folders);
5139
5140
            $sql = "SELECT path, title 
5141
                    FROM $doc_table
5142
                    WHERE 
5143
                        filetype = 'folder' AND 
5144
                        c_id = $course_id AND 
5145
                        path IN ('" . $folder_sql . "')";
5146
            $res = Database::query($sql);
5147
            $folder_titles = array();
5148
            while ($obj = Database::fetch_object($res)) {
5149
                $folder_titles[$obj->path] = $obj->title;
5150
            }
5151
        }
5152
5153
        $attributes = [];
5154 View Code Duplication
        if (empty($form)) {
5155
            $form = new FormValidator('selector', 'GET', api_get_self().'?'.api_get_cidreq());
5156
            $attributes = array('onchange' => 'javascript: document.selector.submit();');
5157
        }
5158
        $form->addElement('hidden', 'cidReq', api_get_course_id());
5159
        $parent_select = $form->addSelect(
5160
            $selectName,
5161
            get_lang('CurrentDirectory'),
5162
            '',
5163
            $attributes
5164
        );
5165
5166
        if ($change_renderer) {
5167
            $renderer = $form->defaultRenderer();
5168
            $renderer->setElementTemplate('<span>{label} : {element}</span> ', 'curdirpath');
5169
        }
5170
5171
        // Group documents cannot be uploaded in the root
5172
        if (empty($group_dir)) {
5173
            $parent_select->addOption(get_lang('Documents'), '/');
5174
5175
            if (is_array($folders)) {
5176
                foreach ($folders as $folder_id => & $folder) {
5177
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5178
                    $path_parts = explode('/', $folder);
5179
                    $folder_titles[$folder] = cut($folder_titles[$folder], 80);
5180
                    $counter = count($path_parts) - 2;
5181 View Code Duplication
                    if ($counter > 0) {
5182
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', $counter) . ' &mdash; ' . $folder_titles[$folder];
5183
                    } else {
5184
                        $label = ' &mdash; ' . $folder_titles[$folder];
5185
                    }
5186
                    $parent_select->addOption($label, $folder_id);
5187
                    if ($selected != '') {
5188
                        $parent_select->setSelected($folder_id);
5189
                    }
5190
                }
5191
            }
5192
        } else {
5193
            if (!empty($folders)) {
5194
                foreach ($folders as $folder_id => & $folder) {
5195
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5196
                    $label = $folder_titles[$folder];
5197 View Code Duplication
                    if ($folder == $group_dir) {
5198
                        $label = get_lang('Documents');
5199
                    } else {
5200
                        $path_parts = explode('/', str_replace($group_dir, '', $folder));
5201
                        $label = cut($label, 80);
5202
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', count($path_parts) - 2) . ' &mdash; ' . $label;
5203
                    }
5204
                    $parent_select->addOption($label, $folder_id);
5205
                    if ($selected != '') {
5206
                        $parent_select->setSelected($folder_id);
5207
                    }
5208
                }
5209
            }
5210
        }
5211
5212
        $html = $form->toHtml();
5213
5214
        return $html;
5215
    }
5216
5217
    /**
5218
     * Create a html hyperlink depending on if it's a folder or a file
5219
     *
5220
     * @param array $document_data
5221
     * @param array $course_info
5222
     * @param int $show_as_icon - if it is true, only a clickable icon will be shown
5223
     * @param int $visibility (1/0)
5224
     * @param int $counter
5225
     * @param int $size
5226
     * @param bool $isAllowedToEdit
5227
     *
5228
     * @return string url
5229
     */
5230
    public static function create_document_link(
5231
        $document_data,
5232
        $course_info,
5233
        $show_as_icon = false,
5234
        $counter = null,
5235
        $visibility,
5236
        $size = 0,
5237
        $isAllowedToEdit = false
5238
    ) {
5239
        global $dbl_click_id;
5240
5241
        $current_session_id = api_get_session_id();
5242
        $courseParams = api_get_cidreq();
5243
        $www = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/document';
5244
        $webODFList = DocumentManager::get_web_odf_extension_list();
5245
5246
        // Get the title or the basename depending on what we're using
5247
        if ($document_data['title'] != '') {
5248
            $title = $document_data['title'];
5249
        } else {
5250
            $title = basename($document_data['path']);
5251
        }
5252
5253
        $filetype = $document_data['filetype'];
5254
        $path = $document_data['path'];
5255
        $url_path = urlencode($document_data['path']);
5256
5257
        // Add class="invisible" on invisible files
5258
        $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...
5259
        $forcedownload_link = null;
5260
        $forcedownload_icon = null;
5261
        $prevent_multiple_click = null;
5262
5263
        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...
5264
            // Build download link (icon)
5265
            $forcedownload_link = ($filetype == 'folder') ? api_get_self() . '?' . $courseParams . '&action=downloadfolder&id=' . $document_data['id'] : api_get_self() . '?' . $courseParams . '&amp;action=download&amp;id=' . $document_data['id'];
5266
            // Folder download or file download?
5267
            $forcedownload_icon = ($filetype == 'folder') ? 'save_pack.png' : 'save.png';
5268
            // Prevent multiple clicks on zipped folder download
5269
            $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; }\"" : '';
5270
        }
5271
5272
        $target = '_self';
5273
        $is_browser_viewable_file = false;
5274
5275
        if ($filetype == 'file') {
5276
            // Check the extension
5277
            $ext = explode('.', $path);
5278
            $ext = strtolower($ext[sizeof($ext) - 1]);
5279
5280
            // HTML-files an some other types are shown in a frameset by default.
5281
            $is_browser_viewable_file = self::is_browser_viewable($ext);
5282
5283
            if ($is_browser_viewable_file) {
5284
                if ($ext == 'pdf' || in_array($ext, $webODFList)) {
5285
                    $url = api_get_self() . '?' . $courseParams . '&amp;action=download&amp;id=' . $document_data['id'];
5286
                } else {
5287
                    $url = 'showinframes.php?' . $courseParams . '&id=' . $document_data['id'];
5288
                }
5289
            } else {
5290
                // url-encode for problematic characters (we may not call them dangerous characters...)
5291
                $path = str_replace('%2F', '/', $url_path) . '?' . $courseParams;
5292
                $url = $www . $path;
5293
            }
5294
        } else {
5295
            $url = api_get_self() . '?' . $courseParams . '&id=' . $document_data['id'];
5296
        }
5297
5298
        // The little download icon
5299
        $tooltip_title = $title;
5300
5301
        $tooltip_title_alt = $tooltip_title;
5302
        if ($path == '/shared_folder') {
5303
            $tooltip_title_alt = get_lang('UserFolders');
5304
        } elseif (strstr($path, 'shared_folder_session_')) {
5305
            $tooltip_title_alt = get_lang('UserFolders') . ' (' . api_get_session_name(api_get_session_id()) . ')';
5306
        } elseif (strstr($tooltip_title, 'sf_user_')) {
5307
            $userinfo = api_get_user_info(substr($tooltip_title, 8));
5308
            $tooltip_title_alt = get_lang('UserFolder') . ' ' . $userinfo['complete_name'];
5309
        } elseif ($path == '/chat_files') {
5310
            $tooltip_title_alt = get_lang('ChatFiles');
5311
        } elseif ($path == '/learning_path') {
5312
            $tooltip_title_alt = get_lang('LearningPaths');
5313
        } elseif ($path == '/video') {
5314
            $tooltip_title_alt = get_lang('Video');
5315
        } elseif ($path == '/audio') {
5316
            $tooltip_title_alt = get_lang('Audio');
5317
        } elseif ($path == '/flash') {
5318
            $tooltip_title_alt = get_lang('Flash');
5319
        } elseif ($path == '/images') {
5320
            $tooltip_title_alt = get_lang('Images');
5321
        } elseif ($path == '/images/gallery') {
5322
            $tooltip_title_alt = get_lang('DefaultCourseImages');
5323
        }
5324
5325
        $copy_to_myfiles = $open_in_new_window_link = null;
5326
        $curdirpath = isset($_GET['curdirpath']) ? Security::remove_XSS($_GET['curdirpath']) : null;
5327
        $send_to = null;
5328
        $checkExtension = $path;
5329
5330
        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...
5331
            if ($filetype == 'folder') {
5332
                if ($isAllowedToEdit ||
5333
                    api_is_platform_admin() ||
5334
                    api_get_setting('students_download_folders') == 'true'
5335
                ) {
5336
                    //filter: when I am into a shared folder, I can only show "my shared folder" for donwload
5337
                    if (DocumentManager::is_shared_folder($curdirpath, $current_session_id)) {
5338
                        if (preg_match('/shared_folder\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5339
                            preg_match('/shared_folder_session_' . $current_session_id . '\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5340
                            $isAllowedToEdit || api_is_platform_admin()
5341
                        ) {
5342
                            $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5343
                                Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5344
                        }
5345
                    } elseif (!preg_match('/shared_folder/', urldecode($forcedownload_link)) ||
5346
                        $isAllowedToEdit ||
5347
                        api_is_platform_admin()
5348
                    ) {
5349
                        $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5350
                            Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5351
                    }
5352
                }
5353 View Code Duplication
            } else {
5354
                $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . ' download="' . $document_data['basename'] . '">' .
5355
                    Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5356
            }
5357
5358
            // Copy files to user's myfiles
5359
            if (api_get_setting('allow_my_files') === 'true' &&
5360
                api_get_setting('users_copy_files') === 'true'
5361
            ) {
5362
                $copy_myfiles_link = ($filetype == 'file') ? api_get_self() . '?' . $courseParams . '&action=copytomyfiles&id=' . $document_data['id'] : api_get_self() . '?' . $courseParams;
5363 View Code Duplication
                if ($filetype == 'file') {
5364
                    $copy_to_myfiles = '<a href="' . $copy_myfiles_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5365
                        Display::return_icon('briefcase.png', get_lang('CopyToMyFiles'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5366
5367
                    if (api_get_setting('allow_my_files') === 'false') {
5368
                        $copy_to_myfiles = '';
5369
                    }
5370
                }
5371
            }
5372
5373
            $pdf_icon = '';
5374
            $extension = pathinfo($path, PATHINFO_EXTENSION);
5375
            if (!$isAllowedToEdit &&
5376
                api_get_setting('students_export2pdf') == 'true' &&
5377
                $filetype == 'file' &&
5378
                in_array($extension, array('html', 'htm'))
5379
            ) {
5380
                $pdf_icon = ' <a style="float:right".' . $prevent_multiple_click . ' href="' . api_get_self() . '?' . $courseParams . '&action=export_to_pdf&id=' . $document_data['id'] . '">' .
5381
                    Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a> ';
5382
            }
5383
5384
            if ($is_browser_viewable_file) {
5385
                $open_in_new_window_link = '<a href="' . $www . str_replace('%2F', '/', $url_path) . '?' . $courseParams . '" style="float:right"' . $prevent_multiple_click . ' target="_blank">' .
5386
                    Display::return_icon('open_in_new_window.png', get_lang('OpenInANewWindow'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5387
            }
5388
5389
            if ($filetype == 'file') {
5390
                // Sound preview with jplayer
5391
                if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5392
                    (preg_match('/wav$/i', urldecode($checkExtension))) ||
5393
                    preg_match('/ogg$/i', urldecode($checkExtension))
5394
                ) {
5395
                    return '<span style="float:left" ' . $visibility_class . '>' .
5396
                    $title .
5397
                    '</span>' . $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5398
                } elseif (
5399
5400
                    // Show preview
5401
                    preg_match('/swf$/i', urldecode($checkExtension)) ||
5402
                    preg_match('/png$/i', urldecode($checkExtension)) ||
5403
                    preg_match('/gif$/i', urldecode($checkExtension)) ||
5404
                    preg_match('/jpg$/i', urldecode($checkExtension)) ||
5405
                    preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5406
                    preg_match('/bmp$/i', urldecode($checkExtension)) ||
5407
                    preg_match('/svg$/i', urldecode($checkExtension))
5408
                ) {
5409
                    // Simpler version of showinframesmin.php with no headers
5410
                    $url = 'show_content.php?' . $courseParams . '&id=' . $document_data['id'];
5411
                    $class = 'ajax';
5412
                    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...
5413
                        $class = "ajax text-muted";
5414
                    }
5415
                    return Display::url(
5416
                        $title,
5417
                        $url,
5418
                        [
5419
                            'class' => $class,
5420
                            'title' => $tooltip_title_alt,
5421
                            'data-title' => $title,
5422
                            'style' => 'float:left;'
5423
                        ]
5424
                    )
5425
                    . $force_download_html . $send_to . $copy_to_myfiles
5426
                    . $open_in_new_window_link . $pdf_icon;
5427
                } else {
5428
                    // For a "PDF Download" of the file.
5429
                    $pdfPreview = null;
5430
                    if ($ext != 'pdf' && !in_array($ext, $webODFList)) {
5431
                        $url = 'showinframes.php?' . $courseParams . '&id=' . $document_data['id'];
5432 View Code Duplication
                    } else {
5433
                        $pdfPreview = Display::url(
5434
                            Display::return_icon('preview.gif', get_lang('Preview')),
5435
                            api_get_path(WEB_CODE_PATH).'document/showinframes.php?' . $courseParams . '&id=' . $document_data['id'],
5436
                            array('style' => 'float:right')
5437
                        );
5438
                    }
5439
                    // No plugin just the old and good showinframes.php page
5440
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" style="float:left" ' . $visibility_class . ' >' . $title . '</a>' .
5441
                    $pdfPreview.$force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5442
                }
5443
            } else {
5444
                return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' . $title . '</a>' .
5445
                $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5446
            }
5447
            // end copy files to users myfiles
5448
        } else {
5449
            // Icon column
5450
            if (preg_match('/shared_folder/', urldecode($checkExtension)) &&
5451
                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...
5452
                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...
5453
            ) {
5454
                if ($filetype == 'file') {
5455
                    //Sound preview with jplayer
5456
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5457
                        (preg_match('/wav$/i', urldecode($checkExtension))) ||
5458
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5459
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5460
5461
                        return $sound_preview;
5462
                    } elseif (
5463
                        // Show preview
5464
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5465
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5466
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5467
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5468
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5469
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5470
                        preg_match('/svg$/i', urldecode($checkExtension))
5471
                    ) {
5472
                        $url = 'showinframes.php?' . $courseParams . '&id=' . $document_data['id'];
5473
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5474
                        DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) .
5475
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5476
                    } else {
5477
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5478
                        DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) .
5479
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5480
                    }
5481 View Code Duplication
                } else {
5482
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5483
                    DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) .
5484
                    Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5485
                }
5486
            } else {
5487
                if ($filetype == 'file') {
5488
                    // Sound preview with jplayer
5489
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5490
                        (preg_match('/wav$/i', urldecode($checkExtension))) ||
5491
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5492
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5493
5494
                        return $sound_preview;
5495
                    } elseif (
5496
                        //Show preview
5497
                        preg_match('/html$/i', urldecode($checkExtension)) ||
5498
                        preg_match('/htm$/i', urldecode($checkExtension)) ||
5499
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5500
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5501
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5502
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5503
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5504
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5505
                        preg_match('/svg$/i', urldecode($checkExtension))
5506
                    ) {
5507
                        $url = 'showinframes.php?' . $courseParams . '&id=' . $document_data['id']; //without preview
5508
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5509
                        DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) . '</a>';
5510 View Code Duplication
                    } else {
5511
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5512
                        DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) . '</a>';
5513
                    }
5514 View Code Duplication
                } else {
5515
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5516
                    DocumentManager::build_document_icon_tag($filetype, $path, $isAllowedToEdit) . '</a>';
5517
                }
5518
            }
5519
        }
5520
    }
5521
5522
    /**
5523
     * Builds an img html tag for the file type
5524
     *
5525
     * @param string $type (file/folder)
5526
     * @param string $path
5527
     * @param bool $isAllowedToEdit
5528
     * @return string img html tag
5529
     */
5530
    public static function build_document_icon_tag($type, $path, $isAllowedToEdit = null)
5531
    {
5532
        $basename = basename($path);
5533
        $current_session_id = api_get_session_id();
5534
        if (is_null($isAllowedToEdit)) {
5535
            $isAllowedToEdit = api_is_allowed_to_edit(null, true);
5536
        }
5537
        $user_image = false;
5538
        if ($type == 'file') {
5539
            $icon = choose_image($basename);
5540
            $basename = substr(strrchr($basename, '.'), 1);
5541
        } else {
5542
            if ($path == '/shared_folder') {
5543
                $icon = 'folder_users.png';
5544
                if ($isAllowedToEdit) {
5545
                    $basename = get_lang('HelpUsersFolder');
5546
                } else {
5547
                    $basename = get_lang('UserFolders');
5548
                }
5549
            } elseif (strstr($basename, 'sf_user_')) {
5550
                $userInfo = api_get_user_info(substr($basename, 8));
5551
                $icon = $userInfo['avatar_small'];
5552
                $basename = get_lang('UserFolder') . ' ' . $userInfo['complete_name'];
5553
                $user_image = true;
5554
            } elseif (strstr($path, 'shared_folder_session_')) {
5555
                $sessionName = api_get_session_name($current_session_id);
5556
                if ($isAllowedToEdit) {
5557
                    $basename = '***(' . $sessionName . ')*** ' . get_lang('HelpUsersFolder');
5558
                } else {
5559
                    $basename = get_lang('UserFolders') . ' (' . $sessionName . ')';
5560
                }
5561
                $icon = 'folder_users.png';
5562
            } else {
5563
                $icon = 'folder_document.gif';
5564
5565
                if ($path == '/audio') {
5566
                    $icon = 'folder_audio.gif';
5567
                    if ($isAllowedToEdit) {
5568
                        $basename = get_lang('HelpDefaultDirDocuments');
5569
                    } else {
5570
                        $basename = get_lang('Audio');
5571
                    }
5572
                } elseif ($path == '/flash') {
5573
                    $icon = 'folder_flash.gif';
5574
                    if ($isAllowedToEdit) {
5575
                        $basename = get_lang('HelpDefaultDirDocuments');
5576
                    } else {
5577
                        $basename = get_lang('Flash');
5578
                    }
5579
                } elseif ($path == '/images') {
5580
                    $icon = 'folder_images.gif';
5581
                    if ($isAllowedToEdit) {
5582
                        $basename = get_lang('HelpDefaultDirDocuments');
5583
                    } else {
5584
                        $basename = get_lang('Images');
5585
                    }
5586
                } elseif ($path == '/video') {
5587
                    $icon = 'folder_video.gif';
5588
                    if ($isAllowedToEdit) {
5589
                        $basename = get_lang('HelpDefaultDirDocuments');
5590
                    } else {
5591
                        $basename = get_lang('Video');
5592
                    }
5593
                } elseif ($path == '/images/gallery') {
5594
                    $icon = 'folder_gallery.gif';
5595
                    if ($isAllowedToEdit) {
5596
                        $basename = get_lang('HelpDefaultDirDocuments');
5597
                    } else {
5598
                        $basename = get_lang('Gallery');
5599
                    }
5600
                } elseif ($path == '/chat_files') {
5601
                    $icon = 'folder_chat.png';
5602
                    if ($isAllowedToEdit) {
5603
                        $basename = get_lang('HelpFolderChat');
5604
                    } else {
5605
                        $basename = get_lang('ChatFiles');
5606
                    }
5607
                } elseif ($path == '/learning_path') {
5608
                    $icon = 'folder_learningpath.gif';
5609
                    if ($isAllowedToEdit) {
5610
                        $basename = get_lang('HelpFolderLearningPaths');
5611
                    } else {
5612
                        $basename = get_lang('LearningPaths');
5613
                    }
5614
                }
5615
            }
5616
        }
5617
5618
        if ($user_image) {
5619
            return Display::img($icon, $basename, array(), false);
5620
        }
5621
5622
        return Display::return_icon($icon, $basename, array(), ICON_SIZE_MEDIUM);
5623
    }
5624
5625
    /**
5626
     * Creates the row of edit icons for a file/folder
5627
     *
5628
     * @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...
5629
     * @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...
5630
     * @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...
5631
     * @param int $visibility (1/0)
5632
     * @param int $id dbase id of the document
5633
     * @return string html img tags with hyperlinks
5634
     */
5635
    public static function build_edit_icons($document_data, $id, $is_template, $is_read_only = 0, $visibility)
5636
    {
5637
        $sessionId = api_get_session_id();
5638
        $courseParams = api_get_cidreq();
5639
        $web_odf_extension_list = DocumentManager::get_web_odf_extension_list();
5640
        $document_id = $document_data['id'];
5641
        $type = $document_data['filetype'];
5642
        $is_read_only = $document_data['readonly'];
5643
        $path = $document_data['path'];
5644
5645
        $parent_id = DocumentManager::get_document_id(
5646
            api_get_course_info(),
5647
            dirname($path),
5648
            0
5649
        );
5650
5651
        if (empty($parent_id) && !empty($sessionId)) {
5652
            $parent_id = DocumentManager::get_document_id(
5653
                api_get_course_info(),
5654
                dirname($path),
5655
                $sessionId
5656
            );
5657
        }
5658
5659
        $curdirpath = dirname($document_data['path']);
5660
        $is_certificate_mode = DocumentManager::is_certificate_mode($path);
5661
        $curdirpath = urlencode($curdirpath);
5662
        $extension = pathinfo($path, PATHINFO_EXTENSION);
5663
        //@todo Implement remote support for converter
5664
        $usePpt2lp = (api_get_setting('service_ppt2lp', 'active') == 'true' && api_get_setting('service_ppt2lp', 'host') == 'localhost');
5665
        $formatTypeList = DocumentManager::getFormatTypeListConvertor('from', $extension);
5666
        $formatType = current($formatTypeList);
5667
5668
        // Build URL-parameters for table-sorting
5669
        $sort_params = array();
5670
        if (isset($_GET['column'])) {
5671
            $sort_params[] = 'column=' . Security::remove_XSS($_GET['column']);
5672
        }
5673
        if (isset($_GET['page_nr'])) {
5674
            $sort_params[] = 'page_nr=' . Security::remove_XSS($_GET['page_nr']);
5675
        }
5676
        if (isset($_GET['per_page'])) {
5677
            $sort_params[] = 'per_page=' . Security::remove_XSS($_GET['per_page']);
5678
        }
5679
        if (isset($_GET['direction'])) {
5680
            $sort_params[] = 'direction=' . Security::remove_XSS($_GET['direction']);
5681
        }
5682
        $sort_params = implode('&amp;', $sort_params);
5683
        $visibility_icon = ($visibility == 0) ? 'invisible' : 'visible';
5684
        $visibility_command = ($visibility == 0) ? 'set_visible' : 'set_invisible';
5685
5686
        $modify_icons = '';
5687
5688
        // If document is read only *or* we're in a session and the document
5689
        // is from a non-session context, hide the edition capabilities
5690
        if ($is_read_only /* or ($session_id!=api_get_session_id()) */) {
5691
            if (api_is_course_admin() || api_is_platform_admin()) {
5692 View Code Duplication
                if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5693
                    $modify_icons = '<a href="edit_draw.php?' . $courseParams . '&id=' . $document_id . '">' .
5694
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5695
                } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5696
                    $modify_icons = '<a href="edit_odf.php?' . $courseParams . '&id=' . $document_id . '">' .
5697
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5698
                } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5699
                    $modify_icons = '<a href="edit_paint.php?' . $courseParams . '&id=' . $document_id . '">' .
5700
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5701
                } else {
5702
                    $modify_icons = '<a href="edit_document.php?' . $courseParams . '&id=' . $document_id. '">' .
5703
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5704
                }
5705
            } else {
5706
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5707
            }
5708
            $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL);
5709
            if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5710
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), '', ICON_SIZE_SMALL);
5711
            }
5712
            $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('Delete'), array(), ICON_SIZE_SMALL);
5713
        } else {
5714
            //Edit button
5715
            if (in_array($path, DocumentManager::get_system_folders())) {
5716
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5717
            } elseif ($is_certificate_mode ) {
5718
                // gradebook category doesn't seem to be taken into account
5719
                $modify_icons = '<a href="edit_document.php?' . $courseParams . '&amp;id=' . $document_id . '&curdirpath=/certificates">' . Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5720
            } else {
5721
                if ($sessionId) {
5722
                    if ($document_data['session_id'] == $sessionId) {
5723 View Code Duplication
                        if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5724
                            $modify_icons = '<a href="edit_draw.php?' . $courseParams . '&amp;id=' . $document_id  . '">' .
5725
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5726
                        } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5727
                            $modify_icons = '<a href="edit_odf.php?' . $courseParams . '&id=' . $document_id  . '">' .
5728
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5729
                        } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5730
                            $modify_icons = '<a href="edit_paint.php?' . $courseParams . '&id=' . $document_id  . '">' .
5731
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5732
                        } else {
5733
                            $modify_icons = '<a href="edit_document.php?' . $courseParams . '&amp;id=' . $document_id  . '">' .
5734
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5735
                        }
5736
                    } else {
5737
                        $modify_icons .= '&nbsp;' . Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>';
5738
                    }
5739 View Code Duplication
                } else {
5740
                    if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5741
                        $modify_icons = '<a href="edit_draw.php?' . $courseParams . '&amp;id=' . $document_id  . '">' .
5742
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5743
                    } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5744
                        $modify_icons = '<a href="edit_odf.php?' . $courseParams . '&id=' . $document_id  . '">' .
5745
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5746
                    } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5747
                        $modify_icons = '<a href="edit_paint.php?' . $courseParams . '&amp;id=' . $document_id . '">' .
5748
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5749
                    } else {
5750
                        $modify_icons = '<a href="edit_document.php?' . $courseParams . '&amp;id=' . $document_id  . '">' .
5751
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5752
                    }
5753
                }
5754
            }
5755
5756
            // Move button.
5757
            if ($is_certificate_mode || in_array($path, DocumentManager::get_system_folders())) {
5758
                $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5759
            } else {
5760
                if ($sessionId) {
5761 View Code Duplication
                    if ($document_data['session_id'] == $sessionId) {
5762
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5763
                            Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5764
                    } else {
5765
                        $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5766
                    }
5767
                } else {
5768
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5769
                        Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5770
                }
5771
            }
5772
5773
            //Visibility button
5774
            if ($is_certificate_mode) {
5775
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), array(), ICON_SIZE_SMALL) . '</a>';
5776
            } else {
5777
                if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5778
                    if ($visibility_icon == 'invisible') {
5779
                        $tip_visibility = get_lang('Show');
5780
                    } else {
5781
                        $tip_visibility = get_lang('Hide');
5782
                    }
5783
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;id=' . $parent_id . '&amp;' . $visibility_command . '=' . $id . '&amp;' . $sort_params . '">' .
5784
                        Display::return_icon($visibility_icon . '.png', $tip_visibility, '', ICON_SIZE_SMALL) . '</a>';
5785
                }
5786
            }
5787
5788
            // Delete button
5789
            if (in_array($path, DocumentManager::get_system_folders())) {
5790
                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5791
            } else {
5792
                $titleToShow = addslashes(basename($document_data['title']));
5793
5794
                if (isset($_GET['curdirpath']) &&
5795
                    $_GET['curdirpath'] == '/certificates' &&
5796
                    DocumentManager::get_default_certificate_id(api_get_course_id()) == $id
5797
                ) {
5798
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;' . $sort_params . 'delete_certificate_id=' . $id . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5799
                        Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5800
                } else {
5801
                    if ($is_certificate_mode) {
5802
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid=' . $document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5803
                            Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5804
                    } else {
5805
                        if ($sessionId) {
5806
                            if ($document_data['session_id'] == $sessionId) {
5807
                                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">'.
5808
                                    Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5809
                            } else {
5810
                                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5811
                            }
5812
                        } else {
5813
                            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow. '\');">' .
5814
                                Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5815
                        }
5816
                    }
5817
                }
5818
            }
5819
5820
            // Add action to covert to PDF, will create a new document whit same filename but .pdf extension
5821
            // @TODO: add prompt to select a format target
5822
            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...
5823
                // nothing to do
5824
            } else {
5825
                if ($usePpt2lp && $formatType) {
5826
                    $modify_icons .= '&nbsp;<a class="convertAction" href="#" ' .
5827
                        'data-documentId = ' . $document_id .
5828
                        ' data-formatType = ' . $formatType . '>' .
5829
                        Display::return_icon(
5830
                            'convert.png',
5831
                            get_lang('Convert'),
5832
                            array(),
5833
                            ICON_SIZE_SMALL
5834
                        ) . '</a>';
5835
                }
5836
            }
5837
        }
5838
5839
        if ($type == 'file' && ($extension == 'html' || $extension == 'htm')) {
5840
            if ($is_template == 0) {
5841
                if ((isset($_GET['curdirpath']) && $_GET['curdirpath'] != '/certificates') || !isset($_GET['curdirpath'])) {
5842
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&amp;add_as_template=' . $id .  '&amp;' . $sort_params . '">' .
5843
                        Display::return_icon('wizard.png', get_lang('AddAsTemplate'), array(), ICON_SIZE_SMALL) . '</a>';
5844
                }
5845
                if (isset($_GET['curdirpath']) && $_GET['curdirpath'] == '/certificates') {//allow attach certificate to course
5846
                    $visibility_icon_certificate = 'nocertificate';
5847
                    if (DocumentManager::get_default_certificate_id(api_get_course_id()) == $id) {
5848
                        $visibility_icon_certificate = 'certificate';
5849
                        $certificate = get_lang('DefaultCertificate');
5850
                        $preview = get_lang('PreviewCertificate');
5851
                        $is_preview = true;
5852
                    } else {
5853
                        $is_preview = false;
5854
                        $certificate = get_lang('NoDefaultCertificate');
5855
                    }
5856
                    if (isset($_GET['selectcat'])) {
5857
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&amp;selectcat=' . intval($_GET['selectcat']) . '&amp;set_certificate=' . $id . '&amp;' . $sort_params . '">';
5858
                        $modify_icons .= Display::return_icon($visibility_icon_certificate.'.png', $certificate);
5859
                        $modify_icons .= '</a>';
5860 View Code Duplication
                        if ($is_preview) {
5861
                            $modify_icons .= '&nbsp;<a target="_blank"  href="' . api_get_self() . '?' . $courseParams . '&amp;curdirpath=' . $curdirpath . '&amp;set_preview=' . $id . '&amp;' . $sort_params . '" >' .
5862
                                Display::return_icon('preview_view.png', $preview, '', ICON_SIZE_SMALL) . '</a>';
5863
                        }
5864
                    }
5865
                }
5866 View Code Duplication
            } else {
5867
                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&curdirpath=' . $curdirpath . '&amp;remove_as_template=' . $id. '&amp;' . $sort_params . '">' .
5868
                    Display::return_icon('wizard_na.png', get_lang('RemoveAsTemplate'), '', ICON_SIZE_SMALL) . '</a>';
5869
            }
5870
            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . $courseParams . '&action=export_to_pdf&id=' . $id . '">' .
5871
                Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a>';
5872
        }
5873
5874
        return $modify_icons;
5875
    }
5876
5877
    /**
5878
     * @param $folders
5879
     * @param $curdirpath
5880
     * @param $move_file
5881
     * @param string $group_dir
5882
     * @param $form
5883
     *
5884
     * @return string
5885
     */
5886
    public static function build_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
5887
    {
5888
        $form = new FormValidator('move_to', 'post', api_get_self().'?'.api_get_cidreq());
5889
5890
        // Form title
5891
        $form->addElement('hidden', 'move_file', $move_file);
5892
5893
        $options = array();
5894
5895
        // Group documents cannot be uploaded in the root
5896
        if ($group_dir == '') {
5897
            if ($curdirpath != '/') {
5898
                $options['/'] = get_lang('Documents');
5899
            }
5900
5901
            if (is_array($folders)) {
5902
                foreach ($folders as & $folder) {
5903
                    // Hide some folders
5904
                    if ($folder == '/HotPotatoes_files' ||
5905
                        $folder == '/certificates' ||
5906
                        basename($folder) == 'css'
5907
                    ) {
5908
                        continue;
5909
                    }
5910
                    // Admin setting for Hide/Show the folders of all users
5911 View Code Duplication
                    if (api_get_setting('show_users_folders') == 'false' &&
5912
                        (strstr($folder, '/shared_folder') || strstr($folder, 'shared_folder_session_'))
5913
                    ) {
5914
                        continue;
5915
                    }
5916
5917
                    // Admin setting for Hide/Show Default folders to all users
5918 View Code Duplication
                    if (api_get_setting('show_default_folders') == 'false' &&
5919
                        (
5920
                            $folder == '/images' ||
5921
                            $folder == '/flash' ||
5922
                            $folder == '/audio' ||
5923
                            $folder == '/video' ||
5924
                            strstr($folder, '/images/gallery') ||
5925
                            $folder == '/video/flv'
5926
                        )
5927
                    ) {
5928
                        continue;
5929
                    }
5930
5931
                    // Admin setting for Hide/Show chat history folder
5932
                    if (api_get_setting('show_chat_folder') == 'false' &&
5933
                        $folder == '/chat_files') {
5934
                        continue;
5935
                    }
5936
5937
                    // You cannot move a file to:
5938
                    // 1. current directory
5939
                    // 2. inside the folder you want to move
5940
                    // 3. inside a subfolder of the folder you want to move
5941
                    if (($curdirpath != $folder) &&
5942
                        ($folder != $move_file) &&
5943
                        (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5944
                    ) {
5945
                        $path_displayed = $folder;
5946
                        // If document title is used, we have to display titles instead of real paths...
5947
                        $path_displayed = DocumentManager::get_titles_of_path($folder);
5948
5949
                        if (empty($path_displayed)) {
5950
                            $path_displayed = get_lang('Untitled');
5951
                        }
5952
                        $options[$folder] = $path_displayed;
5953
                    }
5954
                }
5955
            }
5956
        } else {
5957
            foreach ($folders as $folder) {
5958
                if (($curdirpath != $folder) &&
5959
                    ($folder != $move_file) &&
5960
                    (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5961
                ) {
5962
                    // Cannot copy dir into his own subdir
5963
                    $path_displayed = DocumentManager::get_titles_of_path($folder);
5964
                    $display_folder = substr($path_displayed, strlen($group_dir));
5965
                    $display_folder = ($display_folder == '') ? get_lang('Documents') : $display_folder;
5966
                    //$form .= '<option value="'.$folder.'">'.$display_folder.'</option>';
5967
                    $options[$folder] = $display_folder;
5968
                }
5969
            }
5970
        }
5971
        $form->addElement('select', 'move_to', get_lang('MoveTo'), $options);
5972
        $form->addButtonNext(get_lang('MoveElement'), 'move_file_submit');
5973
5974
        return $form->returnForm();
5975
    }
5976
5977
    /**
5978
     * Gets the path translated with title of docs and folders
5979
     * @param string $path the real path
5980
     * @return the path which should be displayed
5981
     */
5982
    public static function get_titles_of_path($path)
5983
    {
5984
        global $tmp_folders_titles;
5985
        $course_id = api_get_course_int_id();
5986
        $nb_slashes = substr_count($path, '/');
5987
        $current_slash_pos = 0;
5988
        $path_displayed = '';
5989
        for ($i = 0; $i < $nb_slashes; $i++) {
5990
            // For each folder of the path, retrieve title.
5991
            $current_slash_pos = strpos($path, '/', $current_slash_pos + 1);
5992
            $tmp_path = substr($path, strpos($path, '/', 0), $current_slash_pos);
5993
5994
            if (empty($tmp_path)) {
5995
                // If empty, then we are in the final part of the path
5996
                $tmp_path = $path;
5997
            }
5998
5999
            if (!empty($tmp_folders_titles[$tmp_path])) {
6000
                // If this path has soon been stored here we don't need a new query
6001
                $path_displayed .= $tmp_folders_titles[$tmp_path];
6002
            } else {
6003
                $sql = 'SELECT title FROM ' . Database::get_course_table(TABLE_DOCUMENT) . '
6004
                    WHERE c_id = ' . $course_id . ' AND path LIKE BINARY "' . $tmp_path . '"';
6005
                $rs = Database::query($sql);
6006
                $tmp_title = '/' . Database::result($rs, 0, 0);
6007
                $path_displayed .= $tmp_title;
6008
                $tmp_folders_titles[$tmp_path] = $tmp_title;
6009
            }
6010
        }
6011
6012
        return $path_displayed;
6013
    }
6014
6015
    /**
6016
     * Creates form that asks for the directory name.
6017
     * @return string	html-output text for the form
6018
     */
6019
    public static function create_dir_form($dirId)
6020
    {
6021
        global $document_id;
6022
        $form = new FormValidator('create_dir_form', 'post', api_get_self().'?'.api_get_cidreq());
6023
        $form->addElement('hidden', 'create_dir', 1);
6024
        $form->addElement('hidden', 'dir_id', intval($document_id));
6025
        $form->addElement('hidden', 'id', intval($dirId));
6026
        $form->addElement('header', get_lang('CreateDir'));
6027
        $form->addText('dirname', get_lang('NewDir'), array('autofocus' => 'autofocus'));
6028
        $form->addButtonCreate(get_lang('CreateFolder'));
6029
6030
        return $form->returnForm();
6031
6032
    }
6033
6034
    /**
6035
     * Checks whether the user is in shared folder
6036
     * @return return bool Return true when user is into shared folder
6037
     */
6038
    public static function is_shared_folder($curdirpath, $current_session_id)
6039
    {
6040
        $clean_curdirpath = Security::remove_XSS($curdirpath);
6041
        if ($clean_curdirpath == '/shared_folder') {
6042
            return true;
6043
        } elseif ($clean_curdirpath == '/shared_folder_session_' . $current_session_id) {
6044
            return true;
6045
        } else {
6046
            return false;
6047
        }
6048
    }
6049
6050
    /**
6051
     * Checks whether the user is into any user shared folder
6052
     * @return return bool Return true when user is in any user shared folder
6053
     */
6054
    public static function is_any_user_shared_folder($path, $current_session_id)
6055
    {
6056
        $clean_path = Security::remove_XSS($path);
6057
        if (strpos($clean_path, 'shared_folder/sf_user_')) {
6058
            return true;
6059
        } elseif (strpos($clean_path, 'shared_folder_session_' . $current_session_id . '/sf_user_')) {
6060
            return true;
6061
        } else {
6062
            return false;
6063
        }
6064
    }
6065
6066
    /**
6067
     * Checks whether the user is into his shared folder or into a subfolder
6068
     * @return bool Return true when user is in his user shared folder or into a subfolder
6069
     */
6070
    public static function is_my_shared_folder($user_id, $path, $current_session_id)
6071
    {
6072
        $clean_path = Security::remove_XSS($path) . '/';
6073
        //for security does not remove the last slash
6074
        $main_user_shared_folder = '/shared_folder\/sf_user_' . $user_id . '\//';
6075
        //for security does not remove the last slash
6076
        $main_user_shared_folder_session = '/shared_folder_session_' . $current_session_id . '\/sf_user_' . $user_id . '\//';
6077
6078
        if (preg_match($main_user_shared_folder, $clean_path)) {
6079
            return true;
6080
        } elseif (preg_match($main_user_shared_folder_session, $clean_path)) {
6081
            return true;
6082
        } else {
6083
            return false;
6084
        }
6085
    }
6086
6087
    /**
6088
     * Check if the file name or folder searched exist
6089
     * @return bool Return true when exist
6090
     */
6091
    public static function search_keyword($document_name, $keyword)
6092
    {
6093
        if (api_strripos($document_name, $keyword) !== false) {
6094
            return true;
6095
        } else {
6096
            return false;
6097
        }
6098
    }
6099
6100
    /**
6101
     * Checks whether a document can be previewed by using the browser.
6102
     * @param string $file_extension    The filename extension of the document (it must be in lower case).
6103
     * @return bool                     Returns TRUE or FALSE.
6104
     */
6105
    public static function is_browser_viewable($file_extension)
6106
    {
6107
        static $allowed_extensions = array(
6108
            'htm', 'html', 'xhtml',
6109
            'gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff',
6110
            'pdf', 'svg', 'swf',
6111
            'txt', 'log',
6112
            'mp4', 'ogg', 'ogv', 'ogx', 'mpg', 'mpeg', 'mov', 'avi', 'webm', 'wmv',
6113
            'mp3', 'oga', 'wav', 'au', 'wma', 'mid', 'kar'
6114
        );
6115
6116
        /*
6117
          //TODO: make a admin swich to strict mode
6118
          1. global default $allowed_extensions only: 'htm', 'html', 'xhtml', 'gif', 'jpg', 'jpeg', 'png', 'bmp', 'txt', 'log'
6119
          if (in_array($file_extension, $allowed_extensions)) { // Assignment + a logical check.
6120
          return true;
6121
          }
6122
          2. check native support
6123
          3. check plugins: quicktime, mediaplayer, vlc, acrobat, flash, java
6124
         */
6125
6126
        if (!($result = in_array($file_extension, $allowed_extensions))) { // Assignment + a logical check.
6127
            return false;
6128
        }
6129
6130
        //check native support (Explorer, Opera, Firefox, Chrome, Safari)
6131
        if ($file_extension == "pdf") {
6132
            return api_browser_support('pdf');
6133
        } elseif ($file_extension == "mp3") {
6134
            return api_browser_support('mp3');
6135
        } elseif ($file_extension == "mp4") {
6136
            return api_browser_support('mp4');
6137
        } elseif ($file_extension == "ogg" || $file_extension == "ogx" || $file_extension == "ogv" || $file_extension == "oga") {
6138
            return api_browser_support('ogg');
6139
        } elseif ($file_extension == "svg") {
6140
            return api_browser_support('svg');
6141
        } elseif ($file_extension == "mpg" || $file_extension == "mpeg") {
6142
            return api_browser_support('mpg');
6143
        } elseif ($file_extension == "mov") {
6144
            return api_browser_support('mov');
6145
        } elseif ($file_extension == "wav") {
6146
            return api_browser_support('wav');
6147
        } elseif ($file_extension == "mid" || $file_extension == "kar") {
6148
            return api_browser_support('mid');
6149
        } elseif ($file_extension == "avi") {
6150
            return api_browser_support('avi');
6151
        } elseif ($file_extension == "wma") {
6152
            return api_browser_support('wma');
6153
        } elseif ($file_extension == "wmv") {
6154
            return api_browser_support('wmv');
6155
        } elseif ($file_extension == "tif" || $file_extension == "tiff") {
6156
            return api_browser_support('tif');
6157
        } elseif ($file_extension == "mov") {
6158
            return api_browser_support('mov');
6159
        } elseif ($file_extension == "au") {
6160
            return api_browser_support('au');
6161
        } elseif ($file_extension == "webm") {
6162
            return api_browser_support('webm');
6163
        }
6164
        return $result;
6165
    }
6166
6167
    /**
6168
     * @param array $courseInfo
6169
     * @param int $sessionId
6170
     *
6171
     * @return array
6172
     */
6173 View Code Duplication
    public static function getDeletedDocuments($courseInfo, $sessionId = 0)
6174
    {
6175
        $table = Database::get_course_table(TABLE_DOCUMENT);
6176
        $courseId = $courseInfo['real_id'];
6177
        $sessionCondition = api_get_session_condition($sessionId);
6178
        $sql = "SELECT * FROM $table
6179
                WHERE
6180
                  path LIKE '%DELETED%' AND
6181
                  c_id = $courseId
6182
                  $sessionCondition
6183
                ORDER BY path
6184
        ";
6185
6186
        $result = Database::query($sql);
6187
        $files = array();
6188
        while ($document = Database::fetch_array($result, 'ASSOC')) {
6189
            $files[] = $document;
6190
        }
6191
6192
        return $files;
6193
    }
6194
6195
    /**
6196
     * @param int $id
6197
     * @param array $courseInfo
6198
     * @param int $sessionId
6199
     *
6200
     * @return array
6201
     */
6202
    public static function getDeletedDocument($id, $courseInfo, $sessionId = 0)
6203
    {
6204
        if (empty($courseInfo)) {
6205
            return false;
6206
        }
6207
6208
        $table = Database::get_course_table(TABLE_DOCUMENT);
6209
        $courseId = $courseInfo['real_id'];
6210
        $sessionCondition = api_get_session_condition($sessionId);
6211
        $sql = "SELECT * FROM $table
6212
                WHERE
6213
                  path LIKE '%DELETED%' AND
6214
                  id = $id AND
6215
                  c_id = $courseId
6216
                  $sessionCondition
6217
                LIMIT 1
6218
        ";
6219
        $result = Database::query($sql);
6220
        if (Database::num_rows($result)) {
6221
            $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...
6222
6223
            return $result;
6224
        }
6225
6226
        return array();
6227
    }
6228
6229
    /**
6230
     * @param int $id
6231
     * @param array $courseInfo
6232
     * @param int $sessionId
6233
     * @return bool
6234
     */
6235
    public static function purgeDocument($id, $courseInfo, $sessionId = 0)
6236
    {
6237
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6238 View Code Duplication
        if (!empty($document)) {
6239
            $path = $document['path'];
6240
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6241
            my_delete($coursePath.$path);
6242
            // Hard delete.
6243
            self::deleteDocumentFromDb($id, $courseInfo, $sessionId, true);
6244
6245
            return true;
6246
        }
6247
        return false;
6248
    }
6249
6250
    /**
6251
     * @param array $courseInfo
6252
     * @param int $sessionId
6253
     */
6254
    public static function purgeDocuments($courseInfo, $sessionId)
6255
    {
6256
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6257
        foreach ($files as $file) {
6258
            self::purgeDocument($file['id'], $courseInfo, $sessionId);
6259
        }
6260
    }
6261
6262
    /**
6263
     * @param int $id
6264
     * @param array $courseInfo
6265
     * @param int $sessionId
6266
     * @return bool
6267
     */
6268
    public static function downloadDeletedDocument($id, $courseInfo, $sessionId)
6269
    {
6270
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6271 View Code Duplication
        if (!empty($document)) {
6272
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6273
6274
            if (Security::check_abs_path($coursePath.$document['path'], $coursePath)) {
6275
                self::file_send_for_download($coursePath.$document['path']);
6276
                exit;
6277
            }
6278
        }
6279
    }
6280
6281
    /**
6282
     * @param array $courseInfo
6283
     * @param int $sessionId
6284
     *
6285
     * @return bool
6286
     */
6287
    public static function downloadAllDeletedDocument($courseInfo, $sessionId)
6288
    {
6289
        // Zip library for creation of the zip file.
6290
        require api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
6291
6292
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6293
6294
        if (empty($files)) {
6295
            return false;
6296
        }
6297
6298
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
6299
6300
        // Creating a ZIP file.
6301
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
6302
        $zip = new PclZip($tempZipFile);
6303
        foreach ($files as $file) {
6304
            $zip->add(
6305
                $coursePath.$file['path'],
6306
                PCLZIP_OPT_REMOVE_PATH,
6307
                $coursePath
6308
            );
6309
        }
6310
6311 View Code Duplication
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
6312
            DocumentManager::file_send_for_download($tempZipFile, true);
6313
            @unlink($tempZipFile);
6314
            exit;
6315
        }
6316
    }
6317
6318
    /**
6319
     *
6320
     * Delete documents from a session in a course.
6321
     * @param array $courseInfo
6322
     * @param int $sessionId
6323
     *
6324
     * @return bool
6325
     */
6326
    public static function deleteDocumentsFromSession($courseInfo, $sessionId)
6327
    {
6328
        if (empty($courseInfo)) {
6329
            return false;
6330
        }
6331
6332
        if (empty($sessionId)) {
6333
            return false;
6334
        }
6335
6336
        $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
6337
        $documentTable = Database::get_course_table(TABLE_DOCUMENT);
6338
6339
        $conditionSession = api_get_session_condition($sessionId, true, false, 'd.session_id');
6340
        $courseId = $courseInfo['real_id'];
6341
6342
        // get invisible folders
6343
        $sql = "SELECT DISTINCT d.id, path
6344
                FROM $itemPropertyTable i
6345
                INNER JOIN $documentTable d
6346
                ON (i.c_id = d.c_id)
6347
                WHERE
6348
                    d.id = i.ref AND
6349
                    i.tool = '" . TOOL_DOCUMENT . "'
6350
                    $conditionSession AND
6351
                    i.c_id = $courseId AND
6352
                    d.c_id = $courseId ";
6353
6354
        $result = Database::query($sql);
6355
        $documents = Database::store_result($result, 'ASSOC');
6356
        if ($documents) {
6357
            $course_dir = $courseInfo['directory'] . '/document';
6358
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
6359
            $base_work_dir = $sys_course_path . $course_dir;
6360
6361
            foreach ($documents as $document) {
6362
                $documentId = $document['id'];
6363
                DocumentManager::delete_document(
6364
                    $courseInfo,
6365
                    null,
6366
                    $base_work_dir,
6367
                    $sessionId,
6368
                    $documentId
6369
                );
6370
            }
6371
        }
6372
6373
        $sql = "DELETE FROM $documentTable
6374
                WHERE c_id = $courseId AND session_id = $sessionId";
6375
        Database::query($sql);
6376
6377
        $sql = "DELETE FROM $itemPropertyTable
6378
                WHERE c_id = $courseId AND session_id = $sessionId AND tool = '".TOOL_DOCUMENT."'";
6379
        Database::query($sql);
6380
    }
6381
6382
    /**
6383
     * Update the file or directory path in the document db document table
6384
     *
6385
     * @author - Hugues Peeters <[email protected]>
6386
     * @param  - action (string) - action type require : 'delete' or 'update'
6387
     * @param  - old_path (string) - old path info stored to change
6388
     * @param  - new_path (string) - new path info to substitute
6389
     * @desc Update the file or directory path in the document db document table
6390
     *
6391
     */
6392
    public static function updateDbInfo($action, $old_path, $new_path = '')
6393
    {
6394
        $dbTable = Database::get_course_table(TABLE_DOCUMENT);
6395
        $course_id = api_get_course_int_id();
6396
        switch ($action) {
6397
            case 'delete':
6398
                $old_path = Database::escape_string($old_path);
6399
                $query = "DELETE FROM $dbTable
6400
                          WHERE
6401
                            c_id = $course_id AND
6402
                            (
6403
                                path LIKE BINARY '".$old_path."' OR
6404
                                path LIKE BINARY '".$old_path."/%'
6405
                            )";
6406
                Database::query($query);
6407
                break;
6408
            case 'update':
6409
                if ($new_path[0] == '.') {
6410
                    $new_path = substr($new_path, 1);
6411
                }
6412
                $new_path = str_replace('//', '/', $new_path);
6413
6414
                // Attempt to update	- tested & working for root	dir
6415
                $new_path = Database::escape_string($new_path);
6416
                $query = "UPDATE $dbTable SET
6417
                            path = CONCAT('".$new_path."', SUBSTRING(path, LENGTH('".$old_path."')+1) )
6418
                          WHERE c_id = $course_id AND (path LIKE BINARY '".$old_path."' OR path LIKE BINARY '".$old_path."/%')";
6419
                Database::query($query);
6420
                break;
6421
        }
6422
    }
6423
}
6424