Passed
Push — 1.10.x ( 23173d...b65d66 )
by
unknown
59:50 queued 10:49
created

DocumentManager::parseFolder()   D

Complexity

Conditions 15
Paths 320

Size

Total Lines 75
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 75
rs 4
cc 15
eloc 39
nc 320
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

There are different options of fixing this problem.

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

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

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

Loading history...
585
                    $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
586
                }
587
                $sharedCondition .= ' AND docs.path IN ("' . implode('","', $conditionList) . '")';
588
            }
589
        }
590
591
        $sql = "SELECT
592
                    docs.id,
593
                    docs.filetype,
594
                    docs.path,
595
                    docs.title,
596
                    docs.comment,
597
                    docs.size,
598
                    docs.readonly,
599
                    docs.session_id,
600
                    last.session_id item_property_session_id,
601
                    last.lastedit_date,
602
                    last.visibility,
603
                    last.insert_user_id
604
                FROM $TABLE_ITEMPROPERTY AS last
605
                INNER JOIN $TABLE_DOCUMENT AS docs
606
                ON (
607
                    docs.id = last.ref AND
608
                    last.tool = '".TOOL_DOCUMENT."' AND
609
                    docs.c_id = {$_course['real_id']} AND
610
                    last.c_id = {$_course['real_id']}
611
                )
612
                WHERE
613
                    docs.path LIKE '" . Database::escape_string($path . $added_slash.'%'). "' AND
614
                    docs.path NOT LIKE '" . Database::escape_string($path . $added_slash.'%/%')."' AND
615
                    docs.path NOT LIKE '%_DELETED_%' AND
616
                    $userGroupFilter AND
617
                    last.visibility $visibility_bit
618
                    $condition_session
619
                    $sharedCondition
620
                ";
621
        $result = Database::query($sql);
622
623
        $doc_list = array();
624
        $document_data = array();
625
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
626
        $isCoach = api_is_coach();
627
        if ($result !== false && Database::num_rows($result) != 0) {
628
            while ($row = Database::fetch_array($result, 'ASSOC')) {
629
                if ($isCoach) {
630
                    // Looking for course items that are invisible to hide it in the session
631
                    if (in_array($row['id'], array_keys($doc_list))) {
632
                        if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
633
                            $doc_list[$row['id']]['session_id'] == 0
634
                        ) {
635
                            if ($doc_list[$row['id']]['visibility'] == 0) {
636
                                unset($document_data[$row['id']]);
637
                                continue;
638
                            }
639
                        }
640
                    }
641
                    $doc_list[$row['id']] = $row;
642
                }
643
644
                if (!$isCoach && !$is_allowed_to_edit) {
645
                    $doc_list[] = $row;
646
                }
647
648
                if ($row['filetype'] == 'file' &&
649
                    pathinfo($row['path'], PATHINFO_EXTENSION) == 'html'
650
                ) {
651
                    // Templates management
652
                    $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
653
                    $sql = "SELECT id FROM $table_template
654
                            WHERE
655
                                course_code = '" . $_course['code'] . "' AND
656
                                user_id = '".api_get_user_id()."' AND
657
                                ref_doc = '".$row['id']."'";
658
                    $template_result = Database::query($sql);
659
                    $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
660
                }
661
                // Just filling $document_data.
662
                $document_data[$row['id']] = $row;
663
            }
664
665
            // Only for the student we filter the results see BT#1652
666
            if (!$isCoach && !$is_allowed_to_edit) {
667
                $ids_to_remove = array();
668
                $my_repeat_ids = $temp = array();
669
670
                // Selecting repeated ids
671
                foreach ($doc_list as $row) {
672
                    if (in_array($row['id'], array_keys($temp))) {
673
                        $my_repeat_ids[] = $row['id'];
674
                    }
675
                    $temp[$row['id']] = $row;
676
                }
677
678
                //@todo use the DocumentManager::is_visible function
679
                // Checking visibility in a session
680
                foreach ($my_repeat_ids as $id) {
681
                    foreach ($doc_list as $row) {
682
                        if ($id == $row['id']) {
683 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
684
                                $delete_repeated[$id] = true;
685
                            }
686 View Code Duplication
                            if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
687
                                $delete_repeated[$id] = true;
688
                            }
689
                        }
690
                    }
691
                }
692
693
                foreach ($doc_list as $key => $row) {
694
                    if (in_array($row['visibility'], array('0', '2')) &&
695
                        !in_array($row['id'], $my_repeat_ids)
696
                    ) {
697
                        $ids_to_remove[] = $row['id'];
698
                        unset($doc_list[$key]);
699
                    }
700
                }
701
702
                foreach ($document_data as $row) {
703
                    if (in_array($row['id'], $ids_to_remove)) {
704
                        unset($document_data[$row['id']]);
705
                    }
706
                    if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
707
                        unset($document_data[$row['id']]);
708
                    }
709
                }
710
711
                // Checking parents visibility.
712
                $final_document_data = array();
713
                foreach ($document_data as $row) {
714
                    $is_visible = DocumentManager::check_visibility_tree(
715
                        $row['id'],
716
                        $_course['code'],
717
                        $sessionId,
718
                        api_get_user_id(),
719
                        $to_group_id
720
                    );
721
                    if ($is_visible) {
722
                        $final_document_data[$row['id']] = $row;
723
                    }
724
                }
725
            } else {
726
                $final_document_data = $document_data;
727
            }
728
729
            return $final_document_data;
730
        } else {
731
            return false;
732
        }
733
    }
734
735
    /**
736
     * Gets the paths of all folders in a course
737
     * can show all folders (except for the deleted ones) or only visible ones
738
     *
739
     * @param array $_course
740
     * @param int $to_group_id
741
     * @param boolean $can_see_invisible
742
     *
743
     * @return array with paths
744
     */
745
    public static function get_all_document_folders(
746
        $_course,
747
        $to_group_id = 0,
748
        $can_see_invisible = false
749
    ) {
750
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
751
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
752
        $to_group_id = intval($to_group_id);
753
        $document_folders = array();
754
755
        $students = CourseManager::get_user_list_from_course_code(
756
            $_course['code'],
757
            api_get_session_id()
758
        );
759
760
        $sharedCondition = null;
761
762
        if (!empty($students)) {
763
            $conditionList = array();
764
            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...
765
                $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
766
            }
767
        }
768
769
        $groupCondition = " last.to_group_id = $to_group_id";
770
        if (empty($to_group_id)) {
771
            $groupCondition = " (last.to_group_id = 0 OR last.to_group_id IS NULL)";
772
        }
773
774
        if ($can_see_invisible) {
775
            // condition for the session
776
            $session_id = api_get_session_id();
777
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
778
            $show_users_condition = "";
779
            if (api_get_setting('show_users_folders') == 'false') {
780
                $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
781
            }
782
783
            if ($to_group_id <> 0) {
784
                $sql = "SELECT DISTINCT docs.id, path
785
                       FROM $TABLE_ITEMPROPERTY  AS last
786
                       INNER JOIN $TABLE_DOCUMENT  AS docs
787
                       ON (
788
                            docs.id = last.ref AND
789
                            last.tool = '" . TOOL_DOCUMENT . "' AND
790
                            last.c_id = {$_course['real_id']} AND
791
                            docs.c_id = {$_course['real_id']}
792
                       )
793
                       WHERE
794
                            docs.filetype 		= 'folder' AND
795
                            $groupCondition AND
796
                            docs.path NOT LIKE '%shared_folder%' AND
797
                            docs.path NOT LIKE '%_DELETED_%' AND
798
                            last.visibility 	<> 2
799
                            $condition_session ";
800
            } else {
801
                $sql = "SELECT DISTINCT docs.id, path
802
                        FROM $TABLE_ITEMPROPERTY  AS last
803
                        INNER JOIN $TABLE_DOCUMENT  AS docs
804
                        ON (
805
                            docs.id = last.ref AND
806
                            last.tool = '" . TOOL_DOCUMENT . "' AND
807
                            last.c_id = {$_course['real_id']} AND
808
                            docs.c_id = {$_course['real_id']}
809
                        )
810
                        WHERE
811
                            docs.filetype 		= 'folder' AND
812
                            docs.path NOT LIKE '%_DELETED_%' AND
813
                            $groupCondition AND
814
                            last.visibility 	<> 2
815
                            $show_users_condition $condition_session ";
816
            }
817
            $result = Database::query($sql);
818
819
            if ($result && Database::num_rows($result) != 0) {
820
                while ($row = Database::fetch_array($result, 'ASSOC')) {
821
                    if (DocumentManager::is_folder_to_avoid($row['path'])) {
822
                        continue;
823
                    }
824
825
                    if (strpos($row['path'], '/shared_folder/') !== false) {
826
                        if (!in_array($row['path'], $conditionList)) {
827
                            continue;
828
                        }
829
                    }
830
831
                    $document_folders[$row['id']] = $row['path'];
832
                }
833
834
                if (!empty($document_folders)) {
835
                    natsort($document_folders);
836
                }
837
                return $document_folders;
838
            } else {
839
                return false;
840
            }
841
        } else {
842
            // No invisible folders
843
            // Condition for the session
844
            $session_id = api_get_session_id();
845
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
846
            //get visible folders
847
            $sql = "SELECT DISTINCT docs.id, path
848
                    FROM
849
                        $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
850
                    WHERE
851
                        docs.id = last.ref AND
852
                        docs.filetype = 'folder' AND
853
                        last.tool = '" . TOOL_DOCUMENT . "' AND
854
                        $groupCondition AND
855
                        last.visibility = 1
856
                        $condition_session AND
857
                        last.c_id = {$_course['real_id']}  AND
858
                        docs.c_id = {$_course['real_id']} ";
859
            $result = Database::query($sql);
860
            $visibleFolders = array();
861
            while ($row = Database::fetch_array($result, 'ASSOC')) {
862
                $visibleFolders[$row['id']] = $row['path'];
863
            }
864
865
            // Condition for the session
866
            $session_id = api_get_session_id();
867
            $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
868
            //get invisible folders
869
            $sql = "SELECT DISTINCT docs.id, path
870
                    FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
871
                    WHERE
872
                        docs.id = last.ref AND
873
                        docs.filetype = 'folder' AND
874
                        last.tool = '" . TOOL_DOCUMENT . "' AND
875
                        $groupCondition AND
876
                        last.visibility = 0 $condition_session AND
877
                        last.c_id = {$_course['real_id']} AND
878
                        docs.c_id = {$_course['real_id']} ";
879
            $result = Database::query($sql);
880
            $invisibleFolders = array();
881
            while ($row = Database::fetch_array($result, 'ASSOC')) {
882
                //condition for the session
883
                $session_id = api_get_session_id();
884
                $condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
885
                //get visible folders in the invisible ones -> they are invisible too
886
                $sql = "SELECT DISTINCT docs.id, path
887
                        FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
888
                        WHERE
889
                            docs.id = last.ref AND
890
                            docs.path LIKE '" . Database::escape_string($row['path'].'/%') . "' AND
891
                            docs.filetype = 'folder' AND
892
                            last.tool = '" . TOOL_DOCUMENT . "' AND
893
                            $groupCondition AND
894
                            last.visibility = 1 $condition_session AND
895
                            last.c_id = {$_course['real_id']} AND
896
                            docs.c_id = {$_course['real_id']}  ";
897
                $folder_in_invisible_result = Database::query($sql);
898
                while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
899
                    $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
900
                }
901
            }
902
903
            //if both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
904
            if (is_array($visibleFolders) && is_array($invisibleFolders)) {
905
                $document_folders = array_diff($visibleFolders, $invisibleFolders);
906
                natsort($document_folders);
907
                return $document_folders;
908
            } elseif (is_array($visibleFolders)) {
909
                natsort($visibleFolders);
910
                return $visibleFolders;
911
            } else {
912
                //no visible folders found
913
                return false;
914
            }
915
        }
916
    }
917
918
    /**
919
     * This check if a document has the readonly property checked, then see if the user
920
     * is the owner of this file, if all this is true then return true.
921
     *
922
     * @param array  $_course
923
     * @param int    $user_id id of the current user
924
     * @param string $file path stored in the database (if not defined, $documentId must be used)
925
     * @param int    $document_id in case you dont have the file path ,
926
     *                insert the id of the file here and leave $file in blank ''
927
     * @param bool $to_delete
928
     * @param int $sessionId
929
     * @return boolean true/false
930
     * */
931
    public static function check_readonly(
932
        $_course,
933
        $user_id,
934
        $file = null,
935
        $document_id = '',
936
        $to_delete = false,
937
        $sessionId = null,
938
        $documentId = null
939
    ) {
940
941
        if (empty($sessionId)) {
942
            $sessionId = api_get_session_id();
943
        } else {
944
            $sessionId = intval($sessionId);
945
        }
946
947
        if (empty($document_id) || !is_numeric($document_id)) {
948
            $document_id = self::get_document_id($_course, $file, $sessionId);
949
        } else {
950
            $document_id = intval($document_id);
951
        }
952
953
        $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
954
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
955
        $course_id = $_course['real_id'];
956
957
        if ($to_delete) {
958
            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 948 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...
959
                if (!empty($file)) {
960
                    $path = Database::escape_string($file);
961
                    // Check
962
                    $sql = "SELECT td.id, readonly, tp.insert_user_id
963
                            FROM $TABLE_DOCUMENT td, $TABLE_PROPERTY tp
964
                            WHERE
965
                                td.c_id = $course_id AND
966
                                tp.c_id = $course_id AND
967
                                td.session_id = $sessionId AND
968
                                tp.ref= td.id AND
969
                                (path='" . $path . "' OR path LIKE BINARY '" . $path . "/%' ) ";
970
                    // Get all id's of documents that are deleted
971
                    $what_to_check_result = Database::query($sql);
972
973
                    if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
974
                        // file with readonly set to 1 exist?
975
                        $readonly_set = false;
976
                        while ($row = Database::fetch_array($what_to_check_result)) {
977
                            //query to delete from item_property table
978
                            if ($row['readonly'] == 1) {
979
                                if (!($row['insert_user_id'] == $user_id)) {
980
                                    $readonly_set = true;
981
                                    break;
982
                                }
983
                            }
984
                        }
985
986
                        if ($readonly_set) {
987
                            return true;
988
                        }
989
                    }
990
                }
991
                return false;
992
            }
993
        }
994
995
        if (!empty($document_id)) {
996
            $sql = "SELECT a.insert_user_id, b.readonly
997
                   FROM $TABLE_PROPERTY a, $TABLE_DOCUMENT b
998
                   WHERE
999
            			a.c_id = $course_id AND
1000
                        b.c_id = $course_id AND
1001
            			a.ref = b.id and a.ref = $document_id LIMIT 1";
1002
            $result = Database::query($sql);
1003
            $doc_details = Database ::fetch_array($result, 'ASSOC');
1004
1005
            if ($doc_details['readonly'] == 1) {
1006
                return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
1007
            }
1008
        }
1009
        return false;
1010
    }
1011
1012
    /**
1013
     * This check if a document is a folder or not
1014
     * @param array  $_course
1015
     * @param int    $document_id of the item
1016
     * @return boolean true/false
1017
     * */
1018
    public static function is_folder($_course, $document_id)
1019
    {
1020
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1021
        $course_id = $_course['real_id'];
1022
        $document_id = intval($document_id);
1023
        $sql = "SELECT filetype FROM $TABLE_DOCUMENT
1024
                WHERE c_id = $course_id AND id= $document_id";
1025
        $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...
1026
        return $result['filetype'] == 'folder';
1027
    }
1028
1029
    /**
1030
     * @param int $document_id
1031
     * @param array $course_info
1032
     * @param int $session_id
1033
     * @param bool $remove_content_from_db
1034
     */
1035
    public static function deleteDocumentFromDb(
1036
        $document_id,
1037
        $course_info = array(),
1038
        $session_id = 0,
1039
        $remove_content_from_db = false
1040
    ) {
1041
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1042
        $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
1043
1044
        // Deleting from the DB
1045
        $user_id = api_get_user_id();
1046
        $document_id = intval($document_id);
1047
1048
        if (empty($course_info)) {
1049
            $course_info = api_get_course_info();
1050
        }
1051
1052
        if (empty($session_id)) {
1053
            $session_id = api_get_session_id();
1054
        }
1055
1056
        // Soft DB delete
1057
        api_item_property_update(
1058
            $course_info,
1059
            TOOL_DOCUMENT,
1060
            $document_id,
1061
            'delete',
1062
            $user_id,
1063
            null,
1064
            null,
1065
            null,
1066
            null,
1067
            $session_id
1068
        );
1069
        self::delete_document_from_search_engine($course_info['code'], $document_id);
1070
        self::unset_document_as_template($document_id, $course_info['code'], $user_id);
1071
1072
        //Hard DB delete
1073
        if ($remove_content_from_db) {
1074
            $sql = "DELETE FROM $TABLE_ITEMPROPERTY
1075
                    WHERE
1076
                        c_id = {$course_info['real_id']} AND
1077
                        ref = ".$document_id." AND
1078
                        tool='".TOOL_DOCUMENT."'";
1079
            Database::query($sql);
1080
1081
            $sql = "DELETE FROM $TABLE_DOCUMENT
1082
                    WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
1083
            Database::query($sql);
1084
        }
1085
    }
1086
1087
    /**
1088
     * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
1089
     * Files/folders that are inside a deleted folder get visibility 2
1090
     *
1091
     * @param array $_course
1092
     * @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...
1093
     * @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...
1094
     * @param int   $sessionId The ID of the session, if any
1095
     * @param int   $documentId The document id, if available
1096
     * @param int $groupId
1097
     * @return boolean true/false
1098
     * @todo now only files/folders in a folder get visibility 2, we should rename them too.
1099
     * @todo We should be able to get rid of this later when using only documentId (check further usage)
1100
     */
1101
    public static function delete_document(
1102
        $_course,
1103
        $path = null,
1104
        $base_work_dir = null,
1105
        $sessionId = null,
1106
        $documentId = null,
1107
        $groupId = null
1108
    ) {
1109
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1110
1111
        if (empty($groupId)) {
1112
            $groupId = api_get_group_id();
1113
        } else {
1114
            $groupId = intval($groupId);
1115
        }
1116
1117
        if (empty($sessionId)) {
1118
            $sessionId = api_get_session_id();
1119
        } else {
1120
            $sessionId = intval($sessionId);
1121
        }
1122
1123
        $course_id = $_course['real_id'];
1124
1125
        if (empty($course_id)) {
1126
            return false;
1127
        }
1128
1129
        if (empty($base_work_dir)) {
1130
            return false;
1131
        }
1132
        if (empty($documentId)) {
1133
            $documentId = self::get_document_id($_course, $path, $sessionId);
1134
            $docInfo = self::get_document_data_by_id(
1135
                $documentId,
0 ignored issues
show
Security Bug introduced by
It seems like $documentId defined by self::get_document_id($_course, $path, $sessionId) on line 1133 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...
1136
                $_course['code'],
1137
                false,
1138
                $sessionId
1139
            );
1140
            $path = $docInfo['path'];
1141 View Code Duplication
        } else {
1142
            $docInfo = self::get_document_data_by_id(
1143
                $documentId,
1144
                $_course['code'],
1145
                false,
1146
                $sessionId
1147
            );
1148
            if (empty($docInfo)) {
1149
                return false;
1150
            }
1151
            $path = $docInfo['path'];
1152
        }
1153
1154
        $documentId = intval($documentId);
1155
1156
        if (empty($path) || empty($docInfo) || empty($documentId)) {
1157
            return false;
1158
        }
1159
        $itemInfo = api_get_item_property_info(
1160
            $_course['real_id'],
1161
            TOOL_DOCUMENT,
1162
            $documentId,
1163
            $sessionId
1164
        );
1165
1166
        if (empty($itemInfo)) {
1167
            return false;
1168
        }
1169
1170
        // File was already deleted.
1171
        if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
1172
            $itemInfo['lastedit_type'] == 'delete' ||
1173
            $itemInfo['visibility'] == 2
1174
        ) {
1175
            return false;
1176
        }
1177
1178
        // Filtering by group.
1179
        if ($itemInfo['to_group_id'] != $groupId) {
1180
            return false;
1181
        }
1182
1183
        $document_exists_in_disk = file_exists($base_work_dir.$path);
1184
        $new_path = $path.'_DELETED_'.$documentId;
1185
1186
        $file_deleted_from_db = false;
1187
        $file_deleted_from_disk = false;
1188
        $file_renamed_from_disk = false;
1189
1190
        if ($documentId) {
1191
            // Deleting doc from the DB.
1192
            self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1193
            // Checking
1194
            // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
1195
            $file_deleted_from_db = true;
1196
        }
1197
1198
        // Looking for children.
1199
        if ($docInfo['filetype'] == 'folder') {
1200
            $cleanPath = Database::escape_string($path);
1201
1202
            // Deleted files inside this folder.
1203
            $sql = "SELECT id FROM $TABLE_DOCUMENT
1204
                    WHERE
1205
                        c_id = $course_id AND
1206
                        session_id = $sessionId AND
1207
                        path LIKE BINARY '".$cleanPath."/%'";
1208
1209
            // Get all id's of documents that are deleted.
1210
            $result = Database::query($sql);
1211
1212
            if ($result && Database::num_rows($result) != 0) {
1213
                // Recursive delete.
1214
                while ($row = Database::fetch_array($result)) {
1215
                    self::delete_document(
1216
                        $_course,
1217
                        null,
1218
                        $base_work_dir,
1219
                        $sessionId,
1220
                        $row['id']
1221
                    );
1222
                }
1223
            }
1224
        }
1225
1226
        if ($document_exists_in_disk) {
1227
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
1228
                // Delete documents, do it like this so metadata gets deleted too
1229
                my_delete($base_work_dir.$path);
1230
                // Hard delete.
1231
                self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
1232
                $file_deleted_from_disk = true;
1233
            } else {
1234
                // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
1235
1236
                if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
1237
                    if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
1238
                        $new_path = Database::escape_string($new_path);
1239
1240
                        $sql = "UPDATE $TABLE_DOCUMENT
1241
                                SET path = '".$new_path."'
1242
                                WHERE
1243
                                    c_id = $course_id AND
1244
                                    session_id = $sessionId AND
1245
                                    id = ".$documentId;
1246
                        Database::query($sql);
1247
1248
                        // Soft delete.
1249
                        self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1250
1251
                        // Change path of sub folders and documents in database.
1252
                        $old_item_path = $docInfo['path'];
1253
                        $new_item_path = $new_path.substr($old_item_path, strlen($path));
1254
                        $new_item_path = Database::escape_string($new_item_path);
1255
1256
                        $sql = "UPDATE $TABLE_DOCUMENT
1257
                                SET path = '".$new_item_path."'
1258
                                WHERE
1259
                                    c_id = $course_id AND
1260
                                    session_id = $sessionId AND
1261
                                    id = ".$documentId;
1262
                        Database::query($sql);
1263
1264
                        $file_renamed_from_disk = true;
1265
                    } else {
1266
                        // Couldn't rename - file permissions problem?
1267
                        error_log(
1268
                            __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
1269
                            0
1270
                        );
1271
                    }
1272
                }
1273
            }
1274
        }
1275
        // Checking inconsistency
1276
        //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').')');
1277
        if ($file_deleted_from_db && $file_deleted_from_disk ||
1278
            $file_deleted_from_db && $file_renamed_from_disk
1279
        ) {
1280
            return true;
1281
        } else {
1282
            //Something went wrong
1283
            //The file or directory isn't there anymore (on the filesystem)
1284
            // This means it has been removed externally. To prevent a
1285
            // blocking error from happening, we drop the related items from the
1286
            // item_property and the document table.
1287
            error_log(
1288
                __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',
1289
                0
1290
            );
1291
            return false;
1292
        }
1293
    }
1294
1295
    /**
1296
     * Removes documents from search engine database
1297
     *
1298
     * @param string $course_id Course code
1299
     * @param int $document_id Document id to delete
1300
     */
1301 View Code Duplication
    public static function delete_document_from_search_engine($course_id, $document_id)
