Completed
Push — 1.10.x ( 6bc0e1...b7a253 )
by Angel Fernando Quiroz
45:49
created

DocumentManager::build_directory_selector()   C

Complexity

Conditions 16
Paths 16

Size

Total Lines 75
Code Lines 52

Duplication

Lines 12
Ratio 16 %

Importance

Changes 0
Metric Value
cc 16
eloc 52
nc 16
nop 4
dl 12
loc 75
rs 5.3027
c 0
b 0
f 0

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