1302
    {
1303
        // remove from search engine if enabled
1304
        if (api_get_setting('search_enabled') == 'true') {
1305
            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
1306
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1307
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1308
            $res = Database::query($sql);
1309
            if (Database::num_rows($res) > 0) {
1310
                $row2 = Database::fetch_array($res);
1311
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
1312
                $di = new ChamiloIndexer();
1313
                $di->remove_document((int) $row2['search_did']);
1314
            }
1315
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1316
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1317
            Database::query($sql);
1318
1319
            // remove terms from db
1320
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
1321
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
1322
        }
1323
    }
1324
1325
    /**
1326
     * Gets the id of a document with a given path
1327
     *
1328
     * @param array $courseInfo
1329
     * @param string $path
1330
     * @param int $sessionId
1331
     * @return int id of document / false if no doc found
1332
     */
1333
    public static function get_document_id($courseInfo, $path, $sessionId = null)
1334
    {
1335
        $table = Database :: get_course_table(TABLE_DOCUMENT);
1336
        $courseId = $courseInfo['real_id'];
1337
1338
        if (!isset($sessionId)) {
1339
            $sessionId = api_get_session_id();
1340
        } else {
1341
            $sessionId = intval($sessionId);
1342
        }
1343
1344
        $path = Database::escape_string($path);
1345 View Code Duplication
        if (!empty($courseId) && !empty($path)) {
1346
            $sql = "SELECT id FROM $table
1347
                    WHERE
1348
                        c_id = $courseId AND
1349
                        path LIKE BINARY '$path' AND
1350
                        session_id = $sessionId
1351
                    LIMIT 1";
1352
1353
            $result = Database::query($sql);
1354
            if (Database::num_rows($result)) {
1355
                $row = Database::fetch_array($result);
1356
1357
                return intval($row['id']);
1358
            }
1359
        }
1360
1361
        return false;
1362
    }
1363
1364
    /**
1365
     * Gets the document data with a given id
1366
     *
1367
     * @param int $id Document Id (id field in c_document table)
1368
     * @param string $course_code Course code
1369
     * @param bool $load_parents load folder parents.
1370
     * @param int $session_id The session ID,
1371
     * 0 if requires context *out of* session, and null to use global context
1372
     * @return array document content
1373
     */
1374
    public static function get_document_data_by_id(
1375
        $id,
1376
        $course_code,
1377
        $load_parents = false,
1378
        $session_id = null
1379
    ) {
1380
        $course_info = api_get_course_info($course_code);
1381
        $course_id = $course_info['real_id'];
1382
1383
        if (empty($course_info)) {
1384
            return false;
1385
        }
1386
1387
        if (isset($session_id)) {
1388
            $session_id = intval($session_id);
1389
        } else {
1390
            $session_id = api_get_session_id();
1391
        }
1392
1393
        $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
1394
1395
        $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
1396
        $id = intval($id);
1397
        $sql = "SELECT * FROM $TABLE_DOCUMENT
1398
                WHERE c_id = $course_id AND session_id = $session_id AND id = $id";
1399
1400
        $result = Database::query($sql);
1401
        if ($result && Database::num_rows($result) == 1) {
1402
            $row = Database::fetch_array($result, 'ASSOC');
1403
1404
            //@todo need to clarify the name of the URLs not nice right now
1405
            $url_path = urlencode($row['path']);
1406
            $path = str_replace('%2F', '/', $url_path);
1407
            $pathinfo = pathinfo($row['path']);
1408
1409
            $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
1410
            $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
1411
            $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1412
            $row['absolute_path_from_document'] = '/document' . $row['path'];
1413
            $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
1414
            $row['direct_url'] = $www . $path;
1415
1416
            if (dirname($row['path']) == '.') {
1417
                $row['parent_id'] = '0';
1418
            } else {
1419
                $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
1420
            }
1421
            $parents = array();
1422
1423
            //Use to generate parents (needed for the breadcrumb)
1424
            //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
1425
1426
            if ($load_parents) {
1427
                $dir_array = explode('/', $row['path']);
1428
                $dir_array = array_filter($dir_array);
1429
                $array_len = count($dir_array) + 1;
1430
                $real_dir = '';
1431
1432
                for ($i = 1; $i < $array_len; $i++) {
1433
                    $real_dir .= '/' . $dir_array[$i];
1434
                    $parent_id = self::get_document_id($course_info, $real_dir);
1435
                    if ($session_id != 0 && empty($parent_id)) {
1436
                        $parent_id = self::get_document_id($course_info, $real_dir, 0);
1437
                    }
1438
                    if (!empty($parent_id)) {
1439
                        $sub_document_data = self::get_document_data_by_id(
1440
                            $parent_id,
1441
                            $course_code,
1442
                            false,
1443
                            $session_id
1444
                        );
1445
                        if ($session_id != 0 and !$sub_document_data) {
1446
                            $sub_document_data = self::get_document_data_by_id(
1447
                                $parent_id,
1448
                                $course_code,
1449
                                false,
1450
                                0
1451
                            );
1452
                        }
1453
                        //@todo add visibility here
1454
                        $parents[] = $sub_document_data;
1455
                    }
1456
                }
1457
            }
1458
            $row['parents'] = $parents;
1459
1460
            return $row;
1461
        }
1462
1463
        return false;
1464
    }
1465
1466
    /**
1467
     * Allow to set a specific document as a new template for CKeditor
1468
     * for a particular user in a particular course
1469
     *
1470
     * @param string $title
1471
     * @param string $description
1472
     * @param int $document_id_for_template the document id
1473
     * @param string $course_code
1474
     * @param int $user_id
1475
     * @return bool
1476
     */
1477
    public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
1478
    {
1479
        // Database table definition
1480
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1481
        $params = [
1482
            'title' => $title,
1483
            'description' => $description,
1484
            'course_code' => $course_code,
1485
            'user_id' => $user_id,
1486
            'ref_doc' => $document_id_for_template,
1487
            'image' => $image,
1488
        ];
1489
        Database::insert($table_template, $params);
1490
        return true;
1491
    }
1492
1493
    /**
1494
     * Unset a document as template
1495
     *
1496
     * @param int $document_id
1497
     * @param string $course_code
1498
     * @param int $user_id
1499
     */
1500
    public static function unset_document_as_template($document_id, $course_code, $user_id)
1501
    {
1502
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1503
        $course_code = Database::escape_string($course_code);
1504
        $user_id = intval($user_id);
1505
        $document_id = intval($document_id);
1506
1507
        $sql = 'SELECT id FROM ' . $table_template . '
1508
                WHERE
1509
                    course_code="' . $course_code . '" AND
1510
                    user_id="' . $user_id . '" AND
1511
                    ref_doc="' . $document_id . '"';
1512
        $result = Database::query($sql);
1513
        $template_id = Database::result($result, 0, 0);
1514
1515
        my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
1516
1517
        $sql = 'DELETE FROM ' . $table_template . '
1518
                WHERE
1519
                    course_code="' . $course_code . '" AND
1520
                    user_id="' . $user_id . '" AND
1521
                    ref_doc="' . $document_id . '"';
1522
1523
        Database::query($sql);
1524
    }
1525
1526
    /**
1527
     * Return true if the documentpath have visibility=1 as
1528
     * item_property (you should use the is_visible_by_id)
1529
     *
1530
     * @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...
1531
     * @param array  $course the _course array info of the document's course
1532
     * @param int
1533
     * @param string
1534
     * @return bool
1535
     */
1536
    public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
1537
    {
1538
        $docTable = Database::get_course_table(TABLE_DOCUMENT);
1539
        $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
1540
1541
        $course_id = $course['real_id'];
1542
        //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
1543
1544
        $session_id = intval($session_id);
1545
        $condition = "AND d.session_id IN  ('$session_id', '0') ";
1546
        // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
1547
1548
        /*
1549
          When using hotpotatoes files, a new html files are generated
1550
          in the hotpotatoes folder to display the test.
1551
          The genuine html file is copied to math4.htm(user_id).t.html
1552
          Images files are not copied, and keep same name.
1553
          To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
1554
          In this case, we have to remove (user_id).t.html to check the visibility of the file
1555
          For images, we just check the path of the image file.
1556
1557
          Exemple of hotpotatoes folder :
1558
          A.jpg
1559
          maths4-consigne.jpg
1560
          maths4.htm
1561
          maths4.htm1.t.html
1562
          maths4.htm52.t.html
1563
          maths4.htm654.t.html
1564
          omega.jpg
1565
          theta.jpg
1566
         */
1567
1568
        if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
1569
            $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
1570
        }
1571
1572
        if (!in_array($file_type, array('file', 'folder'))) {
1573
            $file_type = 'file';
1574
        }
1575
1576
        $sql = "SELECT visibility
1577
                FROM $docTable d
1578
                INNER JOIN $propTable ip
1579
                ON (d.id = ip.ref AND d.c_id  = $course_id AND ip.c_id = $course_id)
1580
        		WHERE
1581
        		    ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
1582
        			filetype = '$file_type' AND
1583
        			locate(concat(path,'/'), '" . Database::escape_string($doc_path.'/'). "')=1
1584
                ";
1585
1586
        $result = Database::query($sql);
1587
        $is_visible = false;
1588 View Code Duplication
        if (Database::num_rows($result) > 0) {
1589
            $row = Database::fetch_array($result, 'ASSOC');
1590
            if ($row['visibility'] == 1) {
1591
                $is_visible = api_is_allowed_in_course() || api_is_platform_admin();
1592
            }
1593
        }
1594
1595
        /* improved protection of documents viewable directly through the url:
1596
            incorporates the same protections of the course at the url of
1597
            documents:
1598
            access allowed for the whole world Open, access allowed for
1599
            users registered on the platform Private access, document accessible
1600
            only to course members (see the Users list), Completely closed;
1601
            the document is only accessible to the course admin and
1602
            teaching assistants.*/
1603
        //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
1604
        return $is_visible;
1605
    }
1606
1607
    /**
1608
     * Return true if user can see a file
1609
     *
1610
     * @param   int     document id
1611
     * @param   array   course info
1612
     * @param   int
1613
     * @param   int
1614
     * @param bool
1615
     * @return  bool
1616
     */
1617
    public static function is_visible_by_id(
1618
        $doc_id,
1619
        $course_info,
1620
        $session_id,
1621
        $user_id,
1622
        $admins_can_see_everything = true
1623
    ) {
1624
        $user_in_course = false;
1625
1626
        //1. Checking the course array
1627
        if (empty($course_info)) {
1628
            $course_info = api_get_course_info();
1629
            if (empty($course_info)) {
1630
                return false;
1631
            }
1632
        }
1633
1634
        $doc_id = intval($doc_id);
1635
        $session_id = intval($session_id);
1636
1637
        //2. Course and Session visibility are handle in local.inc.php/global.inc.php
1638
        //3. Checking if user exist in course/session
1639
1640
        if ($session_id == 0) {
1641
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']) || api_is_platform_admin()
1642
            ) {
1643
                $user_in_course = true;
1644
            }
1645
            // Check if course is open then we can consider that the student is registered to the course
1646
            if (isset($course_info) &&
1647
                in_array(
1648
                    $course_info['visibility'],
1649
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
1650
                )
1651
            ) {
1652
                $user_in_course = true;
1653
            }
1654 View Code Duplication
        } else {
1655
            $user_status = SessionManager::get_user_status_in_course_session(
1656
                $user_id,
1657
                $course_info['real_id'],
1658
                $session_id
1659
            );
1660
1661
            if (in_array($user_status, array('0', '2', '6'))) {
1662
                //is true if is an student, course session teacher or coach
1663
                $user_in_course = true;
1664
            }
1665
1666
            if (api_is_platform_admin()) {
1667
                $user_in_course = true;
1668
            }
1669
        }
1670
1671
        // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
1672
1673
        if ($user_in_course) {
1674
1675
            // 4.1 Checking document visibility for a Course
1676
            if ($session_id == 0) {
1677
                $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
1678
1679
                if (isset($item_info['visibility'])) {
1680
                    // True for admins if document exists
1681
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1682
                        return true;
1683
                    }
1684
                    if ($item_info['visibility'] == 1) {
1685
                        return true;
1686
                    }
1687
                }
1688
            } else {
1689
                // 4.2 Checking document visibility for a Course in a Session
1690
                $item_info = api_get_item_property_info(
1691
                    $course_info['real_id'],
1692
                    'document',
1693
                    $doc_id,
1694
                    0
1695
                );
1696
1697
                $item_info_in_session = api_get_item_property_info(
1698
                    $course_info['real_id'],
1699
                    'document',
1700
                    $doc_id,
1701
                    $session_id
1702
                );
1703
1704
                // True for admins if document exists
1705
                if (isset($item_info['visibility'])) {
1706
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1707
                        return true;
1708
                    }
1709
                }
1710
1711
                if (isset($item_info_in_session['visibility'])) {
1712
                    if ($item_info_in_session['visibility'] == 1) {
1713
                        return true;
1714
                    }
1715
                } else {
1716
                    if ($item_info['visibility'] == 1) {
1717
                        return true;
1718
                    }
1719
                }
1720
            }
1721
        } elseif ($admins_can_see_everything && api_is_platform_admin()) {
1722
            return true;
1723
        }
1724
        return false;
1725
    }
1726
1727
    /**
1728
     * Allow attach a certificate to a course
1729
     * @param string $course_id
1730
     * @param int $document_id
1731
     * @param int $session_id
1732
     *
1733
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

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

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

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

Loading history...
1959
     */
1960
    public static function remove_attach_certificate($course_id, $default_certificate_id)
1961
    {
1962
        if (empty($default_certificate_id)) {
1963
            return false;
1964
        }
1965
1966
        $default_certificate = self::get_default_certificate_id($course_id);
1967
        if ((int) $default_certificate == (int) $default_certificate_id) {
1968
            $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
1969
            $session_id = api_get_session_id();
1970 View Code Duplication
            if ($session_id == 0 || is_null($session_id)) {
1971
                $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
1972
            } elseif ($session_id > 0) {
1973
                $sql_session = 'AND session_id=' . intval($session_id);
1974
            } else {
1975
                $sql_session = '';
1976
            }
1977
1978
            $sql = 'UPDATE ' . $tbl_category . ' SET document_id=null
1979
                    WHERE
1980
                        course_code = "' . Database::escape_string($course_id) . '" AND
1981
                        document_id="' . $default_certificate_id . '" ' . $sql_session;
1982
            Database::query($sql);
1983
        }
1984
    }
1985
1986
    /**
1987
     * Create directory certificate
1988
     * @param string $courseCode
1989
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

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

Loading history...
1990
     */
1991
    public static function create_directory_certificate_in_course($courseCode)
1992
    {
1993
        $courseInfo = api_get_course_info($courseCode);
1994
        if (!empty($courseInfo)) {
1995
            $to_group_id = 0;
1996
            $to_user_id = null;
1997
            $course_dir = $courseInfo['path'] . "/document/";
1998
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
1999
            $base_work_dir = $sys_course_path . $course_dir;
2000
            $base_work_dir_test = $base_work_dir . 'certificates';
2001
            $dir_name = '/certificates';
2002
            $post_dir_name = get_lang('CertificatesFiles');
2003
            $visibility_command = 'invisible';
2004
2005
            $id = self::get_document_id_of_directory_certificate();
2006
2007
            if (empty($id)) {
2008
2009
                create_unexisting_directory(
2010
                    $courseInfo,
2011
                    api_get_user_id(),
2012
                    api_get_session_id(),
2013
                    $to_group_id,
2014
                    $to_user_id,
2015
                    $base_work_dir,
2016
                    $dir_name,
2017
                    $post_dir_name,
2018
                    null,
2019
                    false
2020
                );
2021
2022
                $id = self::get_document_id_of_directory_certificate();
2023
2024
                if (empty($id)) {
2025
2026
                    $id = add_document(
2027
                        $courseInfo,
2028
                        $dir_name,
2029
                        'folder',
2030
                        0,
2031
                        $post_dir_name,
2032
                        null,
2033
                        0,
2034
                        true,
2035
                        $to_group_id
2036
                    );
2037
                }
2038
2039
                if (!empty($id)) {
2040
                    api_item_property_update(
2041
                        $courseInfo,
2042
                        TOOL_DOCUMENT,
2043
                        $id,
2044
                        $visibility_command,
2045
                        api_get_user_id()
2046
                    );
2047
                }
2048
            }
2049
        }
2050
    }
2051
2052
    /**
2053
     * Get the document id of the directory certificate
2054
     * @return int The document id of the directory certificate
2055
     */
2056
    public static function get_document_id_of_directory_certificate()
2057
    {
2058
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
2059
        $course_id = api_get_course_int_id();
2060
        $sql = "SELECT id FROM $tbl_document WHERE c_id = $course_id AND path='/certificates' ";
2061
        $rs = Database::query($sql);
2062
        $row = Database::fetch_array($rs);
2063
        return $row['id'];
2064
    }
2065
2066
    /**
2067
     * Check if a directory given is for certificate
2068
     * @param string $dir path of directory
2069
     * @return bool  true if is a certificate or false otherwise
2070
     */
2071
    public static function is_certificate_mode($dir)
2072
    {
2073
        // I'm in the certification module?
2074
        $is_certificate_mode = false;
2075
        $is_certificate_array = explode('/', $dir);
2076
        array_shift($is_certificate_array);
2077
        if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
2078
            $is_certificate_mode = true;
2079
        }
2080
        return $is_certificate_mode;
2081
    }
2082
2083
    /**
2084
     * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
2085
     * This allows for a better SCORM export or replace urls inside content html from copy course
2086
     * The list will generally include pictures, flash objects, java applets, or any other
2087
     * stuff included in the source of the current item. The current item is expected
2088
     * to be an HTML file or string html. If it is not, then the function will return and empty list.
2089
     * @param	string  source html (content or path)
2090
     * @param	bool  	is file or string html
2091
     * @param	string	type (one of the app tools) - optional (otherwise takes the current item's type)
2092
     * @param	int		level of recursivity we're in
2093
     * @return	array	List of file paths. An additional field containing 'local' or 'remote' helps determine
2094
     * if the file should be copied into the zip or just linked
2095
     */
2096
    public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
2097
    {
2098
        $max = 5;
2099
        $attributes = array();
2100
        $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars');
2101
        $explode_attributes = array('flashvars' => 'file');
2102
        $abs_path = '';
2103
2104
        if ($recursivity > $max) {
2105
            return array();
2106
        }
2107
2108
        if (!isset($type)) {
2109
            $type = TOOL_DOCUMENT;
2110
        }
2111
2112
        if (!$is_file) {
2113
            $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
2114
        } else {
2115
            if (is_file($source_html)) {
2116
                $abs_path = $source_html;
2117
                //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
2118
                $info = pathinfo($abs_path);
2119
                $ext = $info['extension'];
2120
                switch (strtolower($ext)) {
2121
                    case 'html':
2122
                    case 'htm':
2123
                    case 'shtml':
2124
                    case 'css':
2125
                        $file_content = file_get_contents($abs_path);
2126
                        //get an array of attributes from the HTML source
2127
                        $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
2128
                        break;
2129
                    default:
2130
                        break;
2131
                }
2132
            } else {
2133
                return false;
2134
            }
2135
        }
2136
2137
        $files_list = array();
2138
2139
        switch ($type) {
2140
            case TOOL_DOCUMENT:
2141
            case TOOL_QUIZ:
2142
            case 'sco':
2143
                foreach ($wanted_attributes as $attr) {
2144
                    if (isset($attributes[$attr])) {
2145
                        //find which kind of path these are (local or remote)
2146
                        $sources = $attributes[$attr];
2147
                        foreach ($sources as $source) {
2148
                            //skip what is obviously not a resource
2149
                            if (strpos($source, '+this.')) {
2150
                                continue; //javascript code - will still work unaltered
2151
                            }
2152
                            if (strpos($source, '.') === false) {
2153
                                continue; //no dot, should not be an external file anyway
2154
                            }
2155
                            if (strpos($source, 'mailto:')) {
2156
                                continue; //mailto link
2157
                            }
2158
                            if (strpos($source, ';') && !strpos($source, '&amp;')) {
2159
                                continue; //avoid code - that should help
2160
                            }
2161
2162 View Code Duplication
                            if ($attr == 'value') {
2163
                                if (strpos($source, 'mp3file')) {
2164
                                    $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
2165
                                    $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
2166
                                    if (substr($mp3file, 0, 1) == '/') {
2167
                                        $files_list[] = array($mp3file, 'local', 'abs');
2168
                                    } else {
2169
                                        $files_list[] = array($mp3file, 'local', 'rel');
2170
                                    }
2171
                                } elseif (strpos($source, 'flv=') === 0) {
2172
                                    $source = substr($source, 4);
2173
                                    if (strpos($source, '&') > 0) {
2174
                                        $source = substr($source, 0, strpos($source, '&'));
2175
                                    }
2176
                                    if (strpos($source, '://') > 0) {
2177
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2178
                                            //we found the current portal url
2179
                                            $files_list[] = array($source, 'local', 'url');
2180
                                        } else {
2181
                                            //we didn't find any trace of current portal
2182
                                            $files_list[] = array($source, 'remote', 'url');
2183
                                        }
2184
                                    } else {
2185
                                        $files_list[] = array($source, 'local', 'abs');
2186
                                    }
2187
                                    /* skipping anything else to avoid two entries
2188
                                    (while the others can have sub-files in their url, flv's can't)*/
2189
                                    continue;
2190
                                }
2191
                            }
2192
                            if (strpos($source, '://') > 0) {
2193
                                //cut at '?' in a URL with params
2194
                                if (strpos($source, '?') > 0) {
2195
                                    $second_part = substr($source, strpos($source, '?'));
2196
                                    if (strpos($second_part, '://') > 0) {
2197
                                        //if the second part of the url contains a url too, treat the second one before cutting
2198
                                        $pos1 = strpos($second_part, '=');
2199
                                        $pos2 = strpos($second_part, '&');
2200
                                        $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
2201 View Code Duplication
                                        if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
2202
                                            //we found the current portal url
2203
                                            $files_list[] = array($second_part, 'local', 'url');
2204
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2205
                                            if (count($in_files_list) > 0) {
2206
                                                $files_list = array_merge($files_list, $in_files_list);
2207
                                            }
2208
                                        } else {
2209
                                            //we didn't find any trace of current portal
2210
                                            $files_list[] = array($second_part, 'remote', 'url');
2211
                                        }
2212 View Code Duplication
                                    } elseif (strpos($second_part, '=') > 0) {
2213
                                        if (substr($second_part, 0, 1) === '/') {
2214
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2215
                                            $files_list[] = array($second_part, 'local', 'abs');
2216
                                            $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
2217
                                            if (count($in_files_list) > 0) {
2218
                                                $files_list = array_merge($files_list, $in_files_list);
2219
                                            }
2220
                                        } 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...
2221
                                            //link is relative but going back in the hierarchy
2222
                                            $files_list[] = array($second_part, 'local', 'rel');
2223
                                            //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
2224
                                            //$new_abs_path = realpath($dir.'/'.$second_part);
2225
                                            $dir = '';
2226
                                            if (!empty($abs_path)) {
2227
                                                $dir = dirname($abs_path) . '/';
2228
                                            }
2229
                                            $new_abs_path = realpath($dir . $second_part);
2230
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2231
                                            if (count($in_files_list) > 0) {
2232
                                                $files_list = array_merge($files_list, $in_files_list);
2233
                                            }
2234
                                        } else {
2235
                                            //no starting '/', making it relative to current document's path
2236
                                            if (substr($second_part, 0, 2) == './') {
2237
                                                $second_part = substr($second_part, 2);
2238
                                            }
2239
                                            $files_list[] = array($second_part, 'local', 'rel');
2240
                                            $dir = '';
2241
                                            if (!empty($abs_path)) {
2242
                                                $dir = dirname($abs_path) . '/';
2243
                                            }
2244
                                            $new_abs_path = realpath($dir . $second_part);
2245
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2246
                                            if (count($in_files_list) > 0) {
2247
                                                $files_list = array_merge($files_list, $in_files_list);
2248
                                            }
2249
                                        }
2250
                                    }
2251
                                    //leave that second part behind now
2252
                                    $source = substr($source, 0, strpos($source, '?'));
2253
                                    if (strpos($source, '://') > 0) {
2254 View Code Duplication
                                        if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2255
                                            //we found the current portal url
2256
                                            $files_list[] = array($source, 'local', 'url');
2257
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2258
                                            if (count($in_files_list) > 0) {
2259
                                                $files_list = array_merge($files_list, $in_files_list);
2260
                                            }
2261
                                        } else {
2262
                                            //we didn't find any trace of current portal
2263
                                            $files_list[] = array($source, 'remote', 'url');
2264
                                        }
2265 View Code Duplication
                                    } else {
2266
                                        //no protocol found, make link local
2267
                                        if (substr($source, 0, 1) === '/') {
2268
                                            //link starts with a /, making it absolute (relative to DocumentRoot)
2269
                                            $files_list[] = array($source, 'local', 'abs');
2270
                                            $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2271
                                            if (count($in_files_list) > 0) {
2272
                                                $files_list = array_merge($files_list, $in_files_list);
2273
                                            }
2274
                                        } 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...
2275
                                            $files_list[] = array($source, 'local', 'rel');
2276
                                            $dir = '';
2277
                                            if (!empty($abs_path)) {
2278
                                                $dir = dirname($abs_path) . '/';
2279
                                            }
2280
                                            $new_abs_path = realpath($dir . $source);
2281
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2282
                                            if (count($in_files_list) > 0) {
2283
                                                $files_list = array_merge($files_list, $in_files_list);
2284
                                            }
2285
                                        } else {
2286
                                            //no starting '/', making it relative to current document's path
2287
                                            if (substr($source, 0, 2) == './') {
2288
                                                $source = substr($source, 2);
2289
                                            }
2290
                                            $files_list[] = array($source, 'local', 'rel');
2291
                                            $dir = '';
2292
                                            if (!empty($abs_path)) {
2293
                                                $dir = dirname($abs_path) . '/';
2294
                                            }
2295
                                            $new_abs_path = realpath($dir . $source);
2296
                                            $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2297
                                            if (count($in_files_list) > 0) {
2298
                                                $files_list = array_merge($files_list, $in_files_list);
2299
                                            }
2300
                                        }
2301
                                    }
2302
                                }
2303
                                //found some protocol there
2304 View Code Duplication
                                if (strpos($source, api_get_path(WEB_PATH)) !== false) {
2305
                                    //we found the current portal url
2306
                                    $files_list[] = array($source, 'local', 'url');
2307
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2308
                                    if (count($in_files_list) > 0) {
2309
                                        $files_list = array_merge($files_list, $in_files_list);
2310
                                    }
2311
                                } else {
2312
                                    //we didn't find any trace of current portal
2313
                                    $files_list[] = array($source, 'remote', 'url');
2314
                                }
2315 View Code Duplication
                            } else {
2316
                                //no protocol found, make link local
2317
                                if (substr($source, 0, 1) === '/') {
2318
                                    //link starts with a /, making it absolute (relative to DocumentRoot)
2319
                                    $files_list[] = array($source, 'local', 'abs');
2320
                                    $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
2321
                                    if (count($in_files_list) > 0) {
2322
                                        $files_list = array_merge($files_list, $in_files_list);
2323
                                    }
2324
                                } elseif (strpos($source, '..') === 0) {
2325
                                    //link is relative but going back in the hierarchy
2326
                                    $files_list[] = array($source, 'local', 'rel');
2327
                                    $dir = '';
2328
                                    if (!empty($abs_path)) {
2329
                                        $dir = dirname($abs_path) . '/';
2330
                                    }
2331
                                    $new_abs_path = realpath($dir . $source);
2332
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2333
                                    if (count($in_files_list) > 0) {
2334
                                        $files_list = array_merge($files_list, $in_files_list);
2335
                                    }
2336
                                } else {
2337
                                    //no starting '/', making it relative to current document's path
2338
                                    if (substr($source, 0, 2) == './') {
2339
                                        $source = substr($source, 2);
2340
                                    }
2341
                                    $files_list[] = array($source, 'local', 'rel');
2342
                                    $dir = '';
2343
                                    if (!empty($abs_path)) {
2344
                                        $dir = dirname($abs_path) . '/';
2345
                                    }
2346
                                    $new_abs_path = realpath($dir . $source);
2347
                                    $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
2348
                                    if (count($in_files_list) > 0) {
2349
                                        $files_list = array_merge($files_list, $in_files_list);
2350
                                    }
2351
                                }
2352
                            }
2353
                        }
2354
                    }
2355
                }
2356
                break;
2357
            default: //ignore
2358
                break;
2359
        }
2360
2361
        $checked_files_list = array();
2362
        $checked_array_list = array();
2363
2364
        if (count($files_list) > 0) {
2365 View Code Duplication
            foreach ($files_list as $idx => $file) {
2366
                if (!empty($file[0])) {
2367
                    if (!in_array($file[0], $checked_files_list)) {
2368
                        $checked_files_list[] = $files_list[$idx][0];
2369
                        $checked_array_list[] = $files_list[$idx];
2370
                    }
2371
                }
2372
            }
2373
        }
2374
        return $checked_array_list;
2375
    }
2376
2377
    /**
2378
     * Parses the HTML attributes given as string.
2379
     *
2380
     * @param    string  HTML attribute string
2381
     * @param	 array	 List of attributes that we want to get back
2382
     * @param    array
2383
     * @return   array   An associative array of attributes
2384
     * @author 	 Based on a function from the HTML_Common2 PEAR module     *
2385
     */
2386
    public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
2387
    {
2388
        $attributes = array();
2389
        $regs = array();
2390
        $reduced = false;
2391
        if (count($wanted) > 0) {
2392
            $reduced = true;
2393
        }
2394
        try {
2395
            //Find all occurences of something that looks like a URL
2396
            // The structure of this regexp is:
2397
            // (find protocol) then
2398
            // (optionally find some kind of space 1 or more times) then
2399
            // find (either an equal sign or a bracket) followed by an optional space
2400
            // followed by some text without quotes (between quotes itself or not)
2401
            // then possible closing brackets if we were in the opening bracket case
2402
            // OR something like @import()
2403
            $res = preg_match_all(
2404
                '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
2405
                // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
2406
                // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
2407
                '([ \n\t\r]+)?(' .
2408
                // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
2409
                '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
2410
                '|' .
2411
                // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
2412
                '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
2413
                '))' .
2414
                '|' .
2415
                // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
2416
                '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
2417
                $attrString,
2418
                $regs
2419
            );
2420
        } catch (Exception $e) {
2421
            error_log('Caught exception: ' . $e->getMessage(), 0);
2422
        }
2423
        if ($res) {
2424
            for ($i = 0; $i < count($regs[1]); $i++) {
2425
                $name = trim($regs[3][$i]);
2426
                $check = trim($regs[0][$i]);
2427
                $value = trim($regs[10][$i]);
2428 View Code Duplication
                if (empty($value) and !empty($regs[13][$i])) {
2429
                    $value = $regs[13][$i];
2430
                }
2431 View Code Duplication
                if (empty($name) && !empty($regs[16][$i])) {
2432
                    $name = '@import';
2433
                    $value = trim($regs[16][$i]);
2434
                }
2435
                if (!empty($name)) {
2436
                    if (!$reduced OR in_array(strtolower($name), $wanted)) {
2437
                        if ($name == $check) {
2438
                            $attributes[strtolower($name)][] = strtolower($name);
2439
                        } else {
2440 View Code Duplication
                            if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
2441
                                $value = substr($value, 1, -1);
2442
                            }
2443
2444
                            if ($value == 'API.LMSGetValue(name') {
2445
                                $value = 'API.LMSGetValue(name)';
2446
                            }
2447
                            //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
2448
                            if (isset($explode_variables[$name])) {
2449
                                $value_modified = str_replace('&amp;', '&', $value);
2450
                                $value_array = explode('&', $value_modified);
2451
                                foreach ($value_array as $item) {
2452
                                    list($key, $item_value) = explode('=', $item);
2453
                                    if ($key == $explode_variables[$name]) {
2454
                                        $attributes[strtolower($name)][] = $item_value;
2455
                                    }
2456
                                }
2457
                            }
2458
                            $attributes[strtolower($name)][] = $value;
2459
                        }
2460
                    }
2461
                }
2462
            }
2463
        }
2464
2465
        return $attributes;
2466
    }
2467
2468
    /**
2469
     * Replace urls inside content html from a copy course
2470
     * @param string $content_html
2471
     * @param string $origin_course_code
2472
     * @param string $destination_course_directory
2473
     * @param string $origin_course_path_from_zip
2474
     * @param string $origin_course_info_path
2475
     *
2476
     * @return string	new content html with replaced urls or return false if content is not a string
2477
     */
2478
    static function replace_urls_inside_content_html_from_copy_course(
2479
        $content_html,
2480
        $origin_course_code,
2481
        $destination_course_directory,
2482
        $origin_course_path_from_zip = null,
2483
        $origin_course_info_path = null
2484
    ) {
2485
        if (empty($content_html)) {
2486
            return false;
2487
        }
2488
2489
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2490
        $orig_course_info = api_get_course_info($origin_course_code);
2491
2492
        // Course does not exist in the current DB probably this came from a zip file?
2493
        if (empty($orig_course_info)) {
2494
            if (!empty($origin_course_path_from_zip)) {
2495
                $orig_course_path = $origin_course_path_from_zip.'/';
2496
                $orig_course_info_path = $origin_course_info_path;
2497
            }
2498
        } else {
2499
            $orig_course_path = api_get_path(SYS_COURSE_PATH).$orig_course_info['path'] . '/';
2500
            $orig_course_info_path = $orig_course_info['path'];
2501
        }
2502
2503
        $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
2504
        $destination_course_info = api_get_course_info($destination_course_code);
2505
        $dest_course_path = api_get_path(SYS_COURSE_PATH) . $destination_course_directory . '/';
2506
        $dest_course_path_rel = api_get_path(REL_COURSE_PATH) . $destination_course_directory . '/';
2507
2508
        $user_id = api_get_user_id();
2509
2510
        if (!empty($orig_source_html)) {
2511
            foreach ($orig_source_html as $source) {
2512
2513
                // Get information about source url
2514
                $real_orig_url = $source[0]; // url
2515
                $scope_url = $source[1];   // scope (local, remote)
2516
                $type_url = $source[2]; // type (rel, abs, url)
2517
2518
                // Get path and query from origin url
2519
                $orig_parse_url = parse_url($real_orig_url);
2520
                $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
2521
                $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
2522
2523
                // Replace origin course code by destination course code from origin url query
2524
                $dest_url_query = '';
2525
2526
                if (!empty($real_orig_query)) {
2527
                    $dest_url_query = '?' . $real_orig_query;
2528
                    if (strpos($dest_url_query, $origin_course_code) !== false) {
2529
                        $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2530
                    }
2531
                }
2532
2533
                if ($scope_url == 'local') {
2534
                    if ($type_url == 'abs' || $type_url == 'rel') {
2535
                        $document_file = strstr($real_orig_path, 'document');
2536
2537
                        if (strpos($real_orig_path, $document_file) !== false) {
2538
                            $origin_filepath = $orig_course_path.$document_file;
2539
                            $destination_filepath = $dest_course_path.$document_file;
2540
2541
                            // copy origin file inside destination course
2542
                            if (file_exists($origin_filepath)) {
2543
                                $filepath_dir = dirname($destination_filepath);
2544
2545 View Code Duplication
                                if (!is_dir($filepath_dir)) {
2546
                                    $perm = api_get_permissions_for_new_directories();
2547
                                    $result = @mkdir($filepath_dir, $perm, true);
2548
                                    if ($result) {
2549
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
2550
2551
                                        //Add to item properties to the new folder
2552
                                        $doc_id = add_document(
2553
                                            $destination_course_info,
2554
                                            $filepath_to_add,
2555
                                            'folder',
2556
                                            0,
2557
                                            basename($filepath_to_add)
2558
                                        );
2559
                                        api_item_property_update(
2560
                                            $destination_course_info,
2561
                                            TOOL_DOCUMENT,
2562
                                            $doc_id,
2563
                                            'FolderCreated',
2564
                                            $user_id,
2565
                                            null,
2566
                                            null,
2567
                                            null,
2568
                                            null
2569
                                        );
2570
                                    }
2571
                                }
2572
2573 View Code Duplication
                                if (!file_exists($destination_filepath)) {
2574
                                    $result = @copy($origin_filepath, $destination_filepath);
2575
                                    if ($result) {
2576
                                        $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
2577
                                        $size = filesize($destination_filepath);
2578
2579
                                        // Add to item properties to the file
2580
                                        $doc_id = add_document(
2581
                                            $destination_course_info,
2582
                                            $filepath_to_add,
2583
                                            'file',
2584
                                            $size,
2585
                                            basename($filepath_to_add)
2586
                                        );
2587
                                        api_item_property_update(
2588
                                            $destination_course_info,
2589
                                            TOOL_DOCUMENT,
2590
                                            $doc_id,
2591
                                            'FolderCreated',
2592
                                            $user_id,
2593
                                            null,
2594
                                            null,
2595
                                            null,
2596
                                            null
2597
                                        );
2598
                                    }
2599
                                }
2600
                            }
2601
2602
                            // Replace origin course path by destination course path.
2603
                            if (strpos($content_html, $real_orig_url) !== false) {
2604
                                $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
2605
2606
                                //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
2607
                                // See BT#7780
2608
                                $destination_url = $dest_course_path_rel . $document_file . $dest_url_query;
2609
2610
                                // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
2611
                                if (strpos($real_orig_path, $origin_course_code) === false) {
2612
                                    $url_course_path = $real_orig_path;
2613
                                    $destination_url = $real_orig_path;
2614
                                }
2615
                                $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2616
                            }
2617
                        }
2618
2619
                        // replace origin course code by destination course code  from origin url
2620
                        if (strpos($real_orig_url, '?') === 0) {
2621
                            $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
2622
                            $content_html = str_replace($real_orig_url, $dest_url, $content_html);
2623
                        }
2624
                    }
2625
                }
2626
            }
2627
        }
2628
2629
        return $content_html;
2630
    }
2631
2632
    /**
2633
     * Replace urls inside content html when moving a file
2634
     * @todo this code is only called in document.php but is commented
2635
     * @param string     content html
2636
     * @param string     origin
2637
     * @param string     destination
2638
     * @return string    new content html with replaced urls or return false if content is not a string
2639
     */
2640
    function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
2641
    {
2642 View Code Duplication
        if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
2643
            $original = $original_path . $file_name;
2644
        } else {
2645
            $original = $original_path . '/' . $file_name;
2646
        }
2647 View Code Duplication
        if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
2648
            $destination = $destiny_path . $file_name;
2649
        } else {
2650
            $destination = $destiny_path . '/' . $file_name;
2651
        }
2652
        $original_count = count(explode('/', $original));
2653
        $destination_count = count(explode('/', $destination));
2654
        if ($original_count == $destination_count) {
2655
            //Nothing to change
2656
            return true;
2657
        }
2658
        if ($original_count > $destination_count) {
2659
            $mode = 'outside';
2660
        } else {
2661
            $mode = 'inside';
2662
        }
2663
        //We do not select the $original_path becayse the file was already moved
2664
        $content_html = file_get_contents($destiny_path . '/' . $file_name);
2665
        $destination_file = $destiny_path . '/' . $file_name;
2666
2667
        $pre_original = strstr($original_path, 'document');
2668
        $pre_destin = strstr($destiny_path, 'document');
2669
        $pre_original = substr($pre_original, 8, strlen($pre_original));
2670
        $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
2671
2672
        $levels = count(explode('/', $pre_destin)) - 1;
2673
        $link_to_add = '';
2674
        for ($i = 1; $i <= $levels; $i++) {
2675
            $link_to_add .= '../';
2676
        }
2677
2678
        if ($pre_original == '/') {
2679
            $pre_original = '';
2680
        }
2681
2682
        if ($pre_destin == '/') {
2683
            $pre_destin = '';
2684
        }
2685
2686
        if ($pre_original != '') {
2687
            $pre_original = '..' . $pre_original . '/';
2688
        }
2689
2690
        if ($pre_destin != '') {
2691
            $pre_destin = '..' . $pre_destin . '/';
2692
        }
2693
2694
        $levels = explode('/', $pre_original);
2695
        $count_pre_destination_levels = 0;
2696
        foreach ($levels as $item) {
2697
            if (!empty($item) && $item != '..') {
2698
                $count_pre_destination_levels++;
2699
            }
2700
        }
2701
        $count_pre_destination_levels--;
2702
        //$count_pre_destination_levels = count() - 3;
2703
        if ($count_pre_destination_levels == 0) {
2704
            $count_pre_destination_levels = 1;
2705
        }
2706
        //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
2707
        $pre_remove = '';
2708
        for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
2709
            $pre_remove .='..\/';
2710
        }
2711
2712
        $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
2713
2714
        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...
2715
2716
            // get information about source url
2717
            $real_orig_url = $source[0];   // url
2718
            $scope_url = $source[1];   // scope (local, remote)
2719
            $type_url = $source[2];   // tyle (rel, abs, url)
2720
            // Get path and query from origin url
2721
            $orig_parse_url = parse_url($real_orig_url);
2722
            $real_orig_path = $orig_parse_url['path'];
2723
            $real_orig_query = $orig_parse_url['query'];
2724
2725
            // Replace origin course code by destination course code from origin url query
2726
            /*
2727
              $dest_url_query = '';
2728
              if (!empty($real_orig_query)) {
2729
              $dest_url_query = '?'.$real_orig_query;
2730
              if (strpos($dest_url_query,$origin_course_code) !== false) {
2731
              $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
2732
              }
2733
              } */
2734
2735
            if ($scope_url == 'local') {
2736
                if ($type_url == 'abs' || $type_url == 'rel') {
2737
                    $document_file = strstr($real_orig_path, 'document');
2738
2739
                    if (strpos($real_orig_path, $document_file) !== false) {
2740
                        echo 'continue1';
2741
                        continue;
2742
                    } else {
2743
                        $real_orig_url_temp = '';
2744
                        if ($mode == 'inside') {
2745
                            $real_orig_url_temp = str_replace('../', '', $real_orig_url);
2746
                            $destination_url = $link_to_add . $real_orig_url_temp;
2747
                        } else {
2748
                            $real_orig_url_temp = $real_orig_url;
2749
2750
                            $destination_url = preg_replace("/" . $pre_remove . "/", '', $real_orig_url, 1);
2751
                        }
2752
                        if ($real_orig_url == $destination_url) {
2753
                            //echo 'continue2';
2754
                            continue;
2755
                        }
2756
                        $content_html = str_replace($real_orig_url, $destination_url, $content_html);
2757
                    }
2758
                } else {
2759
                    echo 'continue3';
2760
                    continue;
2761
                }
2762
            }
2763
        }
2764
        $return = file_put_contents($destination, $content_html);
2765
        return $return;
2766
    }
2767
2768
    /**
2769
     * @param int $document_id
2770
     * @param string $course_code
2771
     */
2772
    public static function export_to_pdf($document_id, $course_code)
2773
    {
2774
        $course_data = api_get_course_info($course_code);
2775
        $document_data = self::get_document_data_by_id($document_id, $course_code);
2776
        $file_path = api_get_path(SYS_COURSE_PATH) . $course_data['path'] . '/document' . $document_data['path'];
2777
        $pdf = new PDF('A4-L', 'L');
2778
        $pdf->html_to_pdf($file_path, $document_data['title'], $course_code);
2779
    }
2780
2781
    /**
2782
     * Uploads a document
2783
     *
2784
     * @param array $files the $_FILES variable
2785
     * @param string $path
2786
     * @param string $title
2787
     * @param string $comment
2788
     * @param int $unzip unzip or not the file
2789
     * @param string $if_exists overwrite, rename or warn (default)
2790
     * @param bool $index_document index document (search xapian module)
2791
     * @param bool $show_output print html messages
2792
     * @return array|bool
2793
     */
2794
    public static function upload_document(
2795
        $files,
2796
        $path,
2797
        $title = null,
2798
        $comment = null,
2799
        $unzip = 0,
2800
        $if_exists = null,
2801
        $index_document = false,
2802
        $show_output = false,
2803
        $fileKey = 'file'
2804
    ) {
2805
        $course_info = api_get_course_info();
2806
        $sessionId = api_get_session_id();
2807
        $course_dir = $course_info['path'] . '/document';
2808
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
2809
        $base_work_dir = $sys_course_path . $course_dir;
2810
2811
        if (isset($files[$fileKey])) {
2812
            $upload_ok = process_uploaded_file($files[$fileKey], $show_output);
2813
2814
            if ($upload_ok) {
2815
                // File got on the server without problems, now process it
2816
                $new_path = handle_uploaded_document(
2817
                    $course_info,
2818
                    $files[$fileKey],
2819
                    $base_work_dir,
2820
                    $path,
2821
                    api_get_user_id(),
2822
                    api_get_group_id(),
2823
                    null,
2824
                    $unzip,
2825
                    $if_exists,
2826
                    $show_output,
2827
                    false,
2828
                    null,
2829
                    $sessionId
2830
                );
2831
2832
                if ($new_path) {
2833
                    $documentId = DocumentManager::get_document_id(
2834
                        $course_info,
2835
                        $new_path,
0 ignored issues
show
Bug introduced by
It seems like $new_path defined by handle_uploaded_document...alse, null, $sessionId) on line 2816 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...
2836
                        $sessionId
2837
                    );
2838
2839
                    if (!empty($documentId)) {
2840
                        $table_document = Database::get_course_table(TABLE_DOCUMENT);
2841
                        $params = array();
2842
                        /*if ($if_exists == 'rename') {
2843
                            // Remove prefix
2844
                            $suffix = DocumentManager::getDocumentSuffix(
2845
                                $course_info,
2846
                                $sessionId,
2847
                                api_get_group_id()
2848
                            );
2849
                            $new_path = basename($new_path);
2850
                            $new_path = str_replace($suffix, '', $new_path);
2851
                            error_log('renamed');
2852
                            error_log($new_path);
2853
                            $params['title'] = get_document_title($new_path);
2854
                        } else {
2855
                            if (!empty($title)) {
2856
                                $params['title'] = get_document_title($title);
2857
                            } else {
2858
                                $params['title'] = get_document_title($files['file']['name']);
2859
                            }
2860
                        }*/
2861
2862
                        if (!empty($comment)) {
2863
                            $params['comment'] = trim($comment);
2864
                        }
2865
2866
                        Database::update(
2867
                            $table_document,
2868
                            $params,
2869
                            array(
2870
                                'id = ? AND c_id = ? ' => array(
2871
                                    $documentId,
2872
                                    $course_info['real_id']
2873
                                )
2874
                            )
2875
                        );
2876
                    }
2877
2878
                    // Showing message when sending zip files
2879
                    if ($new_path === true && $unzip == 1 && $show_output) {
2880
                        Display::display_confirmation_message(
2881
                            get_lang('UplUploadSucceeded') . '<br />',
2882
                            false
2883
                        );
2884
                    }
2885
2886
                    if ($index_document) {
2887
                        self::index_document(
2888
                            $documentId,
2889
                            $course_info['code'],
2890
                            null,
2891
                            $_POST['language'],
2892
                            $_REQUEST,
2893
                            $if_exists
2894
                        );
2895
                    }
2896
2897 View Code Duplication
                    if (!empty($documentId) && is_numeric($documentId)) {
2898
                        $documentData = self::get_document_data_by_id(
2899
                            $documentId,
2900
                            $course_info['code'],
2901
                            false,
2902
                            $sessionId
2903
                        );
2904
2905
                        return $documentData;
2906
                    }
2907
                }
2908
            }
2909
        }
2910
2911
        return false;
2912
    }
2913
2914
    /**
2915
     * Obtains the text inside the file with the right parser
2916
     */
2917
    public static function get_text_content($doc_path, $doc_mime)
2918
    {
2919
        // TODO: review w$ compatibility
2920
        // Use usual exec output lines array to store stdout instead of a temp file
2921
        // because we need to store it at RAM anyway before index on ChamiloIndexer object
2922
        $ret_val = null;
2923
        switch ($doc_mime) {
2924
            case 'text/plain':
2925
                $handle = fopen($doc_path, 'r');
2926
                $output = array(fread($handle, filesize($doc_path)));
2927
                fclose($handle);
2928
                break;
2929
            case 'application/pdf':
2930
                exec("pdftotext $doc_path -", $output, $ret_val);
2931
                break;
2932
            case 'application/postscript':
2933
                $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
2934
                exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
2935
                if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
2936
                    return false;
2937
                }
2938
                exec("pdftotext $temp_file -", $output, $ret_val);
2939
                unlink($temp_file);
2940
                break;
2941
            case 'application/msword':
2942
                exec("catdoc $doc_path", $output, $ret_val);
2943
                break;
2944
            case 'text/html':
2945
                exec("html2text $doc_path", $output, $ret_val);
2946
                break;
2947
            case 'text/rtf':
2948
                // Note: correct handling of code pages in unrtf
2949
                // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
2950
                exec("unrtf --text $doc_path", $output, $ret_val);
2951
                if ($ret_val == 127) { // command not found
2952
                    return false;
2953
                }
2954
                // Avoid index unrtf comments
2955
                if (is_array($output) && count($output) > 1) {
2956
                    $parsed_output = array();
2957
                    foreach ($output as & $line) {
2958
                        if (!preg_match('/^###/', $line, $matches)) {
2959
                            if (!empty($line)) {
2960
                                $parsed_output[] = $line;
2961
                            }
2962
                        }
2963
                    }
2964
                    $output = $parsed_output;
2965
                }
2966
                break;
2967
            case 'application/vnd.ms-powerpoint':
2968
                exec("catppt $doc_path", $output, $ret_val);
2969
                break;
2970
            case 'application/vnd.ms-excel':
2971
                exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
2972
                break;
2973
        }
2974
2975
        $content = '';
2976
        if (!is_null($ret_val)) {
2977
            if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
2978
                return false;
2979
            }
2980
        }
2981
        if (isset($output)) {
2982
            foreach ($output as & $line) {
2983
                $content .= $line . "\n";
2984
            }
2985
            return $content;
2986
        } else {
2987
            return false;
2988
        }
2989
    }
2990
2991
    /**
2992
     * Calculates the total size of all documents in a course
2993
     *
2994
     * @author Bert vanderkimpen
2995
     * @param  int $course_id
2996
     * @param  int $group_id (to calculate group document space)
2997
     * @param  int $session_id
2998
     *
2999
     * @return int total size
3000
     */
3001
    static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
3002
    {
3003
        $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3004
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
3005
3006
        if (isset($course_id)) {
3007
            $course_id = intval($course_id);
3008
        } else {
3009
            $course_id = api_get_course_int_id();
3010
        }
3011
3012
        $group_condition = null;
3013
        if (isset($group_id)) {
3014
            $group_id = intval($group_id);
3015
            $group_condition = " AND props.to_group_id='" . $group_id . "' ";
3016
        }
3017
3018
        $session_condition = null;
3019
        if (isset($session_id)) {
3020
            $session_id = intval($session_id);
3021
            $session_condition = " AND props.session_id='" . $session_id . "' ";
3022
        }
3023
3024
        $sql = "SELECT SUM(size)
3025
                FROM $TABLE_ITEMPROPERTY AS props
3026
                INNER JOIN $TABLE_DOCUMENT AS docs
3027
                ON (docs.id = props.ref AND props.c_id = docs.c_id)
3028
                WHERE
3029
                    props.c_id 	= $course_id AND
3030
                    docs.c_id 	= $course_id AND
3031
                    props.tool 	= '" . TOOL_DOCUMENT . "' AND
3032
                    props.visibility <> 2
3033
                    $group_condition
3034
                    $session_condition
3035
                ";
3036
        $result = Database::query($sql);
3037
3038
        if ($result && Database::num_rows($result) != 0) {
3039
            $row = Database::fetch_row($result);
3040
            return $row[0];
3041
        } else {
3042
            return 0;
3043
        }
3044
    }
3045
3046
    /**
3047
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3048
     */
3049
    static function display_quota($course_quota, $already_consumed_space)
3050
    {
3051
        $course_quota_m = round($course_quota / 1048576);
3052
        $already_consumed_space_m = round($already_consumed_space / 1048576);
3053
3054
        $message = get_lang('MaximumAllowedQuota') . ' <strong>' . $course_quota_m . ' megabyte</strong>.<br />';
3055
        $message .= get_lang('CourseCurrentlyUses') . ' <strong>' . $already_consumed_space_m . ' megabyte</strong>.<br />';
3056
3057
        $percentage = round(($already_consumed_space / $course_quota * 100), 1);
3058
3059
        $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
3060
3061
        // Decide where to place percentage in graph
3062
        if ($percentage >= 50) {
3063
            $text_in_filled = '&nbsp;' . $other_percentage . '%';
3064
            $text_in_unfilled = '';
3065
        } else {
3066
            $text_in_unfilled = '&nbsp;' . $other_percentage . '%';
3067
            $text_in_filled = '';
3068
        }
3069
3070
        // Decide the background colour of the graph
3071
        if ($percentage < 65) {
3072
            $colour = '#00BB00';        // Safe - green
3073
        } elseif ($percentage < 90) {
3074
            $colour = '#ffd400';        // Filling up - yelloworange
3075
        } else {
3076
            $colour = '#DD0000';        // Full - red
3077
        }
3078
3079
        // This is used for the table width: a table of only 100 pixels looks too small
3080
        $visual_percentage = 4 * $percentage;
3081
        $visual_other_percentage = 4 * $other_percentage;
3082
3083
        $message .= get_lang('PercentageQuotaInUse') . ': <strong>' . $percentage . '%</strong>.<br />' .
3084
            get_lang('PercentageQuotaFree') . ': <strong>' . $other_percentage . '%</strong>.<br />';
3085
3086
        $show_percentage = '&nbsp;' . $percentage . '%';
3087
        $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">' .
3088
            '<div style="width:' . $percentage . '%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>' .
3089
            '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">' . $show_percentage . '</span></div>';
3090
        echo $message;
3091
    }
3092
3093
    /**
3094
     * Display the document quota in a simple way
3095
     *
3096
     *  Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
3097
     */
3098
    static function display_simple_quota($course_quota, $already_consumed_space)
3099
    {
3100
        $course_quota_m = round($course_quota / 1048576);
3101
        $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
3102
        $percentage = $already_consumed_space / $course_quota * 100;
3103
        $percentage = round($percentage, 1);
3104
        $message = get_lang('YouAreCurrentlyUsingXOfYourX');
3105
        $message = sprintf($message, $already_consumed_space_m, $percentage . '%', $course_quota_m . ' ');
3106
        echo Display::div($message, array('id' => 'document_quota'));
3107
    }
3108
3109
    /**
3110
     * Checks if there is enough place to add a file on a directory
3111
     * on the base of a maximum directory size allowed
3112
     *
3113
     * @author Bert Vanderkimpen
3114
     * @param  int $file_size size of the file in byte
3115
     * @param  int $max_dir_space maximum size
3116
     * @return boolean true if there is enough space, false otherwise
3117
     *
3118
     * @see enough_space() uses  documents_total_space() function
3119
     */
3120
    static function enough_space($file_size, $max_dir_space) {
3121
        if ($max_dir_space) {
3122
            $already_filled_space = self::documents_total_space();
3123
            if (($file_size + $already_filled_space) > $max_dir_space) {
3124
                return false;
3125
            }
3126
        }
3127
        return true;
3128
    }
3129
3130
    /**
3131
     * @param array $params count, url, extension
3132
     * @return string
3133
     */
3134
    static function generate_jplayer_jquery($params = array())
3135
    {
3136
        $js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
3137
3138
        $js = '
3139
            $("#jquery_jplayer_' . $params['count'] . '").jPlayer({
3140
                ready: function() {
3141
                    $(this).jPlayer("setMedia", {
3142
                        ' . $params['extension'] . ' : "' . $params['url'] . '"
3143
                    });
3144
                },
3145
                play: function() { // To avoid both jPlayers playing together.
3146
                    $(this).jPlayer("pauseOthers");
3147
                },
3148
                //errorAlerts: true,
3149
                //warningAlerts: true,
3150
                swfPath: "' . $js_path . 'jquery-jplayer/jplayer/",
3151
                //supplied: "m4a, oga, mp3, ogg, wav",
3152
                supplied: "' . $params['extension'] . '",
3153
                wmode: "window",
3154
                solution: "flash, html",  // Do not change this setting
3155
                cssSelectorAncestor: "#jp_container_' . $params['count'] . '",
3156
            });  	 ' . "\n\n";
3157
3158
        return $js;
3159
    }
3160
3161
    /**
3162
     *
3163
     * Shows a play icon next to the document title in the document list
3164
     * @param int
3165
     * @param string
3166
     * @return string	html content
3167
     */
3168
    static function generate_media_preview($i, $type = 'simple')
3169
    {
3170
        $i = intval($i);
3171
3172
        $extra_controls = $progress = '';
3173
        if ($type == 'advanced') {
3174
            $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
3175
                                <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
3176
                                <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
3177
            $progress = '<div class="jp-progress">
3178
                                <div class="jp-seek-bar">
3179
                                    <div class="jp-play-bar"></div>
3180
                                </div>
3181
                            </div>';
3182
        }
3183
3184
        //Shows only the play button
3185
        $html = '<div id="jquery_jplayer_' . $i . '" class="jp-jplayer"></div>
3186
                <div id="jp_container_' . $i . '" class="jp-audio">
3187
                    <div class="jp-type-single">
3188
                        <div class="jp-gui jp-interface">
3189
                            <ul class="jp-controls">
3190
                                <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
3191
                                <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
3192
                                ' . $extra_controls . '
3193
                            </ul>
3194
                            ' . $progress . '
3195
                        </div>
3196
                    </div>
3197
                </div>';
3198
        //<div id="jplayer_inspector_'.$i.'"></div>
3199
        return $html;
3200
    }
3201
3202
    /**
3203
     * @param array $document_data
3204
     * @return string
3205
     */
3206
    public static function generate_video_preview($document_data = array())
3207
    {
3208
        //<button class="jp-video-play-icon" role="button" tabindex="0">play</button>
3209
        $html = '
3210
        <div id="jp_container_1" class="jp-video" role="application" aria-label="media player">
3211
            <div class="jp-type-single">
3212
                <div id="jquery_jplayer_1" class="jp-jplayer"></div>
3213
                <div class="jp-gui">
3214
                    <div class="jp-video-play">
3215
                    </div>
3216
                    <div class="jp-interface">
3217
                        <div class="jp-progress">
3218
                            <div class="jp-seek-bar">
3219
                                <div class="jp-play-bar"></div>
3220
                            </div>
3221
                        </div>
3222
                        <div class="jp-current-time" role="timer" aria-label="time">&nbsp;</div>
3223
                        <div class="jp-duration" role="timer" aria-label="duration">&nbsp;</div>
3224
                        <div class="jp-controls-holder">
3225
                          <div class="jp-controls">
3226
                            <button class="jp-play" role="button" tabindex="0">play</button>
3227
                            <button class="jp-stop" role="button" tabindex="0">stop</button>
3228
                          </div>
3229
                          <div class="jp-volume-controls">
3230
                            <button class="jp-mute" role="button" tabindex="0">mute</button>
3231
                            <button class="jp-volume-max" role="button" tabindex="0">max volume</button>
3232
                            <div class="jp-volume-bar">
3233
                                <div class="jp-volume-bar-value"></div>
3234
                            </div>
3235
                          </div>
3236
                          <div class="jp-toggles">
3237
                            <button class="jp-repeat" role="button" tabindex="0">repeat</button>
3238
                            <button class="jp-full-screen" role="button" tabindex="0">full screen</button>
3239
                          </div>
3240
                        </div>
3241
                        <div class="jp-details">
3242
                          <div class="jp-title" aria-label="title">&nbsp;</div>
3243
                        </div>
3244
                    </div>
3245
                </div>
3246
                <div class="jp-no-solution">
3247
                    <span>' . get_lang('UpdateRequire') . '</span>
3248
                    ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile") . '
3249
                </div>
3250
            </div>
3251
        </div>';
3252
        return $html;
3253
    }
3254
3255
    /**
3256
     * @param array $course_info
3257
     * @param bool $lp_id
3258
     * @param string $target
3259
     * @param int $session_id
3260
     * @param bool $add_move_button
3261
     * @param string $filter_by_folder
3262
     * @param string $overwrite_url
3263
     * @param bool $showInvisibleFiles
3264
     * @param bool $showOnlyFolders
3265
     * @param int $folderId
3266
     * @return string
3267
     */
3268
    public static function get_document_preview(
3269
        $course_info,
3270
        $lp_id = false,
3271
        $target = '',
3272
        $session_id = 0,
3273
        $add_move_button = false,
3274
        $filter_by_folder = null,
3275
        $overwrite_url = null,
3276
        $showInvisibleFiles = false,
3277
        $showOnlyFolders = false,
3278
        $folderId = false
3279
    ) {
3280
        if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
3281
            return '';
3282
        }
3283
3284
        $overwrite_url = Security::remove_XSS($overwrite_url);
3285
        $user_id = api_get_user_id();
3286
        $user_in_course = false;
3287
3288
        if (api_is_platform_admin()) {
3289
            $user_in_course = true;
3290
        }
3291
3292
        if (!$user_in_course) {
3293
            if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
3294
                $user_in_course = true;
3295
            }
3296
        }
3297
3298
        // Condition for the session
3299
        $session_id = intval($session_id);
3300
3301
        if (!$user_in_course) {
3302
            if (empty($session_id)) {
3303
                if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
3304
                    $user_in_course = true;
3305
                }
3306
                // Check if course is open then we can consider that the student is registered to the course
3307
                if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
3308
                    $user_in_course = true;
3309
                }
3310 View Code Duplication
            } else {
3311
                $user_status = SessionManager::get_user_status_in_course_session(
3312
                    $user_id,
3313
                    $course_info['real_id'],
3314
                    $session_id
3315
                );
3316
                //is true if is an student, course session teacher or coach
3317
                if (in_array($user_status, array('0', '2', '6'))) {
3318
                    $user_in_course = true;
3319
                }
3320
            }
3321
        }
3322
3323
        $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
3324
        $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
3325
        $condition_session = " AND (last.session_id = '$session_id' OR last.session_id = '0' OR last.session_id IS NULL)";
3326
3327
        $add_folder_filter = null;
3328
        if (!empty($filter_by_folder)) {
3329
            $add_folder_filter = " AND docs.path LIKE '" . Database::escape_string($filter_by_folder) . "%'";
3330
        }
3331
3332
        // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
3333
        $lp_visibility_condition = null;
3334
        if ($lp_id) {
3335
            // $lp_visibility_condition = " OR filetype='folder'";
3336
            if ($showInvisibleFiles) {
3337
                $lp_visibility_condition .= ' OR last.visibility = 0';
3338
            }
3339
        }
3340
3341
        $showOnlyFoldersCondition = null;
3342
        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...
3343
            //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
3344
        }
3345
3346
        $folderCondition = " AND docs.path LIKE '/%' ";
3347
3348
        if (!api_is_allowed_to_edit()) {
3349
            $protectedFolders = self::getProtectedFolderFromStudent();
3350
            foreach ($protectedFolders as $folder) {
3351
                $folderCondition .= " AND docs.path NOT LIKE '$folder' ";
3352
            }
3353
        }
3354
3355
        $parentData = [];
3356
        if ($folderId !== false) {
3357
            $parentData = self::get_document_data_by_id($folderId, $course_info['code']);
3358
            if (!empty($parentData)) {
3359
                $cleanedPath = $parentData['path'];
3360
                $num = substr_count($cleanedPath, '/');
3361
3362
                $notLikeCondition = null;
3363
                for ($i = 1; $i <= $num; $i++) {
3364
                    $repeat = str_repeat('/%', $i+1);
3365
                    $notLikeCondition .= " AND docs.path NOT LIKE '".Database::escape_string($cleanedPath.$repeat)."' ";
3366
                }
3367
3368
                $folderCondition = " AND
3369
                    docs.id <> $folderId AND
3370
                    docs.path LIKE '".$cleanedPath."/%'
3371
                    $notLikeCondition
3372
                ";
3373
            } else {
3374
                $folderCondition = " AND
3375
                docs.filetype = 'file' ";
3376
            }
3377
        }
3378
3379
        $levelCondition = null;
3380
        if ($folderId === false) {
3381
            $levelCondition = " AND docs.path NOT LIKE'/%/%'";
3382
        }
3383
3384
        $sql = "SELECT last.visibility, docs.*
3385
                FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
3386
                ON (docs.id = last.ref AND docs.c_id = last.c_id)
3387
                WHERE
3388
                    docs.path NOT LIKE '%_DELETED_%' AND
3389
                    last.tool = '" . TOOL_DOCUMENT . "' $condition_session AND
3390
                    (last.visibility = '1' $lp_visibility_condition) AND
3391
                    last.visibility <> 2 AND
3392
                    docs.c_id = {$course_info['real_id']} AND
3393
                    last.c_id = {$course_info['real_id']}
3394
                    $showOnlyFoldersCondition
3395
                    $folderCondition
3396
                    $levelCondition
3397
                    $add_folder_filter
3398
                ORDER BY docs.filetype DESC, docs.title ASC";
3399
3400
        $res_doc = Database::query($sql);
3401
        $resources = Database::store_result($res_doc, 'ASSOC');
3402
3403
        $return = '';
3404
        if ($lp_id) {
3405
            if ($folderId === false) {
3406
                $return .= '<div class="lp_resource_element">';
3407
                $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
3408
                $return .= Display::url(
3409
                    get_lang('NewDocument'),
3410
                    api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
3411
                );
3412
                $return .= '</div>';
3413
            }
3414
        } else {
3415
            $return .= Display::div(
3416
                Display::url(
3417
                    Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
3418
                    ' javascript:void(0);',
3419
                    array('id' => 'close_div_' . $course_info['real_id'] . '_' . $session_id, 'class' => 'close_div')
3420
                ),
3421
                array('style' => 'position:absolute;right:10px')
3422
            );
3423
        }
3424
3425
        // If you want to debug it, I advise you to do "echo" on the eval statements.
3426
        $newResources = array();
3427
3428
        if (!empty($resources) && $user_in_course) {
3429
            foreach ($resources as $resource) {
3430
                $is_visible = self::is_visible_by_id(
3431
                    $resource['id'],
3432
                    $course_info,
3433
                    $session_id,
3434
                    api_get_user_id()
3435
                );
3436
3437
                if (!$is_visible) {
3438
                    continue;
3439
                }
3440
                $newResources[] = $resource;
3441
            }
3442
        }
3443
3444
        $label = get_lang('Documents');
3445
3446
        $documents = [];
3447
        if ($folderId === false) {
3448
            $documents[$label] = array(
3449
                'id' => 0,
3450
                'files' => $newResources
3451
            );
3452
        } else {
3453
            if (!empty($parentData)) {
3454
                $documents[$parentData['title']] = array(
3455
                    'id' => intval($folderId),
3456
                    'files' => $newResources
3457
                );
3458
            }
3459
        }
3460
3461
        $write_result = self::write_resources_tree(
3462
            $course_info,
3463
            $session_id,
3464
            $documents,
3465
            $lp_id,
3466
            $target,
3467
            $add_move_button,
3468
            $overwrite_url,
3469
            $folderId
3470
        );
3471
3472
        $return .= $write_result;
3473
        if ($lp_id == false) {
3474
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
3475
            $return .= "<script>
3476
            $('.doc_folder').click(function() {
3477
                var realId = this.id;
3478
                var my_id = this.id.split('_')[2];
3479
                var tempId = 'temp_'+my_id;
3480
                $('#res_'+my_id).show();
3481
3482
                var tempDiv = $('#'+realId).find('#'+tempId);
3483
                if (tempDiv.length == 0) {
3484
                    $.ajax({
3485
                        async: false,
3486
                        type: 'GET',
3487
                        url:  '".$url."',
3488
                        data: 'folder_id='+my_id,
3489
                        success: function(data) {
3490
                            $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
3491
                        }
3492
                    });
3493
                }
3494
            });
3495
3496
            $('.close_div').click(function() {
3497
                var course_id = this.id.split('_')[2];
3498
                var session_id = this.id.split('_')[3];
3499
                $('#document_result_'+course_id+'_'+session_id).hide();
3500
                $('.lp_resource').remove();
3501
                $('.document_preview_container').html('');
3502
            });
3503
3504
            </script>";
3505 View Code Duplication
        } else {
3506
            //For LPs
3507
            $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
3508
            $return .= "<script>
3509
3510
            function testResources(id, img) {
3511
                var numericId = id.split('_')[1];
3512
                var parentId = 'doc_id_'+numericId;
3513
                var tempId = 'temp_'+numericId;
3514
                var image = $('#'+img);
3515
3516
                if (image.hasClass('open')) {
3517
                    image.removeClass('open');
3518
                    image.attr('src', '" . Display::returnIconPath('nolines_plus.gif')."');
3519
                    $('#'+id).show();
3520
                    $('#'+tempId).hide();
3521
                } else {
3522
                    image.addClass('open');
3523
                    image.attr('src', '" . Display::returnIconPath('nolines_minus.gif') . "');
3524
                    $('#'+id).hide();
3525
                    $('#'+tempId).show();
3526
3527
                    var tempDiv = $('#'+parentId).find('#'+tempId);
3528
                    if (tempDiv.length == 0) {
3529
                        $.ajax({
3530
                            type: 'GET',
3531
                            async: false,
3532
                            url:  '".$url."',
3533
                            data: 'folder_id='+numericId,
3534
                            success: function(data) {
3535
                                tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
3536
                            }
3537
                        });
3538
                    }
3539
                }
3540
            }
3541
            </script>";
3542
        }
3543
3544
        if (!$user_in_course) {
3545
            $return = '';
3546
        }
3547
3548
        return $return;
3549
    }
3550
3551
    /**
3552
     * @param array $course_info
3553
     * @param int $session_id
3554
     * @param array $resource
3555
     * @param int $lp_id
3556
     * @param bool $add_move_button
3557
     * @param string $target
3558
     * @param string $overwrite_url
3559
     * @return null|string
3560
     */
3561
    private static function parseFile(
3562
        $course_info,
3563
        $session_id,
3564
        $resource,
3565
        $lp_id,
3566
        $add_move_button,
3567
        $target,
3568
        $overwrite_url
3569
    ) {
3570
        $img_sys_path = api_get_path(SYS_CODE_PATH) . 'img/';
3571
        $web_code_path = api_get_path(WEB_CODE_PATH);
3572
3573
        $documentId = $resource['id'];
3574
        $path = $resource['path'];
3575
3576
        if (empty($path)) {
3577
            $num = 0;
3578
        } else {
3579
            $num = substr_count($path, '/') - 1;
3580
        }
3581
3582
        // It's a file.
3583
        $icon = choose_image($path);
3584
        $position = strrpos($icon, '.');
3585
        $icon = substr($icon, 0, $position) . '_small.gif';
3586
        $my_file_title = $resource['title'];
3587
        $visibility = $resource['visibility'];
3588
3589
        // If title is empty we try to use the path
3590
        if (empty($my_file_title)) {
3591
            $my_file_title = basename($path);
3592
        }
3593
3594
        // Show the "image name" not the filename of the image.
3595
        if ($lp_id) {
3596
            // LP URL
3597
            $url = api_get_path(WEB_CODE_PATH).'newscorm/lp_controller.php?'.api_get_cidreq().'&amp;action=add_item&amp;type=' . TOOL_DOCUMENT . '&amp;file=' . $documentId . '&amp;lp_id=' . $lp_id;
3598 View Code Duplication
            if (!empty($overwrite_url)) {
3599
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId.'';
3600
            }
3601
        } else {
3602
            // Direct document URL
3603
            $url = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
3604 View Code Duplication
            if (!empty($overwrite_url)) {
3605
                $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId;
3606
            }
3607
        }
3608
3609
        $img = Display::returnIconPath($icon);
3610
        if (!file_exists($img_sys_path . $icon)) {
3611
            $img = Display::returnIconPath('default_small.gif');
3612
        }
3613
3614
        $link = Display::url(
3615
            '<img alt="" src="' . $img . '" title="" />&nbsp;' . $my_file_title, $url,
3616
            array('target' => $target)
3617
        );
3618
3619
        $visibilityClass = null;
3620
        if ($visibility == 0) {
3621
            $visibilityClass = ' invisible ';
3622
        }
3623
        $return = null;
3624
3625
        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...
3626
            $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3627
        } else {
3628
            $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
3629
        }
3630
3631
        $return .= '<div class="item_data" style="margin-left:' . ($num  * 18) . 'px;margin-right:5px;">';
3632
3633 View Code Duplication
        if ($add_move_button) {
3634
            $return .= '<a class="moved" href="#">';
3635
            $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
3636
            $return .= '</a> ';
3637
        }
3638
        $return .= $link;
3639
        $return .= '</div></li>';
3640
3641
        return $return;
3642
    }
3643
3644
    /**
3645
     * @param int $folderId
3646
     * @param array $resource
3647
     * @param int $lp_id
3648
     * @return null|string
3649
     */
3650
    private static function parseFolder($folderId, $resource, $lp_id)
3651
    {
3652
        $title = isset($resource['title']) ? $resource['title'] : null;
3653
        $path = isset($resource['path']) ? $resource['path'] : null;
3654
3655
        if (empty($path)) {
3656
            $num = 0;
3657
        } else {
3658
            $num = substr_count($path, '/');
3659
        }
3660
3661
        // It's a folder.
3662
        //hide some folders
3663
        if (in_array($path,
3664
            array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
3665
            return null;
3666
        } elseif (preg_match('/_groupdocs/', $path)) {
3667
            return null;
3668
        } elseif (preg_match('/sf_user_/', $path)) {
3669
            return null;
3670
        } elseif (preg_match('/shared_folder_session_/', $path)) {
3671
            return null;
3672
        }
3673
3674
        //trad some titles
3675
        /*
3676
        if ($key == 'images') {
3677
            $key = get_lang('Images');
3678
        } elseif ($key == 'gallery') {
3679
            $key = get_lang('Gallery');
3680
        } elseif ($key == 'flash') {
3681
            $key = get_lang('Flash');
3682
        } elseif ($key == 'audio') {
3683
            $key = get_lang('Audio');
3684
        } elseif ($key == 'video') {
3685
            $key = get_lang('Video');
3686
        }*/
3687
3688
        $onclick = '';
3689
3690
        // if in LP, hidden folder are displayed in grey
3691
        $folder_class_hidden = "";
3692
        if ($lp_id) {
3693
            if (isset($resource['visible']) && $resource['visible'] == 0) {
3694
                $folder_class_hidden = "doc_folder_hidden"; // in base.css
3695
            }
3696
            $onclick = 'onclick="javascript: testResources(\'res_' . $resource['id'] . '\',\'img_' . $resource['id'] . '\')"';
3697
        }
3698
        $return = null;
3699
3700
        if (empty($path)) {
3701
            $return = '<ul class="lp_resource">';
3702
        }
3703
3704
        $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_' . $resource['id'] . '"  style="margin-left:' . ($num * 18) . 'px; ">';
3705
3706
        $image = Display::returnIconPath('nolines_plus.gif');
3707
        if (empty($path)) {
3708
            $image = Display::returnIconPath('nolines_minus.gif');
3709
        }
3710
        $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'] . '" '.$onclick.'>';
3711
        $return .= Display::returnIconPath('lp_folder.gif').'&nbsp;';
3712
        $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
3713
        $return .= '</li>';
3714
3715
        if (empty($path)) {
3716
            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...
3717
                $return .= '<div id="res_' . $resource['id'] . '" >';
3718
            } else {
3719
                $return .= '<div id="res_' . $resource['id'] . '" style="display: none;" >';
3720
            }
3721
        }
3722
3723
        return $return;
3724
    }
3725
3726
    /**
3727
     * Generate and return an HTML list of resources based on a given array.
3728
     * This list is used to show the course creator a list of available resources to choose from
3729
     * when creating a learning path.
3730
     * @param array $course_info
3731
     * @param int $session_id
3732
     * @param array $documents
3733
     * @param bool $lp_id
3734
     * @param string $target
3735
     * @param bool $add_move_button
3736
     * @param string $overwrite_url
3737
     * @param int $folderId
3738
     *
3739
     * @return string
3740
     */
3741
    public static function write_resources_tree(
3742
        $course_info,
3743
        $session_id,
3744
        $documents,
3745
        $lp_id = false,
3746
        $target = '',
3747
        $add_move_button = false,
3748
        $overwrite_url = null,
3749
        $folderId = false
3750
    ) {
3751
        $return = '';
3752
3753
        if (!empty($documents)) {
3754
            foreach ($documents as $key => $resource) {
3755
                if (isset($resource['id']) && is_int($resource['id'])) {
3756
                    $mainFolderResource = array(
3757
                        'id' => $resource['id'],
3758
                        'title' => $key,
3759
                    );
3760
3761
                    if ($folderId === false) {
3762
                        $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
3763
                    }
3764
3765
                    if (isset($resource['files'])) {
3766
                        $return .= self::write_resources_tree(
3767
                            $course_info,
3768
                            $session_id,
3769
                            $resource['files'],
3770
                            $lp_id,
3771
                            $target,
3772
                            $add_move_button,
3773
                            $overwrite_url
3774
                        );
3775
                    }
3776
                    $return .= '</div>';
3777
                    $return .= '</ul>';
3778
                } else {
3779
                    if ($resource['filetype'] == 'folder') {
3780
                        $return .= self::parseFolder($folderId, $resource, $lp_id);
0 ignored issues
show
Bug introduced by
It seems like $folderId defined by parameter $folderId on line 3749 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...
3781
                    } else {
3782
                        $return .= self::parseFile(
3783
                            $course_info,
3784
                            $session_id,
3785
                            $resource,
3786
                            $lp_id,
3787
                            $add_move_button,
3788
                            $target,
3789
                            $overwrite_url
3790
                        );
3791
                    }
3792
                }
3793
            }
3794
        }
3795
3796
        return $return;
3797
    }
3798
3799
    /**
3800
     * @param int $doc_id
3801
     * @param string $course_code
3802
     * @param int $session_id
3803
     * @param int $user_id
3804
     * @param int $groupId
3805
     * @return bool
3806
     */
3807
    public static function check_visibility_tree(
3808
        $doc_id,
3809
        $course_code,
3810
        $session_id,
3811
        $user_id,
3812
        $groupId = 0
3813
    ) {
3814
        $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
3815
        if ($session_id != 0 && !$document_data) {
3816
            $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
3817
        }
3818
3819
        if (!empty($document_data)) {
3820
            // If admin or course teacher, allow anyway
3821
            if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
3822
                return true;
3823
            }
3824
            $course_info = api_get_course_info($course_code);
3825
            if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
3826
                if (!empty($groupId)) {
3827
                    return true;
3828
                }
3829
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3830
                return $visible;
3831
            } else {
3832
                $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
3833
3834
                if (!$visible) {
3835
                    return false;
3836
                } else {
3837
                    return self::check_visibility_tree(
3838
                        $document_data['parent_id'],
3839
                        $course_code,
3840
                        $session_id,
3841
                        $user_id,
3842
                        $groupId
3843
                    );
3844
                }
3845
            }
3846
        } else {
3847
            return false;
3848
        }
3849
    }
3850
3851
    /**
3852
     * Index a given document.
3853
     * @param   int     Document ID inside its corresponding course
3854
     * @param   string  Course code
3855
     * @param   int     Session ID (not used yet)
3856
     * @param   string  Language of document's content (defaults to course language)
3857
     * @param   array   Array of specific fields (['code'=>'value',...])
3858
     * @param   string  What to do if the file already exists (default or overwrite)
3859
     * @param   bool    When set to true, this runs the indexer without actually saving anything to any database
3860
     * @return  bool    Returns true on presumed success, false on failure
3861
     */
3862
    public static function index_document(
3863
        $docid,
3864
        $course_code,
3865
        $session_id = 0,
3866
        $lang = 'english',
3867
        $specific_fields_values = array(),
3868
        $if_exists = '',
3869
        $simulation = false
3870
    ) {
3871
        if (api_get_setting('search_enabled') !== 'true') {
3872
            return false;
3873
        }
3874
        if (empty($docid) or $docid != intval($docid)) {
3875
            return false;
3876
        }
3877
        if (empty($session_id)) {
3878
            $session_id = api_get_session_id();
3879
        }
3880
        $course_info = api_get_course_info($course_code);
3881
        $course_dir = $course_info['path'] . '/document';
3882
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
3883
        $base_work_dir = $sys_course_path . $course_dir;
3884
3885
        $course_id = $course_info['real_id'];
3886
        $table_document = Database::get_course_table(TABLE_DOCUMENT);
3887
3888
        $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
3889
        $result = Database::query($qry);
3890
        if (Database::num_rows($result) == 1) {
3891
            $row = Database::fetch_array($result);
3892
            $doc_path = api_get_path(SYS_COURSE_PATH) . $course_dir . $row['path'];
3893
            //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
3894
            // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
3895
            $doc_mime = mime_content_type($doc_path);
3896
            $allowed_mime_types = self::file_get_mime_type(true);
3897
3898
            // 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
3899
            if (empty($doc_mime)) {
3900
                $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
3901
                $extensions = preg_split("/[\/\\.]/", $doc_path);
3902
                $doc_ext = strtolower($extensions[count($extensions) - 1]);
3903
                if (in_array($doc_ext, $allowed_extensions)) {
3904
                    switch ($doc_ext) {
3905
                        case 'ppt':
3906
                        case 'pps':
3907
                            $doc_mime = 'application/vnd.ms-powerpoint';
3908
                            break;
3909
                        case 'xls':
3910
                            $doc_mime = 'application/vnd.ms-excel';
3911
                            break;
3912
                    }
3913
                }
3914
            }
3915
3916
            //@todo move this nightmare in a search controller or something like that!!! J.M
3917
3918
            if (in_array($doc_mime, $allowed_mime_types)) {
3919
                $file_title = $row['title'];
3920
                $file_content = self::get_text_content($doc_path, $doc_mime);
3921
                $course_code = Database::escape_string($course_code);
3922
3923
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
3924
                require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
3925
3926
                $ic_slide = new IndexableChunk();
3927
                $ic_slide->addValue('title', $file_title);
3928
                $ic_slide->addCourseId($course_code);
3929
                $ic_slide->addToolId(TOOL_DOCUMENT);
3930
                $xapian_data = array(
3931
                    SE_COURSE_ID => $course_code,
3932
                    SE_TOOL_ID => TOOL_DOCUMENT,
3933
                    SE_DATA => array('doc_id' => $docid),
3934
                    SE_USER => api_get_user_id(),
3935
                );
3936
3937
                $ic_slide->xapian_data = serialize($xapian_data);
3938
                $di = new ChamiloIndexer();
3939
                $return = $di->connectDb(null, null, $lang);
3940
3941
                require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
3942
                $specific_fields = get_specific_field_list();
3943
3944
                // process different depending on what to do if file exists
3945
                /**
3946
                 * @TODO Find a way to really verify if the file had been
3947
                 * overwriten. Now all work is done at
3948
                 * handle_uploaded_document() and it's difficult to verify it
3949
                 */
3950
                if (!empty($if_exists) && $if_exists == 'overwrite') {
3951
                    // Overwrite the file on search engine
3952
                    // Actually, it consists on a delete of terms from db,
3953
                    // insert new ones, create a new search engine document,
3954
                    // and remove the old one
3955
                    // Get search_did
3956
                    $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
3957
                    $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
3958
                    $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
3959
3960
                    $res = Database::query($sql);
3961
3962
                    if (Database::num_rows($res) > 0) {
3963
                        $se_ref = Database::fetch_array($res);
3964
                        if (!$simulation) {
3965
                            $di->remove_document($se_ref['search_did']);
3966
                        }
3967
                        $all_specific_terms = '';
3968
                        foreach ($specific_fields as $specific_field) {
3969
                            if (!$simulation) {
3970
                                delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
3971
                            }
3972
                            // Update search engine
3973
                            if (isset($specific_fields_values[$specific_field['code']])) {
3974
                                $sterms = trim($specific_fields_values[$specific_field['code']]);
3975
                            } else { //if the specific field is not defined, force an empty one
3976
                                $sterms = '';
3977
                            }
3978
                            $all_specific_terms .= ' ' . $sterms;
3979
                            $sterms = explode(',', $sterms);
3980
                            foreach ($sterms as $sterm) {
3981
                                $sterm = trim($sterm);
3982
                                if (!empty($sterm)) {
3983
                                    $ic_slide->addTerm($sterm, $specific_field['code']);
3984
                                    // updated the last param here from $value to $sterm without being sure - see commit15464
3985
                                    if (!$simulation) {
3986
                                        add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
3987
                                    }
3988
                                }
3989
                            }
3990
                        }
3991
                        // Add terms also to content to make terms findable by probabilistic search
3992
                        $file_content = $all_specific_terms . ' ' . $file_content;
3993
3994
                        if (!$simulation) {
3995
                            $ic_slide->addValue('content', $file_content);
3996
                            $di->addChunk($ic_slide);
3997
                            // Index and return a new search engine document id
3998
                            $did = $di->index();
3999
4000
                            if ($did) {
4001
                                // update the search_did on db
4002
                                $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4003
                                $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
4004
                                $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
4005
                                Database::query($sql);
4006
                            }
4007
                        }
4008
                    }
4009
                } else {
4010
                    // Add all terms
4011
                    $all_specific_terms = '';
4012 View Code Duplication
                    foreach ($specific_fields as $specific_field) {
4013
                        if (isset($specific_fields_values[$specific_field['code']])) {
4014
                            $sterms = trim($specific_fields_values[$specific_field['code']]);
4015
                        } else { //if the specific field is not defined, force an empty one
4016
                            $sterms = '';
4017
                        }
4018
                        $all_specific_terms .= ' ' . $sterms;
4019
                        if (!empty($sterms)) {
4020
                            $sterms = explode(',', $sterms);
4021
                            foreach ($sterms as $sterm) {
4022
                                if (!$simulation) {
4023
                                    $ic_slide->addTerm(trim($sterm), $specific_field['code']);
4024
                                    add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
4025
                                }
4026
                            }
4027
                        }
4028
                    }
4029
                    // Add terms also to content to make terms findable by probabilistic search
4030
                    $file_content = $all_specific_terms . ' ' . $file_content;
4031
                    if (!$simulation) {
4032
                        $ic_slide->addValue('content', $file_content);
4033
                        $di->addChunk($ic_slide);
4034
                        // Index and return search engine document id
4035
                        $did = $di->index();
4036
                        if ($did) {
4037
                            // Save it to db
4038
                            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
4039
                            $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
4040
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
4041
                            $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
4042
                            Database::query($sql);
4043
                        } else {
4044
                            return false;
4045
                        }
4046
                    }
4047
                }
4048
            } else {
4049
                return false;
4050
            }
4051
        }
4052
        return true;
4053
    }
4054
4055
    /**
4056
     * @return array
4057
     */
4058
    public static function get_web_odf_extension_list()
4059
    {
4060
        return array('ods', 'odt', 'odp');
4061
    }
4062
4063
    /**
4064
     * Set of extension allowed to use Jodconverter
4065
     * @param $mode 'from'
4066
     *              'to'
4067
     *              'all'
4068
     * @param $format   'text'
4069
     *                  'spreadsheet'
4070
     *                  'presentation'
4071
     *                  'drawing'
4072
     *                  'all'
4073
     * @return array
4074
     */
4075
    public static function getJodconverterExtensionList($mode, $format)
4076
    {
4077
        $extensionList = array();
4078
        $extensionListFromText = array(
4079
            'odt',
4080
            'sxw',
4081
            'rtf',
4082
            'doc',
4083
            'docx',
4084
            'wpd',
4085
            'txt',
4086
        );
4087
        $extensionListToText = array(
4088
            'pdf',
4089
            'odt',
4090
            'sxw',
4091
            'rtf',
4092
            'doc',
4093
            'docx',
4094
            'txt',
4095
        );
4096
        $extensionListFromSpreadsheet = array(
4097
            'ods',
4098
            'sxc',
4099
            'xls',
4100
            'xlsx',
4101
            'csv',
4102
            'tsv',
4103
        );
4104
        $extensionListToSpreadsheet = array(
4105
            'pdf',
4106
            'ods',
4107
            'sxc',
4108
            'xls',
4109
            'xlsx',
4110
            'csv',
4111
            'tsv',
4112
        );
4113
        $extensionListFromPresentation = array(
4114
            'odp',
4115
            'sxi',
4116
            'ppt',
4117
            'pptx',
4118
        );
4119
        $extensionListToPresentation = array(
4120
            'pdf',
4121
            'swf',
4122
            'odp',
4123
            'sxi',
4124
            'ppt',
4125
            'pptx',
4126
        );
4127
        $extensionListFromDrawing = array('odg');
4128
        $extensionListToDrawing = array('svg', 'swf');
4129
4130
        if ($mode === 'from') {
4131 View Code Duplication
            if ($format === 'text') {
4132
                $extensionList = array_merge($extensionList, $extensionListFromText);
4133
            } elseif ($format === 'spreadsheet') {
4134
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4135
            } elseif ($format === 'presentation') {
4136
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4137
            } elseif ($format === 'drawing') {
4138
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4139
            } elseif ($format === 'all') {
4140
                $extensionList = array_merge($extensionList, $extensionListFromText);
4141
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4142
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4143
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4144
            }
4145 View Code Duplication
        } elseif ($mode === 'to') {
4146
            if ($format === 'text') {
4147
                $extensionList = array_merge($extensionList, $extensionListToText);
4148
            } elseif ($format === 'spreadsheet') {
4149
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4150
            } elseif ($format === 'presentation') {
4151
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4152
            } elseif ($format === 'drawing') {
4153
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4154
            } elseif ($format === 'all') {
4155
                $extensionList = array_merge($extensionList, $extensionListToText);
4156
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4157
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4158
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4159
            }
4160
        } elseif ($mode === 'all') {
4161
            if ($format === 'text') {
4162
                $extensionList = array_merge($extensionList, $extensionListFromText);
4163
                $extensionList = array_merge($extensionList, $extensionListToText);
4164
            } elseif ($format === 'spreadsheet') {
4165
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4166
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4167
            } elseif ($format === 'presentation') {
4168
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4169
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4170
            } elseif ($format === 'drawing') {
4171
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4172
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4173
            } elseif ($format === 'all') {
4174
                $extensionList = array_merge($extensionList, $extensionListFromText);
4175
                $extensionList = array_merge($extensionList, $extensionListToText);
4176
                $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
4177
                $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
4178
                $extensionList = array_merge($extensionList, $extensionListFromPresentation);
4179
                $extensionList = array_merge($extensionList, $extensionListToPresentation);
4180
                $extensionList = array_merge($extensionList, $extensionListFromDrawing);
4181
                $extensionList = array_merge($extensionList, $extensionListToDrawing);
4182
            }
4183
        }
4184
        return $extensionList;
4185
    }
4186
4187
    /**
4188
     * Get Format type list by extension and mode
4189
     * @param string $mode Mode to search format type list
4190
     * @example 'from'
4191
     * @example 'to'
4192
     * @param string $extension file extension to check file type
4193
     * @return array
4194
     */
4195
    public static function getFormatTypeListConvertor($mode = 'from', $extension)
4196
    {
4197
        $formatTypesList = array();
4198
        $formatTypes = array('text', 'spreadsheet', 'presentation', 'drawing');
4199
        foreach ($formatTypes as $formatType) {
4200
            if (
4201
            in_array(
4202
                $extension,
4203
                self::getJodconverterExtensionList($mode, $formatType)
4204
            )
4205
            ) {
4206
                $formatTypesList[] = $formatType;
4207
            }
4208
        }
4209
        return $formatTypesList;
4210
    }
4211
4212
    /**
4213
     * @param string $path
4214
     * @param bool $is_certificate_mode
4215
     * @return bool
4216
     */
4217
    public static function is_folder_to_avoid($path, $is_certificate_mode = false)
4218
    {
4219
        $foldersToAvoid = array(
4220
            '/HotPotatoes_files',
4221
            '/certificates',
4222
        );
4223
        $systemFolder = api_get_course_setting('show_system_folders');
4224
4225
        if ($systemFolder == 1) {
4226
            $foldersToAvoid = array();
4227
        }
4228
4229
        if (basename($path) == 'css') {
4230
            return true;
4231
        }
4232
4233
        if ($is_certificate_mode == false) {
4234
            //Certificate results
4235
            if (strstr($path, 'certificates')) {
4236
                return true;
4237
            }
4238
        }
4239
4240
        // Admin setting for Hide/Show the folders of all users
4241 View Code Duplication
        if (api_get_setting('show_users_folders') == 'false') {
4242
            $foldersToAvoid[] = '/shared_folder';
4243
4244
            if (strstr($path, 'shared_folder_session_')) {
4245
                return true;
4246
            }
4247
        }
4248
4249
        // Admin setting for Hide/Show Default folders to all users
4250
        if (api_get_setting('show_default_folders') == 'false') {
4251
            $foldersToAvoid[] = '/images';
4252
            $foldersToAvoid[] = '/flash';
4253
            $foldersToAvoid[] = '/audio';
4254
            $foldersToAvoid[] = '/video';
4255
        }
4256
4257
        // Admin setting for Hide/Show chat history folder
4258
        if (api_get_setting('show_chat_folder') == 'false') {
4259
            $foldersToAvoid[] = '/chat_files';
4260
        }
4261
4262
        if (is_array($foldersToAvoid)) {
4263
4264
            return in_array($path, $foldersToAvoid);
4265
        } else {
4266
4267
            return false;
4268
        }
4269
    }
4270
4271
    /**
4272
     * @return array
4273
     */
4274 View Code Duplication
    public static function get_system_folders()
4275
    {
4276
        return array(
4277
            '/certificates',
4278
            '/HotPotatoes_files',
4279
            '/chat_files',
4280
            '/images',
4281
            '/flash',
4282
            '/audio',
4283
            '/video',
4284
            '/shared_folder',
4285
            '/learning_path'
4286
        );
4287
    }
4288
4289
    /**
4290
     * @return array
4291
     */
4292
    public static function getProtectedFolderFromStudent()
4293
    {
4294
        return array(
4295
            '/certificates',
4296
            '/HotPotatoes_files',
4297
            '/chat_files',
4298
            '/shared_folder',
4299
            '/learning_path'
4300
        );
4301
    }
4302
4303
    /**
4304
     * @param string $courseCode
4305
     * @return string 'visible' or 'invisible' string
4306
     */
4307
    public static function getDocumentDefaultVisibility($courseCode)
4308
    {
4309
        $settings = api_get_setting('tool_visible_by_default_at_creation');
4310
4311
        $defaultVisibility = 'visible';
4312
4313
        if (isset($settings['documents'])) {
4314
            $portalDefaultVisibility =  'invisible';
4315
            if ($settings['documents'] == 'true') {
4316
                $portalDefaultVisibility = 'visible';
4317
            }
4318
4319
            $defaultVisibility = $portalDefaultVisibility;
4320
        }
4321
4322
        if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
4323
            $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
4324
            if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
4325
                $defaultVisibility = $courseVisibility;
4326
            }
4327
        }
4328
        return $defaultVisibility;
4329
    }
4330
4331
    /**
4332
     * @param array $courseInfo
4333
     * @param int $id doc id
4334
     * @param string $visibility visible/invisible
4335
     * @param int $userId
4336
     */
4337
    public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
4338
    {
4339
        $sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
4340
4341
        if (!empty($sessionList)) {
4342
            foreach ($sessionList as $session) {
4343
                $sessionId = $session['id'];
4344
                api_item_property_update(
4345
                    $courseInfo,
4346
                    TOOL_DOCUMENT,
4347
                    $id,
4348
                    $visibility,
4349
                    $userId,
4350
                    null,
4351
                    null,
4352
                    null,
4353
                    null,
4354
                    $sessionId
4355
                );
4356
            }
4357
        }
4358
    }
4359
4360
    /**
4361
     * @param string $file
4362
     * @return string
4363
     */
4364
    public static function readNanogongFile($file)
4365
    {
4366
        $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
4367
        $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
4368
        $html .= '<param name="SoundFileURL" value="'.$file.'" />';
4369
        $html .= '<param name="ShowSaveButton" value="false" />';
4370
        $html .= '<param name="ShowTime" value="true" />';
4371
        $html .= '<param name="ShowRecordButton" value="false" />';
4372
        $html .= '</applet>';
4373
        return $html;
4374
    }
4375
4376
    /**
4377
     * @param string $filePath
4378
     * @param string $path
4379
     * @param array $courseInfo
4380
     * @param int $sessionId
4381
     * @param string $whatIfFileExists overwrite|rename
4382
     * @param int $userId
4383
     * @param int $groupId
4384
     * @param int $toUserId
4385
     * @param string $comment
4386
     * @return bool|path
4387
     */
4388
    public static function addFileToDocumentTool(
4389
        $filePath,
4390
        $path,
4391
        $courseInfo,
4392
        $sessionId,
4393
        $userId,
4394
        $whatIfFileExists = 'overwrite',
4395
        $groupId = null,
4396
        $toUserId = null,
4397
        $comment = null
4398
    ) {
4399
        if (!file_exists($filePath)) {
4400
            return false;
4401
        }
4402
4403
        $fileInfo = pathinfo($filePath);
4404
4405
        $file = array(
4406
            'name' => $fileInfo['basename'],
4407
            'tmp_name' => $filePath,
4408
            'size' => filesize($filePath),
4409
            'from_file' => true
4410
        );
4411
4412
        $course_dir = $courseInfo['path'].'/document';
4413
        $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
4414
4415
        $filePath = handle_uploaded_document(
4416
            $courseInfo,
4417
            $file,
4418
            $baseWorkDir,
4419
            $path,
4420
            $userId,
4421
            $groupId,
4422
            $toUserId,
4423
            false,
4424
            $whatIfFileExists,
4425
            false,
4426
            false,
4427
            $comment,
4428
            $sessionId
4429
        );
4430
4431
        if ($filePath) {
4432
            return DocumentManager::get_document_id(
4433
                $courseInfo,
4434
                $filePath,
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by handle_uploaded_document..., $comment, $sessionId) on line 4415 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...
4435
                $sessionId
4436
            );
4437
        }
4438
        return false;
4439
    }
4440
4441
    /**
4442
     * Converts wav to mp3 file.
4443
     * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
4444
     * @param string $wavFile
4445
     * @param bool $removeWavFileIfSuccess
4446
     * @return bool
4447
     */
4448
    public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
4449
    {
4450
        if (file_exists($wavFile)) {
4451
            try {
4452
                $ffmpeg = \FFMpeg\FFMpeg::create();
4453
                $video = $ffmpeg->open($wavFile);
4454
4455
                $mp3File = str_replace('wav', 'mp3', $wavFile);
4456
                $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
4457
                if ($result && $removeWavFileIfSuccess) {
4458
                    unlink($wavFile);
4459
                }
4460
4461
                if (file_exists($mp3File)) {
4462
                    return $mp3File;
4463
                }
4464
            } catch (Exception $e) {
4465
                error_log($e->getMessage());
4466
                error_log($e->getPrevious()->getMessage());
4467
            }
4468
        }
4469
        return false;
4470
    }
4471
4472
    /**
4473
     * @param string $documentData wav document information
4474
     * @param array $courseInfo
4475
     * @param int $sessionId
4476
     * @param int $userId user that adds the document
4477
     * @param string $whatIfFileExists
4478
     * @param bool $deleteWavFile
4479
     *
4480
     * @return bool
4481
     */
4482
    public static function addAndConvertWavToMp3(
4483
        $documentData,
4484
        $courseInfo,
4485
        $sessionId,
4486
        $userId,
4487
        $whatIfFileExists = 'overwrite',
4488
        $deleteWavFile = false
4489
    ) {
4490
        if (empty($documentData)) {
4491
            return false;
4492
        }
4493
4494
        if (isset($documentData['absolute_path']) &&
4495
            file_exists($documentData['absolute_path'])
4496
        ) {
4497
            $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
4498
4499
            if (!empty($mp3FilePath) && file_exists($mp3FilePath)) {
4500
4501
                $documentId = self::addFileToDocumentTool(
4502
                    $mp3FilePath,
4503
                    dirname($documentData['path']),
4504
                    $courseInfo,
4505
                    $sessionId,
4506
                    $userId,
4507
                    $whatIfFileExists,
4508
                    null,
4509
                    null,
4510
                    $documentData['comment']
4511
                );
4512
4513 View Code Duplication
                if (!empty($documentId)) {
4514
4515
                    if ($deleteWavFile) {
4516
                        $coursePath = $courseInfo['directory'].'/document';
4517
                        $documentPath = api_get_path(SYS_COURSE_PATH).$coursePath;
4518
                        self::delete_document(
4519
                            $courseInfo,
4520
                            null,
4521
                            $documentPath,
4522
                            $sessionId,
4523
                            $documentData['id']
4524
                        );
4525
                    }
4526
4527
                    return $documentId;
4528
                }
4529
            }
4530
        }
4531
4532
        return false;
4533
    }
4534
4535
    /**
4536
     * Sets
4537
     * @param string $file ($document_data['path'])
4538
     * @param string $file_url_sys
4539
     * @return string
4540
     */
4541
    public static function generateAudioTempFile($file, $file_url_sys)
4542
    {
4543
        //make temp audio
4544
        $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
4545
        if (!file_exists($temp_folder)) {
4546
            @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
4547
        }
4548
4549
        //make htaccess with allow from all, and file index.html into temp/audio
4550
        $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
4551 View Code Duplication
        if (!file_exists($htaccess)) {
4552
            $htaccess_content="order deny,allow\r\nallow from all\r\nOptions -Indexes";
4553
            $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
4554
            if ($fp) {
4555
                fwrite($fp, $htaccess_content);
4556
                fclose($fp);
4557
            }
4558
        }
4559
4560
        //encript temp name file
4561
        $name_crip = sha1(uniqid());//encript
4562
        $findext= explode(".", $file);
4563
        $extension = $findext[count($findext)-1];
4564
        $file_crip = $name_crip.'.'.$extension;
4565
4566
        //copy file to temp/audio directory
4567
        $from_sys = $file_url_sys;
4568
        $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4569
4570
        if (file_exists($from_sys)) {
4571
            copy($from_sys, $to_sys);
4572
        }
4573
4574
        //get  file from tmp directory
4575
        $_SESSION['temp_audio_nanogong'] = $to_sys;
4576
4577
        return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
4578
    }
4579
4580
    /**
4581
     * Erase temp nanogong audio.
4582
     */
4583
    public static function removeGeneratedAudioTempFile()
4584
    {
4585 View Code Duplication
        if (isset($_SESSION['temp_audio_nanogong'])
4586
            && !empty($_SESSION['temp_audio_nanogong'])
4587
            && is_file($_SESSION['temp_audio_nanogong'])) {
4588
4589
            unlink($_SESSION['temp_audio_nanogong']);
4590
            unset($_SESSION['temp_audio_nanogong']);
4591
        }
4592
    }
4593
4594
    /**
4595
     * Check if the past is used in this course.
4596
     * @param array $courseInfo
4597
     * @param string $path
4598
     *
4599
     * @return array
4600
     */
4601
    public static function getDocumentByPathInCourse($courseInfo, $path)
4602
    {
4603
        $table = Database::get_course_table(TABLE_DOCUMENT);
4604
        $path = Database::escape_string($path);
4605
        $courseId = $courseInfo['real_id'];
4606
        if (empty($courseId)) {
4607
            return false;
4608
        }
4609
        $sql = "SELECT * FROM $table WHERE c_id = $courseId AND path = '$path'";
4610
        $result = Database::query($sql);
4611
        return Database::store_result($result, 'ASSOC');
4612
    }
4613
4614
    /**
4615
     * @param array $_course
4616
     * @return int
4617
     */
4618
    public static function createDefaultAudioFolder($_course)
4619
    {
4620
        if (!isset($_course['path'])) {
4621
            return false;
4622
        }
4623
4624
        $audioId = null;
4625
        $path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
4626
        if (!is_dir($path.'audio')) {
4627
            mkdir($path.'audio', api_get_permissions_for_new_directories());
4628
            $audioId = add_document($_course, '/audio', 'folder', 0, 'Audio');
4629
            api_item_property_update(
4630
                $_course,
4631
                TOOL_DOCUMENT,
4632
                $audioId,
4633
                'FolderCreated',
4634
                api_get_user_id(),
4635
                null,
4636
                null,
4637
                null,
4638
                null,
4639
                api_get_session_id()
4640
            );
4641
        }
4642
4643
        return $audioId;
4644
    }
4645
4646
    /**
4647
     * Generate a default certificate for a courses
4648
     *
4649
     * @global string $css CSS directory
4650
     * @global string $img_dir image directory
4651
     * @global string $default_course_dir Course directory
4652
     * @global string $js JS directory
4653
     * @param array $courseData The course info
4654
     * @param bool $fromBaseCourse
4655
     * @param int $sessionId
4656
     */
4657
    public static function generateDefaultCertificate($courseData, $fromBaseCourse = false, $sessionId = 0)
4658
    {
4659
        global $css, $img_dir, $default_course_dir, $js;
4660
        $codePath = api_get_path(REL_CODE_PATH);
4661
        $dir = '/certificates';
4662
4663
        $title = get_lang('DefaultCertificate');
4664
        $comment = null;
4665
4666
        $fileName = api_replace_dangerous_char($title);
4667
        $filePath = api_get_path(SYS_COURSE_PATH) . "{$courseData['path']}/document{$dir}";
4668
        $fileFullPath = "{$filePath}/{$fileName}.html";
4669
        $fileSize = 0;
4670
        $fileType = 'file';
4671
        $templateContent = file_get_contents(api_get_path(SYS_CODE_PATH).'gradebook/certificate_template/template.html');
4672
4673
        $search = array('{CSS}', '{IMG_DIR}', '{REL_CODE_PATH}', '{COURSE_DIR}');
4674
        $replace = array($css.$js, $img_dir, $codePath, $default_course_dir);
4675
4676
        $fileContent = str_replace($search, $replace, $templateContent);
4677
4678
        $saveFilePath = "{$dir}/{$fileName}.html";
4679
4680
        if (!is_dir($filePath)) {
4681
            mkdir($filePath, api_get_permissions_for_new_directories());
4682
        }
4683
4684
        if ($fromBaseCourse) {
4685
            $defaultCertificateId = self::get_default_certificate_id($courseData['code'], 0);
4686
4687
            if (!empty($defaultCertificateId)) {
4688
                // We have a certificate from the course base
4689
                $documentData = DocumentManager::get_document_data_by_id(
4690
                    $defaultCertificateId,
4691
                    $courseData['code'],
4692
                    false,
4693
                    0
4694
                );
4695
4696
                if ($documentData) {
4697
                    $fileContent = file_get_contents($documentData['absolute_path']);
4698
                }
4699
            }
4700
        }
4701
4702
        $defaultCertificateFile = $fp = @fopen($fileFullPath, 'w');
4703
4704
        if ($defaultCertificateFile != false) {
4705
            @fputs($defaultCertificateFile, $fileContent);
4706
            fclose($defaultCertificateFile);
4707
            chmod($fileFullPath, api_get_permissions_for_new_files());
4708
4709
            $fileSize = filesize($fileFullPath);
4710
        }
4711
4712
        $documentId = add_document(
4713
            $courseData,
4714
            $saveFilePath,
4715
            $fileType,
4716
            $fileSize,
4717
            $title,
4718
            $comment,
4719
            0,//$readonly = 0,
4720
            true, //$save_visibility = true,
4721
            null, //$group_id = null,
4722
            $sessionId
4723
        );
4724
4725
        api_item_property_update(
4726
            $courseData,
4727
            TOOL_DOCUMENT,
4728
            $documentId,
4729
            'DocumentAdded',
4730
            api_get_user_id(),
4731
            null,
4732
            null,
4733
            null,
4734
            null,
4735
            $sessionId
4736
        );
4737
4738
        $defaultCertificateId = self::get_default_certificate_id(
4739
            $courseData['code'],
4740
            $sessionId
4741
        );
4742
4743
        if (!isset($defaultCertificateId)) {
4744
            self::attach_gradebook_certificate($courseData['code'], $documentId, $sessionId);
4745
        }
4746
    }
4747
4748
    /**
4749
     * Update the document name
4750
     * @param int $documentId The document id
4751
     * @param string $newName The new name
4752
     */
4753
    public static function renameDocument($documentId, $newName)
4754
    {
4755
        $documentId = intval($documentId);
4756
        $newName = Database::escape_string($newName);
4757
4758
        $docuentTable = Database::get_course_table(TABLE_DOCUMENT);
4759
4760
        $values = array(
4761
            'title' => $newName
4762
        );
4763
4764
        $whereConditions = array(
4765
            'id = ?' => $documentId
4766
        );
4767
4768
        Database::update($docuentTable, $values, $whereConditions);
4769
    }
4770
4771
    /**
4772
     * Get folder/file suffix
4773
     *
4774
     * @param array $courseInfo
4775
     * @param int $sessionId
4776
     * @param int $groupId
4777
     *
4778
     * @return string
4779
     */
4780
    public static function getDocumentSuffix($courseInfo, $sessionId, $groupId)
4781
    {
4782
        // If no session or group, then no suffix.
4783
        if (empty($sessionId) && empty($groupId)) {
4784
4785
            return '';
4786
        }
4787
4788
        return '__'.intval($sessionId).'__'.intval($groupId);
4789
    }
4790
4791
    /**
4792
     * Fix a document name adding session id and group id
4793
     * Turns picture.jpg -> picture__1__2.jpg
4794
     * Where 1 = session id and 2 group id
4795
     * Of session id and group id are empty then the function returns:
4796
     * picture.jpg ->  picture.jpg
4797
     *
4798
     * @param string $name folder or file name
4799
     * @param string $type 'folder' or 'file'
4800
     * @param array $courseInfo
4801
     * @param int $sessionId
4802
     * @param int $groupId
4803
     *
4804
     * @return string
4805
     */
4806
    public static function fixDocumentName($name, $type, $courseInfo, $sessionId, $groupId)
4807
    {
4808
        $suffix = self::getDocumentSuffix($courseInfo, $sessionId, $groupId);
4809
4810
        switch ($type) {
4811
            case 'folder':
4812
                $name = $name.$suffix;
4813
                break;
4814
            case 'file':
4815
                $name = self::addSuffixToFileName($name, $suffix);
4816
                break;
4817
        }
4818
4819
        return $name;
4820
    }
4821
4822
    /**
4823
     * Add a suffix to a file Example:
4824
     * /folder/picture.jpg => to /folder/picture_this.jpg
4825
     * where "_this" is the suffix
4826
     * @param string $name
4827
     * @param string $suffix
4828
     * @return string
4829
     */
4830
    public static function addSuffixToFileName($name, $suffix)
4831
    {
4832
        $extension = pathinfo($name, PATHINFO_EXTENSION);
4833
        $fileName = pathinfo($name, PATHINFO_FILENAME);
4834
        $dir = pathinfo($name, PATHINFO_DIRNAME);
4835
4836
        if ($dir == '.') {
4837
            $dir = null;
4838
        }
4839
4840
        if (!empty($dir) && $dir != '/') {
4841
            $dir = $dir.'/';
4842
        }
4843
4844
        $name = $dir.$fileName.$suffix.'.'.$extension;
4845
        return $name;
4846
    }
4847
4848
    /**
4849
     * Check if folder exist in the course base or in the session course
4850
     * @param string $folder Example: /folder/folder2
4851
     * @param array $courseInfo
4852
     * @param int $sessionId
4853
     * @param int $groupId
4854
     *
4855
     * @return bool
4856
     */
4857 View Code Duplication
    public static function folderExists(
4858
        $folder,
4859
        $courseInfo,
4860
        $sessionId,
4861
        $groupId
4862
    ) {
4863
        $courseId = $courseInfo['real_id'];
4864
4865
        if (empty($courseId)) {
4866
            return false;
4867
        }
4868
4869
        $sessionId = intval($sessionId);
4870
        $folderWithSuffix = self::fixDocumentName(
4871
            $folder,
4872
            'folder',
4873
            $courseInfo,
4874
            $sessionId,
4875
            $groupId
4876
        );
4877
4878
        $folder = Database::escape_string($folder);
4879
        $folderWithSuffix = Database::escape_string($folderWithSuffix);
4880
4881
        // Check if pathname already exists inside document table
4882
        $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
4883
        $sql = "SELECT id, path FROM $tbl_document
4884
                WHERE
4885
                    filetype = 'folder' AND
4886
                    c_id = $courseId AND
4887
                    (path = '$folder' OR path = '$folderWithSuffix') AND
4888
                    (session_id = 0 OR session_id = $sessionId)
4889
        ";
4890
4891
        $rs = Database::query($sql);
4892
        if (Database::num_rows($rs)) {
4893
            return true;
4894
        }
4895
4896
        return false;
4897
    }
4898
4899
    /**
4900
     * Check if file exist in the course base or in the session course
4901
     * @param string $fileName Example: /folder/picture.jpg
4902
     * @param array $courseInfo
4903
     * @param int $sessionId
4904
     * @param int $groupId
4905
     *
4906
     * @return bool
4907
     */
4908 View Code Duplication
    public static function documentExists(
4909
        $fileName,
4910
        $courseInfo,
4911
        $sessionId,
4912
        $groupId
4913
    ) {
4914
        $courseId = $courseInfo['real_id'];
4915
4916
        if (empty($courseId)) {
4917
            return false;
4918
        }
4919
4920
        $sessionId = intval($sessionId);
4921
        $fileNameEscape = Database::escape_string($fileName);
4922
4923
        $fileNameWithSuffix = self::fixDocumentName(
4924
            $fileName,
4925
            'file',
4926
            $courseInfo,
4927
            $sessionId,
4928
            $groupId
4929
        );
4930
4931
        $fileNameWithSuffix = Database::escape_string($fileNameWithSuffix);
4932
4933
        // Check if pathname already exists inside document table
4934
        $table = Database::get_course_table(TABLE_DOCUMENT);
4935
        $sql = "SELECT id, path FROM $table
4936
                WHERE
4937
                    filetype = 'file' AND
4938
                    c_id = $courseId AND
4939
                    (
4940
                        path = '".$fileNameEscape."' OR
4941
                        path = '$fileNameWithSuffix'
4942
                    ) AND
4943
                    (session_id = 0 OR session_id = $sessionId)
4944
        ";
4945
        $rs = Database::query($sql);
4946
        if (Database::num_rows($rs)) {
4947
            return true;
4948
        }
4949
4950
        return false;
4951
    }
4952
4953
    /**
4954
     * Undo the suffix applied to a file example:
4955
     * turns picture__1__1.jpg to picture.jpg
4956
     * @param string $name
4957
     * @param int $courseId
4958
     * @param int $sessionId
4959
     * @param int $groupId
4960
     *
4961
     * @return string
4962
     */
4963
    public static function undoFixDocumentName(
4964
        $name,
4965
        $courseId,
4966
        $sessionId,
4967
        $groupId
4968
    ) {
4969
        if (empty($sessionId) && empty($groupId)) {
4970
            return $name;
4971
        }
4972
4973
        $suffix = self::getDocumentSuffix(
4974
            array('real_id' => $courseId),
4975
            $sessionId,
4976
            $groupId
4977
        );
4978
4979
        $name = str_replace($suffix, '', $name);
4980
4981
        return $name;
4982
    }
4983
4984
    /**
4985
     * @param string $path
4986
     * @param string $name
4987
     * @param array $courseInfo
4988
     * @param int $sessionId
4989
     * @param int $groupId
4990
     *
4991
     * @return string
4992
     */
4993
    public static function getUniqueFileName($path, $name, $courseInfo, $sessionId, $groupId)
4994
    {
4995
        $counter = 1;
4996
        $filePath = $path.$name;
4997
        $uniqueName = $name;
4998
        while ($documentExists = self::documentExists(
4999
            $filePath,
5000
            $courseInfo,
5001
            $sessionId,
5002
            $groupId
5003
        )) {
5004
            $uniqueName = self::addSuffixToFileName($name, '_' . $counter);
5005
            $filePath = $path . $uniqueName;
5006
            $counter++;
5007
        }
5008
5009
        return $uniqueName;
5010
    }
5011
5012
5013
    /**
5014
     * Builds the form that enables the user to
5015
     * select a directory to browse/upload in
5016
     *
5017
     * @param array 	An array containing the folders we want to be able to select
5018
     * @param string	The current folder (path inside of the "document" directory, including the prefix "/")
5019
     * @param string	Group directory, if empty, prevents documents to be uploaded (because group documents cannot be uploaded in root)
5020
     * @param	boolean	Whether to change the renderer (this will add a template <span> to the QuickForm object displaying the form)
5021
     * @todo this funcionality is really bad : jmontoya
5022
     * @return string html form
5023
     */
5024
    public static function build_directory_selector($folders, $document_id, $group_dir = '', $change_renderer = false)
5025
    {
5026
        $doc_table = Database::get_course_table(TABLE_DOCUMENT);
5027
        $course_id = api_get_course_int_id();
5028
        $folder_titles = array();
5029
5030
        if (is_array($folders)) {
5031
            $escaped_folders = array();
5032
            foreach ($folders as $key => & $val) {
5033
                $escaped_folders[$key] = Database::escape_string($val);
5034
            }
5035
            $folder_sql = implode("','", $escaped_folders);
5036
5037
            $sql = "SELECT * FROM $doc_table
5038
                WHERE filetype = 'folder' AND c_id = $course_id AND path IN ('" . $folder_sql . "')";
5039
            $res = Database::query($sql);
5040
            $folder_titles = array();
5041
            while ($obj = Database::fetch_object($res)) {
5042
                $folder_titles[$obj->path] = $obj->title;
5043
            }
5044
        }
5045
5046
        $form = new FormValidator('selector', 'GET', api_get_self() . '?' . api_get_cidreq());
5047
        $form->addElement('hidden', 'cidReq', api_get_course_id());
5048
        $parent_select = $form->addSelect('id', get_lang('CurrentDirectory'), '', array('onchange' => 'javascript: document.selector.submit();'));
5049
5050
        if ($change_renderer) {
5051
            $renderer = $form->defaultRenderer();
5052
            $renderer->setElementTemplate('<span>{label} : {element}</span> ', 'curdirpath');
5053
        }
5054
5055
        // Group documents cannot be uploaded in the root
5056
        if (empty($group_dir)) {
5057
            $parent_select->addOption(get_lang('Documents'), '/');
5058
5059
            if (is_array($folders)) {
5060
                foreach ($folders as $folder_id => & $folder) {
5061
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5062
                    $path_parts = explode('/', $folder);
5063
                    $folder_titles[$folder] = cut($folder_titles[$folder], 80);
5064
                    $counter = count($path_parts) - 2;
5065 View Code Duplication
                    if ($counter > 0) {
5066
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', $counter) . ' &mdash; ' . $folder_titles[$folder];
5067
                    } else {
5068
                        $label = ' &mdash; ' . $folder_titles[$folder];
5069
                    }
5070
                    $parent_select->addOption($label, $folder_id);
5071
                    if ($selected != '') {
5072
                        $parent_select->setSelected($folder_id);
5073
                    }
5074
                }
5075
            }
5076
        } else {
5077
            if (!empty($folders)) {
5078
                foreach ($folders as $folder_id => & $folder) {
5079
                    $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
5080
                    $label = $folder_titles[$folder];
5081 View Code Duplication
                    if ($folder == $group_dir) {
5082
                        $label = get_lang('Documents');
5083
                    } else {
5084
                        $path_parts = explode('/', str_replace($group_dir, '', $folder));
5085
                        $label = cut($label, 80);
5086
                        $label = str_repeat('&nbsp;&nbsp;&nbsp;', count($path_parts) - 2) . ' &mdash; ' . $label;
5087
                    }
5088
                    $parent_select->addOption($label, $folder_id);
5089
                    if ($selected != '') {
5090
                        $parent_select->setSelected($folder_id);
5091
                    }
5092
                }
5093
            }
5094
        }
5095
        $html = $form->toHtml();
5096
5097
        return $html;
5098
    }
5099
5100
    /**
5101
     * Create a html hyperlink depending on if it's a folder or a file
5102
     *
5103
     * @param array $document_data
5104
     * @param int $show_as_icon - if it is true, only a clickable icon will be shown
5105
     * @param int $visibility (1/0)
5106
     * @param int $counter
5107
     *
5108
     * @return string url
5109
     */
5110
    public static function create_document_link(
5111
        $document_data,
5112
        $show_as_icon = false,
5113
        $counter = null,
5114
        $visibility
5115
    ) {
5116
        global $dbl_click_id;
5117
        $course_info = api_get_course_info();
5118
        $www = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/document';
5119
        $webOdflist = DocumentManager::get_web_odf_extension_list();
5120
5121
        // Get the title or the basename depending on what we're using
5122 View Code Duplication
        if ($document_data['title'] != '') {
5123
            $title = $document_data['title'];
5124
        } else {
5125
            $title = basename($document_data['path']);
5126
        }
5127
5128
        $filetype = $document_data['filetype'];
5129
        $size = $filetype == 'folder' ? get_total_folder_size($document_data['path'], api_is_allowed_to_edit(null, true)) : $document_data['size'];
5130
        $path = $document_data['path'];
5131
5132
        $url_path = urlencode($document_data['path']);
5133
5134
        // Add class="invisible" on invisible files
5135
        $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...
5136
        $forcedownload_link = null;
5137
        $forcedownload_icon = null;
5138
        $prevent_multiple_click = null;
5139
5140
        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...
5141
            // Build download link (icon)
5142
            $forcedownload_link = ($filetype == 'folder') ? api_get_self() . '?' . api_get_cidreq() . '&action=downloadfolder&id=' . $document_data['id'] : api_get_self() . '?' . api_get_cidreq() . '&amp;action=download&amp;id=' . $document_data['id'];
5143
            // Folder download or file download?
5144
            $forcedownload_icon = ($filetype == 'folder') ? 'save_pack.png' : 'save.png';
5145
            // Prevent multiple clicks on zipped folder download
5146
            $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; }\"" : '';
5147
        }
5148
5149
        $target = '_self';
5150
        $is_browser_viewable_file = false;
5151
5152
        if ($filetype == 'file') {
5153
            // Check the extension
5154
            $ext = explode('.', $path);
5155
            $ext = strtolower($ext[sizeof($ext) - 1]);
5156
5157
            // HTML-files an some other types are shown in a frameset by default.
5158
            $is_browser_viewable_file = self::is_browser_viewable($ext);
5159
5160
            if ($is_browser_viewable_file) {
5161
                if ($ext == 'pdf' || in_array($ext, $webOdflist)) {
5162
                    $url = api_get_self() . '?' . api_get_cidreq() . '&amp;action=download&amp;id=' . $document_data['id'];
5163
                } else {
5164
                    $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5165
                }
5166
            } else {
5167
                // url-encode for problematic characters (we may not call them dangerous characters...)
5168
                $path = str_replace('%2F', '/', $url_path) . '?' . api_get_cidreq();
5169
                $url = $www . $path;
5170
            }
5171
5172
            /*$path = str_replace('%2F', '/', $url_path); //yox view hack otherwise the image can't be well read
5173
            $url = $www . $path;*/
5174
        } else {
5175
            $url = api_get_self() . '?' . api_get_cidreq() . '&id=' . $document_data['id'];
5176
        }
5177
5178
        // The little download icon
5179
        $tooltip_title = $title;
5180
5181
        $tooltip_title_alt = $tooltip_title;
5182
        if ($path == '/shared_folder') {
5183
            $tooltip_title_alt = get_lang('UserFolders');
5184
        } elseif (strstr($path, 'shared_folder_session_')) {
5185
            $tooltip_title_alt = get_lang('UserFolders') . ' (' . api_get_session_name(api_get_session_id()) . ')';
5186
        } elseif (strstr($tooltip_title, 'sf_user_')) {
5187
            $userinfo = api_get_user_info(substr($tooltip_title, 8));
5188
            $tooltip_title_alt = get_lang('UserFolder') . ' ' . $userinfo['complete_name'];
5189
        } elseif ($path == '/chat_files') {
5190
            $tooltip_title_alt = get_lang('ChatFiles');
5191
        } elseif ($path == '/learning_path') {
5192
            $tooltip_title_alt = get_lang('LearningPaths');
5193
        } elseif ($path == '/video') {
5194
            $tooltip_title_alt = get_lang('Video');
5195
        } elseif ($path == '/audio') {
5196
            $tooltip_title_alt = get_lang('Audio');
5197
        } elseif ($path == '/flash') {
5198
            $tooltip_title_alt = get_lang('Flash');
5199
        } elseif ($path == '/images') {
5200
            $tooltip_title_alt = get_lang('Images');
5201
        } elseif ($path == '/images/gallery') {
5202
            $tooltip_title_alt = get_lang('DefaultCourseImages');
5203
        }
5204
5205
        $current_session_id = api_get_session_id();
5206
        $copy_to_myfiles = $open_in_new_window_link = null;
5207
5208
        $curdirpath = isset($_GET['curdirpath']) ? Security::remove_XSS($_GET['curdirpath']) : null;
5209
        $send_to = null;
5210
5211
        $checkExtension = $path;
5212
5213
        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...
5214
            if ($filetype == 'folder') {
5215
                if (api_is_allowed_to_edit() ||
5216
                    api_is_platform_admin() ||
5217
                    api_get_setting('students_download_folders') == 'true'
5218
                ) {
5219
                    //filter when I am into shared folder, I can show for donwload only my shared folder
5220
                    if (DocumentManager::is_shared_folder($curdirpath, $current_session_id)) {
5221
                        if (preg_match('/shared_folder\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5222
                            preg_match('/shared_folder_session_' . $current_session_id . '\/sf_user_' . api_get_user_id() . '$/', urldecode($forcedownload_link)) ||
5223
                            api_is_allowed_to_edit() || api_is_platform_admin()
5224
                        ) {
5225
                            $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5226
                                Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5227
                        }
5228
                    } elseif (!preg_match('/shared_folder/', urldecode($forcedownload_link)) ||
5229
                        api_is_allowed_to_edit() ||
5230
                        api_is_platform_admin()
5231
                    ) {
5232
                        $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5233
                            Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5234
                    }
5235
                }
5236 View Code Duplication
            } else {
5237
                $force_download_html = ($size == 0) ? '' : '<a href="' . $forcedownload_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5238
                    Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL) . '</a>';
5239
            }
5240
5241
            // Copy files to users myfiles
5242
            if (api_get_setting('allow_social_tool') == 'true' &&
5243
                api_get_setting('users_copy_files') == 'true' &&
5244
                !api_is_anonymous()
5245
            ) {
5246
                $copy_myfiles_link = ($filetype == 'file') ? api_get_self() . '?' . api_get_cidreq() . '&action=copytomyfiles&id=' . $document_data['id'] : api_get_self() . '?' . api_get_cidreq();
5247
5248 View Code Duplication
                if ($filetype == 'file') {
5249
5250
                    $copy_to_myfiles = '<a href="' . $copy_myfiles_link . '" style="float:right"' . $prevent_multiple_click . '>' .
5251
                        Display::return_icon('briefcase.png', get_lang('CopyToMyFiles'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5252
5253
                    if (api_get_setting('allow_my_files') === 'false') {
5254
                        $copy_to_myfiles = '';
5255
                    }
5256
                }
5257
5258
                if ($filetype == 'file') {
5259
                    $send_to = Portfolio::share('document', $document_data['id'], array('style' => 'float:right;'));
5260
                }
5261
            }
5262
5263
            $pdf_icon = '';
5264
            $extension = pathinfo($path, PATHINFO_EXTENSION);
5265
            if (!api_is_allowed_to_edit() &&
5266
                api_get_setting('students_export2pdf') == 'true' &&
5267
                $filetype == 'file' &&
5268
                in_array($extension, array('html', 'htm'))
5269
            ) {
5270
                $pdf_icon = ' <a style="float:right".' . $prevent_multiple_click . ' href="' . api_get_self() . '?' . api_get_cidreq() . '&action=export_to_pdf&id=' . $document_data['id'] . '">' .
5271
                    Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a> ';
5272
            }
5273
5274 View Code Duplication
            if ($is_browser_viewable_file) {
5275
                $open_in_new_window_link = '<a href="' . $www . str_replace('%2F', '/', $url_path) . '?' . api_get_cidreq() . '" style="float:right"' . $prevent_multiple_click . ' target="_blank">' .
5276
                    Display::return_icon('open_in_new_window.png', get_lang('OpenInANewWindow'), array(), ICON_SIZE_SMALL) . '&nbsp;&nbsp;</a>';
5277
            }
5278
5279
            if ($filetype == 'file') {
5280
                // Sound preview with jplayer
5281
                if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5282
                    (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5283
                    preg_match('/ogg$/i', urldecode($checkExtension))
5284
                ) {
5285
                    return '<span style="float:left" ' . $visibility_class . '>' .
5286
                    $title .
5287
                    '</span>' . $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5288
                } elseif (
5289
5290
                    // Show preview
5291
                    preg_match('/swf$/i', urldecode($checkExtension)) ||
5292
                    preg_match('/png$/i', urldecode($checkExtension)) ||
5293
                    preg_match('/gif$/i', urldecode($checkExtension)) ||
5294
                    preg_match('/jpg$/i', urldecode($checkExtension)) ||
5295
                    preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5296
                    preg_match('/bmp$/i', urldecode($checkExtension)) ||
5297
                    preg_match('/svg$/i', urldecode($checkExtension)) ||
5298
                    (
5299
                        preg_match('/wav$/i', urldecode($checkExtension)) &&
5300
                        preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5301
                        api_get_setting('enable_nanogong') == 'true'
5302
                    )
5303
                ) {
5304
                    // Simpler version of showinframesmin.php with no headers
5305
                    $url = 'show_content.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5306
                    $class = 'ajax';
5307
                    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...
5308
                        $class = "ajax invisible";
5309
                    }
5310
                    return Display::url(
5311
                        $title,
5312
                        $url,
5313
                        [
5314
                            'class' => $class,
5315
                            'title' => $tooltip_title_alt,
5316
                            'data-title' => $title,
5317
                            'style' => 'float: left;'
5318
                        ]
5319
                    )
5320
                    . $force_download_html . $send_to . $copy_to_myfiles
5321
                    . $open_in_new_window_link . $pdf_icon;
5322
                } else {
5323
                    // For PDF Download the file.
5324
                    $pdfPreview = null;
5325
                    if ($ext != 'pdf' && !in_array($ext, $webOdflist)) {
5326
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5327
                    } else {
5328
                        $pdfPreview = Display::url(
5329
                            Display::return_icon('preview.gif', get_lang('Preview')),
5330
                            api_get_path(WEB_CODE_PATH).'document/showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'],
5331
                            array('style' => 'float:right')
5332
                        );
5333
                    }
5334
                    // No plugin just the old and good showinframes.php page
5335
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" style="float:left" ' . $visibility_class . ' >' . $title . '</a>' .
5336
                    $pdfPreview.$force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5337
                }
5338
            } else {
5339
                return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' . $title . '</a>' .
5340
                $force_download_html . $send_to . $copy_to_myfiles . $open_in_new_window_link . $pdf_icon;
5341
            }
5342
            // end copy files to users myfiles
5343
        } else {
5344
            // Icon column
5345
            if (preg_match('/shared_folder/', urldecode($checkExtension)) &&
5346
                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...
5347
                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...
5348
            ) {
5349
                if ($filetype == 'file') {
5350
                    //Sound preview with jplayer
5351
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5352
                        (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5353
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5354
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5355
5356
                        return $sound_preview;
5357
                    } elseif (
5358
                        // Show preview
5359
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5360
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5361
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5362
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5363
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5364
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5365
                        preg_match('/svg$/i', urldecode($checkExtension)) ||
5366
                        (
5367
                            preg_match('/wav$/i', urldecode($checkExtension)) &&
5368
                            preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5369
                            api_get_setting('enable_nanogong') == 'true'
5370
                        )
5371
                    ) {
5372
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
5373
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5374
                        DocumentManager::build_document_icon_tag($filetype, $path) .
5375
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5376 View Code Duplication
                    } else {
5377
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5378
                        DocumentManager::build_document_icon_tag($filetype, $path) .
5379
                        Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5380
                    }
5381 View Code Duplication
                } else {
5382
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5383
                    DocumentManager::build_document_icon_tag($filetype, $path) .
5384
                    Display::return_icon('shared.png', get_lang('ResourceShared'), array()) . '</a>';
5385
                }
5386
            } else {
5387
                if ($filetype == 'file') {
5388
                    // Sound preview with jplayer
5389
                    if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
5390
                        (preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
5391
                        preg_match('/ogg$/i', urldecode($checkExtension))) {
5392
                        $sound_preview = DocumentManager::generate_media_preview($counter);
5393
5394
                        return $sound_preview;
5395
                    } elseif (
5396
                        //Show preview
5397
                        preg_match('/html$/i', urldecode($checkExtension)) ||
5398
                        preg_match('/htm$/i', urldecode($checkExtension)) ||
5399
                        preg_match('/swf$/i', urldecode($checkExtension)) ||
5400
                        preg_match('/png$/i', urldecode($checkExtension)) ||
5401
                        preg_match('/gif$/i', urldecode($checkExtension)) ||
5402
                        preg_match('/jpg$/i', urldecode($checkExtension)) ||
5403
                        preg_match('/jpeg$/i', urldecode($checkExtension)) ||
5404
                        preg_match('/bmp$/i', urldecode($checkExtension)) ||
5405
                        preg_match('/svg$/i', urldecode($checkExtension)) ||
5406
                        (
5407
                            preg_match('/wav$/i', urldecode($checkExtension)) &&
5408
                            preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
5409
                            api_get_setting('enable_nanogong') == 'true'
5410
                        )
5411
                    ) {
5412
                        $url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id']; //without preview
5413
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5414
                        DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5415 View Code Duplication
                    } else {
5416
                        return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
5417
                        DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5418
                    }
5419 View Code Duplication
                } else {
5420
                    return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" target="' . $target . '"' . $visibility_class . ' style="float:left">' .
5421
                    DocumentManager::build_document_icon_tag($filetype, $path) . '</a>';
5422
                }
5423
            }
5424
        }
5425
    }
5426
5427
    /**
5428
     * Builds an img html tag for the file type
5429
     *
5430
     * @param string $type (file/folder)
5431
     * @param string $path
5432
     * @return string img html tag
5433
     */
5434
    public static function build_document_icon_tag($type, $path)
5435
    {
5436
        $basename = basename($path);
5437
        $current_session_id = api_get_session_id();
5438
        $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
5439
        $user_image = false;
5440
        if ($type == 'file') {
5441
            $icon = choose_image($basename);
5442
5443
            if (preg_match('/_chnano_.wav$/i', $basename)) {
5444
                $icon = "jplayer_play.png";
5445
                $basename = 'wav' . ' ' . '(Nanogong)';
5446
            } else {
5447
                $basename = substr(strrchr($basename, '.'), 1);
5448
            }
5449
        } else {
5450
            if ($path == '/shared_folder') {
5451
                $icon = 'folder_users.gif';
5452
                if ($is_allowed_to_edit) {
5453
                    $basename = get_lang('HelpUsersFolder');
5454
                } else {
5455
                    $basename = get_lang('UserFolders');
5456
                }
5457
            } elseif (strstr($basename, 'sf_user_')) {
5458
                $userinfo = api_get_user_info(substr($basename, 8));
5459
                $icon = $userinfo['avatar_small'];
5460
5461
                $basename = get_lang('UserFolder') . ' ' . $userinfo['complete_name'];
5462
                $user_image = true;
5463
            } elseif (strstr($path, 'shared_folder_session_')) {
5464
                if ($is_allowed_to_edit) {
5465
                    $basename = '***(' . api_get_session_name($current_session_id) . ')*** ' . get_lang('HelpUsersFolder');
5466
                } else {
5467
                    $basename = get_lang('UserFolders') . ' (' . api_get_session_name($current_session_id) . ')';
5468
                }
5469
                $icon = 'folder_users.gif';
5470
            } else {
5471
                $icon = 'folder_document.gif';
5472
5473
                if ($path == '/audio') {
5474
                    $icon = 'folder_audio.gif';
5475
                    if (api_is_allowed_to_edit()) {
5476
                        $basename = get_lang('HelpDefaultDirDocuments');
5477
                    } else {
5478
                        $basename = get_lang('Audio');
5479
                    }
5480 View Code Duplication
                } elseif ($path == '/flash') {
5481
                    $icon = 'folder_flash.gif';
5482
                    if (api_is_allowed_to_edit()) {
5483
                        $basename = get_lang('HelpDefaultDirDocuments');
5484
                    } else {
5485
                        $basename = get_lang('Flash');
5486
                    }
5487
                } elseif ($path == '/images') {
5488
                    $icon = 'folder_images.gif';
5489
                    if (api_is_allowed_to_edit()) {
5490
                        $basename = get_lang('HelpDefaultDirDocuments');
5491
                    } else {
5492
                        $basename = get_lang('Images');
5493
                    }
5494 View Code Duplication
                } elseif ($path == '/video') {
5495
                    $icon = 'folder_video.gif';
5496
                    if (api_is_allowed_to_edit()) {
5497
                        $basename = get_lang('HelpDefaultDirDocuments');
5498
                    } else {
5499
                        $basename = get_lang('Video');
5500
                    }
5501
                } elseif ($path == '/images/gallery') {
5502
                    $icon = 'folder_gallery.gif';
5503
                    if (api_is_allowed_to_edit()) {
5504
                        $basename = get_lang('HelpDefaultDirDocuments');
5505
                    } else {
5506
                        $basename = get_lang('Gallery');
5507
                    }
5508
                } elseif ($path == '/chat_files') {
5509
                    $icon = 'folder_chat.png';
5510
                    if (api_is_allowed_to_edit()) {
5511
                        $basename = get_lang('HelpFolderChat');
5512
                    } else {
5513
                        $basename = get_lang('ChatFiles');
5514
                    }
5515
                } elseif ($path == '/learning_path') {
5516
                    $icon = 'folder_learningpath.gif';
5517
                    if (api_is_allowed_to_edit()) {
5518
                        $basename = get_lang('HelpFolderLearningPaths');
5519
                    } else {
5520
                        $basename = get_lang('LearningPaths');
5521
                    }
5522
                }
5523
            }
5524
        }
5525
        if ($user_image) {
5526
            return Display::img($icon, $basename, array(), false);
5527
        }
5528
        return Display::return_icon($icon, $basename, array());
5529
    }
5530
5531
    /**
5532
     * Creates the row of edit icons for a file/folder
5533
     *
5534
     * @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...
5535
     * @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...
5536
     * @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...
5537
     * @param int $visibility (1/0)
5538
     * @param int $id dbase id of the document
5539
     * @return string html img tags with hyperlinks
5540
     */
5541
    public static function build_edit_icons($document_data, $id, $is_template, $is_read_only = 0, $visibility)
5542
    {
5543
        $web_odf_extension_list = DocumentManager::get_web_odf_extension_list();
5544
        $document_id = $document_data['id'];
5545
        $type = $document_data['filetype'];
5546
        $is_read_only = $document_data['readonly'];
5547
        $path = $document_data['path'];
5548
        $parent_id = DocumentManager::get_document_id(api_get_course_info(), dirname($path));
5549
        $curdirpath = dirname($document_data['path']);
5550
        $is_certificate_mode = DocumentManager::is_certificate_mode($path);
5551
        $curdirpath = urlencode($curdirpath);
5552
        $extension = pathinfo($path, PATHINFO_EXTENSION);
5553
        //@todo Implement remote support for converter
5554
        $usePpt2lp = (api_get_setting('service_ppt2lp', 'active') == 'true' && api_get_setting('service_ppt2lp', 'host') == 'localhost');
5555
        $formatTypeList = DocumentManager::getFormatTypeListConvertor('from', $extension);
5556
        $formatType = current($formatTypeList);
5557
5558
        // Build URL-parameters for table-sorting
5559
        $sort_params = array();
5560
        if (isset($_GET['column'])) {
5561
            $sort_params[] = 'column=' . Security::remove_XSS($_GET['column']);
5562
        }
5563
        if (isset($_GET['page_nr'])) {
5564
            $sort_params[] = 'page_nr=' . Security::remove_XSS($_GET['page_nr']);
5565
        }
5566
        if (isset($_GET['per_page'])) {
5567
            $sort_params[] = 'per_page=' . Security::remove_XSS($_GET['per_page']);
5568
        }
5569
        if (isset($_GET['direction'])) {
5570
            $sort_params[] = 'direction=' . Security::remove_XSS($_GET['direction']);
5571
        }
5572
        $sort_params = implode('&amp;', $sort_params);
5573
        $visibility_icon = ($visibility == 0) ? 'invisible' : 'visible';
5574
        $visibility_command = ($visibility == 0) ? 'set_visible' : 'set_invisible';
5575
5576
        $modify_icons = '';
5577
5578
        // If document is read only *or* we're in a session and the document
5579
        // is from a non-session context, hide the edition capabilities
5580
        if ($is_read_only /* or ($session_id!=api_get_session_id()) */) {
5581
            if (api_is_course_admin() || api_is_platform_admin()) {
5582 View Code Duplication
                if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5583
                    $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5584
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5585
                } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5586
                    $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5587
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5588
                } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5589
                    $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&id=' . $document_id . '">' .
5590
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5591
                } else {
5592
                    $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&id=' . $document_id. '">' .
5593
                        Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5594
                }
5595
            } else {
5596
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5597
            }
5598
            $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL);
5599
            if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5600
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), '', ICON_SIZE_SMALL);
5601
            }
5602
            $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('Delete'), array(), ICON_SIZE_SMALL);
5603
        } else {
5604
            //Edit button
5605
            if (in_array($path, DocumentManager::get_system_folders())) {
5606
                $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
5607 View Code Duplication
            } elseif ($is_certificate_mode ) {
5608
                // gradebook category doesn't seem to be taken into account
5609
                $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id . '&curdirpath=/certificates">' . Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5610
            } else {
5611
                if (api_get_session_id()) {
5612
                    if ($document_data['session_id'] == api_get_session_id()) {
5613 View Code Duplication
                        if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5614
                            $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5615
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5616
                        } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5617
                            $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5618
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5619
                        } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5620
                            $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5621
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5622
                        } else {
5623
                            $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5624
                                Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5625
                        }
5626
                    } else {
5627
                        $modify_icons .= '&nbsp;' . Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>';
5628
                    }
5629 View Code Duplication
                } else {
5630
                    if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
5631
                        $modify_icons = '<a href="edit_draw.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5632
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5633
                    } elseif (in_array($extension, $web_odf_extension_list)  && api_get_setting('enabled_support_odf') === true) {
5634
                        $modify_icons = '<a href="edit_odf.php?' . api_get_cidreq() . '&id=' . $document_id  . '">' .
5635
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5636
                    } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
5637
                        $modify_icons = '<a href="edit_paint.php?' . api_get_cidreq() . '&amp;id=' . $document_id . '">' .
5638
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5639
                    } else {
5640
                        $modify_icons = '<a href="edit_document.php?' . api_get_cidreq() . '&amp;id=' . $document_id  . '">' .
5641
                            Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL) . '</a>';
5642
                    }
5643
                }
5644
            }
5645
5646
            // Move button.
5647
            if ($is_certificate_mode || in_array($path, DocumentManager::get_system_folders())) {
5648
                $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5649
            } else {
5650
                if (api_get_session_id()) {
5651
                    if ($document_data['session_id'] == api_get_session_id()) {
5652
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5653
                            Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5654
                    } else {
5655
                        $modify_icons .= '&nbsp;' . Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5656
                    }
5657
                } else {
5658
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;move=' . $document_id .  '">' .
5659
                        Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL) . '</a>';
5660
                }
5661
            }
5662
5663
            //Visibility button
5664
            if ($is_certificate_mode) {
5665
                $modify_icons .= '&nbsp;' . Display::return_icon($visibility_icon . '.png', get_lang('VisibilityCannotBeChanged'), array(), ICON_SIZE_SMALL) . '</a>';
5666
            } else {
5667
                if (api_is_allowed_to_edit() || api_is_platform_admin()) {
5668
                    if ($visibility_icon == 'invisible') {
5669
                        $tip_visibility = get_lang('Show');
5670
                    } else {
5671
                        $tip_visibility = get_lang('Hide');
5672
                    }
5673
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;id=' . $parent_id . '&amp;' . $visibility_command . '=' . $id . '&amp;' . $sort_params . '">' .
5674
                        Display::return_icon($visibility_icon . '.png', $tip_visibility, '', ICON_SIZE_SMALL) . '</a>';
5675
                }
5676
            }
5677
5678
            // Delete button
5679
            if (in_array($path, DocumentManager::get_system_folders())) {
5680
                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5681
            } else {
5682
                $titleToShow = addslashes(basename($document_data['title']));
5683
5684
                if (isset($_GET['curdirpath']) &&
5685
                    $_GET['curdirpath'] == '/certificates' &&
5686
                    DocumentManager::get_default_certificate_id(api_get_course_id()) == $id
5687
                ) {
5688
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;' . $sort_params . 'delete_certificate_id=' . $id . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5689
                        Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5690
                } else {
5691
                    if ($is_certificate_mode) {
5692
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid=' . $document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">' .
5693
                            Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5694
                    } else {
5695
                        if (api_get_session_id()) {
5696
                            if ($document_data['session_id'] == api_get_session_id()) {
5697
                                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id  . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow . '\');">'.
5698
                                    Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5699
                            } else {
5700
                                $modify_icons .= '&nbsp;' . Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
5701
                            }
5702
                        } else {
5703
                            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&action=delete_item&id='.$parent_id.'&deleteid='.$document_id . '&amp;' . $sort_params . '" onclick="return confirmation(\'' . $titleToShow. '\');">' .
5704
                                Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
5705
                        }
5706
                    }
5707
                }
5708
            }
5709
5710
            // Add action to covert to PDF, will create a new document whit same filename but .pdf extension
5711
            // @TODO: add prompt to select a format target
5712
            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...
5713
                // nothing to do
5714 View Code Duplication
            } else {
5715
                if ($usePpt2lp && $formatType) {
5716
                    $modify_icons .= '&nbsp;<a class="convertAction" href="#" ' .
5717
                        'data-documentId = ' . $document_id .
5718
                        ' data-formatType = ' . $formatType . '>' .
5719
                        Display::return_icon(
5720
                            'convert.png',
5721
                            get_lang('Convert'),
5722
                            array(),
5723
                            ICON_SIZE_SMALL
5724
                        ) . '</a>';
5725
                }
5726
            }
5727
        }
5728
5729
        if ($type == 'file' && ($extension == 'html' || $extension == 'htm')) {
5730
            if ($is_template == 0) {
5731
                if ((isset($_GET['curdirpath']) && $_GET['curdirpath'] != '/certificates') || !isset($_GET['curdirpath'])) {
5732
                    $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;add_as_template=' . $id .  '&amp;' . $sort_params . '">' .
5733
                        Display::return_icon('wizard.png', get_lang('AddAsTemplate'), array(), ICON_SIZE_SMALL) . '</a>';
5734
                }
5735
                if (isset($_GET['curdirpath']) && $_GET['curdirpath'] == '/certificates') {//allow attach certificate to course
5736
                    $visibility_icon_certificate = 'nocertificate';
5737
                    if (DocumentManager::get_default_certificate_id(api_get_course_id()) == $id) {
5738
                        $visibility_icon_certificate = 'certificate';
5739
                        $certificate = get_lang('DefaultCertificate');
5740
                        $preview = get_lang('PreviewCertificate');
5741
                        $is_preview = true;
5742
                    } else {
5743
                        $is_preview = false;
5744
                        $certificate = get_lang('NoDefaultCertificate');
5745
                    }
5746
                    if (isset($_GET['selectcat'])) {
5747
                        $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;selectcat=' . Security::remove_XSS($_GET['selectcat']) . '&amp;set_certificate=' . $id . '&amp;' . $sort_params . '">
5748
                    <img src="../img/' . $visibility_icon_certificate . '.png" border="0" title="' . $certificate . '" alt="" /></a>';
5749
                        if ($is_preview) {
5750
                            $modify_icons .= '&nbsp;<a target="_blank"  href="' . api_get_self() . '?' . api_get_cidreq() . '&amp;curdirpath=' . $curdirpath . '&amp;set_preview=' . $id . '&amp;' . $sort_params . '" >' .
5751
                                Display::return_icon('preview_view.png', $preview, '', ICON_SIZE_SMALL) . '</a>';
5752
                        }
5753
                    }
5754
                }
5755
            } else {
5756
                $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&curdirpath=' . $curdirpath . '&amp;remove_as_template=' . $id. '&amp;' . $sort_params . '">' .
5757
                    Display::return_icon('wizard_na.png', get_lang('RemoveAsTemplate'), '', ICON_SIZE_SMALL) . '</a>';
5758
            }
5759
            $modify_icons .= '&nbsp;<a href="' . api_get_self() . '?' . api_get_cidreq() . '&action=export_to_pdf&id=' . $id . '">' .
5760
                Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL) . '</a>';
5761
        }
5762
        return $modify_icons;
5763
    }
5764
5765
    /**
5766
     * @param $folders
5767
     * @param $curdirpath
5768
     * @param $move_file
5769
     * @param string $group_dir
5770
     * @return string
5771
     */
5772
    public static function build_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
5773
    {
5774
        $form = new FormValidator('move_to', 'post', api_get_self().'?'.api_get_cidreq());
5775
5776
        // Form title
5777
        $form->addElement('hidden', 'move_file', $move_file);
5778
5779
        $options = array();
5780
5781
        // Group documents cannot be uploaded in the root
5782
        if ($group_dir == '') {
5783
            if ($curdirpath != '/') {
5784
                $options['/'] = get_lang('Documents');
5785
            }
5786
5787
            if (is_array($folders)) {
5788
                foreach ($folders as & $folder) {
5789
                    // Hide some folders
5790
                    if ($folder == '/HotPotatoes_files' ||
5791
                        $folder == '/certificates' ||
5792
                        basename($folder) == 'css'
5793
                    ) {
5794
                        continue;
5795
                    }
5796
                    // Admin setting for Hide/Show the folders of all users
5797 View Code Duplication
                    if (api_get_setting('show_users_folders') == 'false' &&
5798
                        (strstr($folder, '/shared_folder') || strstr($folder, 'shared_folder_session_'))
5799
                    ) {
5800
                        continue;
5801
                    }
5802
5803
                    // Admin setting for Hide/Show Default folders to all users
5804 View Code Duplication
                    if (api_get_setting('show_default_folders') == 'false' &&
5805
                        (
5806
                            $folder == '/images' ||
5807
                            $folder == '/flash' ||
5808
                            $folder == '/audio' ||
5809
                            $folder == '/video' ||
5810
                            strstr($folder, '/images/gallery') ||
5811
                            $folder == '/video/flv'
5812
                        )
5813
                    ) {
5814
                        continue;
5815
                    }
5816
5817
                    // Admin setting for Hide/Show chat history folder
5818
                    if (api_get_setting('show_chat_folder') == 'false' &&
5819
                        $folder == '/chat_files') {
5820
                        continue;
5821
                    }
5822
5823
                    // You cannot move a file to:
5824
                    // 1. current directory
5825
                    // 2. inside the folder you want to move
5826
                    // 3. inside a subfolder of the folder you want to move
5827
                    if (($curdirpath != $folder) &&
5828
                        ($folder != $move_file) &&
5829
                        (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5830
                    ) {
5831
                        $path_displayed = $folder;
5832
                        // If document title is used, we have to display titles instead of real paths...
5833
                        $path_displayed = DocumentManager::get_titles_of_path($folder);
5834
5835
                        if (empty($path_displayed)) {
5836
                            $path_displayed = get_lang('Untitled');
5837
                        }
5838
                        $options[$folder] = $path_displayed;
5839
                    }
5840
                }
5841
            }
5842
        } else {
5843
            foreach ($folders as $folder) {
5844
                if (($curdirpath != $folder) &&
5845
                    ($folder != $move_file) &&
5846
                    (substr($folder, 0, strlen($move_file) + 1) != $move_file . '/')
5847
                ) {
5848
                    // Cannot copy dir into his own subdir
5849
                    $path_displayed = DocumentManager::get_titles_of_path($folder);
5850
                    $display_folder = substr($path_displayed, strlen($group_dir));
5851
                    $display_folder = ($display_folder == '') ? get_lang('Documents') : $display_folder;
5852
                    //$form .= '<option value="'.$folder.'">'.$display_folder.'</option>';
5853
                    $options[$folder] = $display_folder;
5854
                }
5855
            }
5856
        }
5857
        $form->addElement('select', 'move_to', get_lang('MoveTo'), $options);
5858
        $form->addButtonNext(get_lang('MoveElement'), 'move_file_submit');
5859
        return $form->returnForm();
5860
    }
5861
5862
    /**
5863
     * Gets the path translated with title of docs and folders
5864
     * @param string $path the real path
5865
     * @return the path which should be displayed
5866
     */
5867
    public static function get_titles_of_path($path)
5868
    {
5869
        global $tmp_folders_titles;
5870
        $course_id = api_get_course_int_id();
5871
        $nb_slashes = substr_count($path, '/');
5872
        $current_slash_pos = 0;
5873
        $path_displayed = '';
5874
        for ($i = 0; $i < $nb_slashes; $i++) {
5875
            // For each folder of the path, retrieve title.
5876
            $current_slash_pos = strpos($path, '/', $current_slash_pos + 1);
5877
            $tmp_path = substr($path, strpos($path, '/', 0), $current_slash_pos);
5878
5879
            if (empty($tmp_path)) {
5880
                // If empty, then we are in the final part of the path
5881
                $tmp_path = $path;
5882
            }
5883
5884
            if (!empty($tmp_folders_titles[$tmp_path])) {
5885
                // If this path has soon been stored here we don't need a new query
5886
                $path_displayed .= $tmp_folders_titles[$tmp_path];
5887
            } else {
5888
                $sql = 'SELECT title FROM ' . Database::get_course_table(TABLE_DOCUMENT) . '
5889
                    WHERE c_id = ' . $course_id . ' AND path LIKE BINARY "' . $tmp_path . '"';
5890
                $rs = Database::query($sql);
5891
                $tmp_title = '/' . Database::result($rs, 0, 0);
5892
                $path_displayed .= $tmp_title;
5893
                $tmp_folders_titles[$tmp_path] = $tmp_title;
5894
            }
5895
        }
5896
        return $path_displayed;
5897
    }
5898
5899
    /**
5900
     * Creates form that asks for the directory name.
5901
     * @return string	html-output text for the form
5902
     */
5903
    public static function create_dir_form($dirId)
5904
    {
5905
        global $document_id;
5906
        $form = new FormValidator('create_dir_form', 'post', api_get_self().'?'.api_get_cidreq());
5907
        $form->addElement('hidden', 'create_dir', 1);
5908
        $form->addElement('hidden', 'dir_id', intval($document_id));
5909
        $form->addElement('hidden', 'id', intval($dirId));
5910
        $form->addElement('header', get_lang('CreateDir'));
5911
        $form->addText('dirname', get_lang('NewDir'), array('autofocus' => 'autofocus'));
5912
        $form->addButtonCreate(get_lang('CreateFolder'));
5913
5914
        return $form->returnForm();
5915
5916
    }
5917
5918
    /**
5919
     * Checks whether the user is in shared folder
5920
     * @return return bool Return true when user is into shared folder
5921
     */
5922
    public static function is_shared_folder($curdirpath, $current_session_id)
5923
    {
5924
        $clean_curdirpath = Security::remove_XSS($curdirpath);
5925
        if ($clean_curdirpath == '/shared_folder') {
5926
            return true;
5927
        } elseif ($clean_curdirpath == '/shared_folder_session_' . $current_session_id) {
5928
            return true;
5929
        } else {
5930
            return false;
5931
        }
5932
    }
5933
5934
    /**
5935
     * Checks whether the user is into any user shared folder
5936
     * @return return bool Return true when user is in any user shared folder
5937
     */
5938
    public static function is_any_user_shared_folder($path, $current_session_id)
5939
    {
5940
        $clean_path = Security::remove_XSS($path);
5941
        if (strpos($clean_path, 'shared_folder/sf_user_')) {
5942
            return true;
5943
        } elseif (strpos($clean_path, 'shared_folder_session_' . $current_session_id . '/sf_user_')) {
5944
            return true;
5945
        } else {
5946
            return false;
5947
        }
5948
    }
5949
5950
    /**
5951
     * Checks whether the user is into his shared folder or into a subfolder
5952
     * @return bool Return true when user is in his user shared folder or into a subfolder
5953
     */
5954
    public static function is_my_shared_folder($user_id, $path, $current_session_id)
5955
    {
5956
        $clean_path = Security::remove_XSS($path) . '/';
5957
        //for security does not remove the last slash
5958
        $main_user_shared_folder = '/shared_folder\/sf_user_' . $user_id . '\//';
5959
        //for security does not remove the last slash
5960
        $main_user_shared_folder_session = '/shared_folder_session_' . $current_session_id . '\/sf_user_' . $user_id . '\//';
5961
5962
        if (preg_match($main_user_shared_folder, $clean_path)) {
5963
            return true;
5964
        } elseif (preg_match($main_user_shared_folder_session, $clean_path)) {
5965
            return true;
5966
        } else {
5967
            return false;
5968
        }
5969
    }
5970
5971
    /**
5972
     * Check if the file name or folder searched exist
5973
     * @return bool Return true when exist
5974
     */
5975
    public static function search_keyword($document_name, $keyword)
5976
    {
5977
        if (api_strripos($document_name, $keyword) !== false) {
5978
            return true;
5979
        } else {
5980
            return false;
5981
        }
5982
    }
5983
5984
    /**
5985
     * Checks whether a document can be previewed by using the browser.
5986
     * @param string $file_extension    The filename extension of the document (it must be in lower case).
5987
     * @return bool                     Returns TRUE or FALSE.
5988
     */
5989
    public static function is_browser_viewable($file_extension)
5990
    {
5991
        static $allowed_extensions = array(
5992
            'htm', 'html', 'xhtml',
5993
            'gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff',
5994
            'pdf', 'svg', 'swf',
5995
            'txt', 'log',
5996
            'mp4', 'ogg', 'ogv', 'ogx', 'mpg', 'mpeg', 'mov', 'avi', 'webm', 'wmv',
5997
            'mp3', 'oga', 'wav', 'au', 'wma', 'mid', 'kar'
5998
        );
5999
6000
        /*
6001
          //TODO: make a admin swich to strict mode
6002
          1. global default $allowed_extensions only: 'htm', 'html', 'xhtml', 'gif', 'jpg', 'jpeg', 'png', 'bmp', 'txt', 'log'
6003
          if (in_array($file_extension, $allowed_extensions)) { // Assignment + a logical check.
6004
          return true;
6005
          }
6006
          2. check native support
6007
          3. check plugins: quicktime, mediaplayer, vlc, acrobat, flash, java
6008
         */
6009
6010
        if (!($result = in_array($file_extension, $allowed_extensions))) { // Assignment + a logical check.
6011
            return false;
6012
        }
6013
        //check native support (Explorer, Opera, Firefox, Chrome, Safari)
6014
6015
        if ($file_extension == "pdf") {
6016
            return api_browser_support('pdf');
6017
        } elseif ($file_extension == "mp3") {
6018
            return api_browser_support('mp3');
6019
        } elseif ($file_extension == "mp4") {
6020
            return api_browser_support('mp4');
6021
        } elseif ($file_extension == "ogg" || $file_extension == "ogx" || $file_extension == "ogv" || $file_extension == "oga") {
6022
            return api_browser_support('ogg');
6023
        } elseif ($file_extension == "svg") {
6024
            return api_browser_support('svg');
6025
        } elseif ($file_extension == "mpg" || $file_extension == "mpeg") {
6026
            return api_browser_support('mpg');
6027
        } elseif ($file_extension == "mov") {
6028
            return api_browser_support('mov');
6029
        } elseif ($file_extension == "wav") {
6030
            return api_browser_support('wav');
6031
        } elseif ($file_extension == "mid" || $file_extension == "kar") {
6032
            return api_browser_support('mid');
6033
        } elseif ($file_extension == "avi") {
6034
            return api_browser_support('avi');
6035
        } elseif ($file_extension == "wma") {
6036
            return api_browser_support('wma');
6037
        } elseif ($file_extension == "wmv") {
6038
            return api_browser_support('wmv');
6039
        } elseif ($file_extension == "tif" || $file_extension == "tiff") {
6040
            return api_browser_support('tif');
6041
        } elseif ($file_extension == "mov") {
6042
            return api_browser_support('mov');
6043
        } elseif ($file_extension == "au") {
6044
            return api_browser_support('au');
6045
        } elseif ($file_extension == "webm") {
6046
            return api_browser_support('webm');
6047
        }
6048
        return $result;
6049
    }
6050
6051
    /**
6052
     * @param array $courseInfo
6053
     * @param int $sessionId
6054
     *
6055
     * @return array
6056
     */
6057
    public static function getDeletedDocuments($courseInfo, $sessionId = 0)
6058
    {
6059
        $table = Database::get_course_table(TABLE_DOCUMENT);
6060
        $courseId = $courseInfo['real_id'];
6061
        $sessionCondition = api_get_session_condition($sessionId);
6062
        $sql = "SELECT * FROM $table
6063
                WHERE
6064
                  path LIKE '%DELETED%' AND
6065
                  c_id = $courseId
6066
                  $sessionCondition
6067
                ORDER BY path
6068
        ";
6069
6070
        $result = Database::query($sql);
6071
        $files = array();
6072
        while ($document = Database::fetch_array($result, 'ASSOC')) {
6073
            $files[] = $document;
6074
        }
6075
6076
        return $files;
6077
    }
6078
6079
    /**
6080
     * @param int $id
6081
     * @param array $courseInfo
6082
     * @param int $sessionId
6083
     *
6084
     * @return array
6085
     */
6086
    public static function getDeletedDocument($id, $courseInfo, $sessionId = 0)
6087
    {
6088
        if (empty($courseInfo)) {
6089
            return false;
6090
        }
6091
6092
        $table = Database::get_course_table(TABLE_DOCUMENT);
6093
        $courseId = $courseInfo['real_id'];
6094
        $sessionCondition = api_get_session_condition($sessionId);
6095
        $sql = "SELECT * FROM $table
6096
                WHERE
6097
                  path LIKE '%DELETED%' AND
6098
                  id = $id AND
6099
                  c_id = $courseId
6100
                  $sessionCondition
6101
                LIMIT 1
6102
        ";
6103
        $result = Database::query($sql);
6104
        if (Database::num_rows($result)) {
6105
            $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...
6106
6107
            return $result;
6108
        }
6109
6110
        return array();
6111
    }
6112
6113
    /**
6114
     * @param int $id
6115
     * @param array $courseInfo
6116
     * @param int $sessionId
6117
     * @return bool
6118
     */
6119
    public static function purgeDocument($id, $courseInfo, $sessionId = 0)
6120
    {
6121
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6122 View Code Duplication
        if (!empty($document)) {
6123
            $path = $document['path'];
6124
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6125
            my_delete($coursePath.$path);
6126
            // Hard delete.
6127
            self::deleteDocumentFromDb($id, $courseInfo, $sessionId, true);
6128
6129
            return true;
6130
        }
6131
        return false;
6132
    }
6133
6134
    /**
6135
     * @param array $courseInfo
6136
     * @param int $sessionId
6137
     */
6138
    public static function purgeDocuments($courseInfo, $sessionId)
6139
    {
6140
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6141
        foreach ($files as $file) {
6142
            self::purgeDocument($file['id'], $courseInfo, $sessionId);
6143
        }
6144
    }
6145
6146
    /**
6147
     * @param int $id
6148
     * @param array $courseInfo
6149
     * @param int $sessionId
6150
     * @return bool
6151
     */
6152
    public static function downloadDeletedDocument($id, $courseInfo, $sessionId)
6153
    {
6154
        $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
6155 View Code Duplication
        if (!empty($document)) {
6156
            $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
6157
6158
            if (Security::check_abs_path($coursePath.$document['path'], $coursePath)) {
6159
                self::file_send_for_download($coursePath.$document['path']);
6160
                exit;
6161
            }
6162
        }
6163
    }
6164
6165
    /**
6166
     * @param array $courseInfo
6167
     * @param int $sessionId
6168
     *
6169
     * @return bool
6170
     */
6171
    public static function downloadAllDeletedDocument($courseInfo, $sessionId)
6172
    {
6173
        // Zip library for creation of the zip file.
6174
        require api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
6175
6176
        $files = self::getDeletedDocuments($courseInfo, $sessionId);
6177
6178
        if (empty($files)) {
6179
            return false;
6180
        }
6181
6182
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
6183
6184
        // Creating a ZIP file.
6185
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
6186
        $zip = new PclZip($tempZipFile);
6187
        foreach ($files as $file) {
6188
            $zip->add(
6189
                $coursePath.$file['path'],
6190
                PCLZIP_OPT_REMOVE_PATH,
6191
                $coursePath
6192
            );
6193
        }
6194
6195 View Code Duplication
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
6196
            DocumentManager::file_send_for_download($tempZipFile, true);
6197
            @unlink($tempZipFile);
6198
            exit;
6199
        }
6200
    }
6201
6202
    /**
6203
     *
6204
     * Delete documents from a session in a course.
6205
     * @param array $courseInfo
6206
     * @param int $sessionId
6207
     *
6208
     * @return bool
6209
     */
6210
    public function deleteDocumentsFromSession($courseInfo, $sessionId)
6211
    {
6212
        if (empty($courseInfo)) {
6213
            return false;
6214
        }
6215
6216
        if (empty($sessionId)) {
6217
            return false;
6218
        }
6219
6220
        $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
6221
        $documentTable = Database::get_course_table(TABLE_DOCUMENT);
6222
6223
        $conditionSession = api_get_session_condition($sessionId, true, false, 'd.session_id');
6224
        $courseId = $courseInfo['real_id'];
6225
6226
        // get invisible folders
6227
        $sql = "SELECT DISTINCT d.id, path
6228
                FROM $itemPropertyTable i
6229
                INNER JOIN $documentTable d
6230
                ON (i.c_id = d.c_id)
6231
                WHERE
6232
                    d.id = i.ref AND
6233
                    i.tool = '" . TOOL_DOCUMENT . "'
6234
                    $conditionSession AND
6235
                    i.c_id = $courseId AND
6236
                    d.c_id = $courseId ";
6237
6238
        $result = Database::query($sql);
6239
        $documents = Database::store_result($result, 'ASSOC');
6240
        if ($documents) {
6241
            $course_dir = $courseInfo['directory'] . '/document';
6242
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
6243
            $base_work_dir = $sys_course_path . $course_dir;
6244
6245
            foreach ($documents as $document) {
6246
                $documentId = $document['id'];
6247
                DocumentManager::delete_document(
6248
                    $courseInfo,
6249
                    null,
6250
                    $base_work_dir,
6251
                    $sessionId,
6252
                    $documentId
6253
                );
6254
            }
6255
        }
6256
6257
        $sql = "DELETE FROM $documentTable
6258
                WHERE c_id = $courseId AND session_id = $sessionId";
6259
        Database::query($sql);
6260
6261
        $sql = "DELETE FROM $itemPropertyTable
6262
                WHERE c_id = $courseId AND session_id = $sessionId AND tool = '".TOOL_DOCUMENT."'";
6263
        Database::query($sql);
6264
    }
6265
}
6266