Passed
Push — 1.10.x ( 1f0c91...36635d )
by Angel Fernando Quiroz
43:44
created

DocumentManager   F

Complexity

Total Complexity 955

Size/Duplication

Total Lines 6264
Duplicated Lines 13.19 %

Coupling/Cohesion

Components 3
Dependencies 17

Importance

Changes 4
Bugs 2 Features 0
Metric Value
wmc 955
c 4
b 2
f 0
lcom 3
cbo 17
dl 826
loc 6264
rs 0.6314

93 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B get_course_quota() 0 20 5
B file_get_mime_type() 0 216 4
A file_visible_to_user() 0 21 2
C string_send_for_download() 10 66 9
A getSessionFolderFilters() 0 16 3
F get_all_document_data() 16 196 41
F get_all_document_folders() 0 172 20
C check_readonly() 0 80 16
A is_folder() 0 10 1
B deleteDocumentFromDb() 0 51 4
F delete_document() 12 193 29
A delete_document_from_search_engine() 23 23 3
B get_document_id() 15 30 5
D get_document_data_by_id() 0 91 13
A set_document_as_template() 0 15 1
B unset_document_as_template() 0 25 1
C is_visible() 6 70 7
F is_visible_by_id() 16 109 24
A attach_gradebook_certificate() 7 19 4
B get_default_certificate_id() 7 27 5
B replace_user_info_into_html() 0 43 4
B get_all_info_to_certificate() 0 104 6
B remove_attach_certificate() 7 25 6
B create_directory_certificate_in_course() 0 60 5
A get_document_id_of_directory_certificate() 0 9 1
A is_certificate_mode() 0 11 3
D get_resources_from_source_html() 185 280 66
D parse_HTML_attributes() 10 81 20
D replace_urls_inside_content_html_from_copy_course() 54 153 22
F replace_urls_inside_content_html_when_moving_file() 10 127 22
A export_to_pdf() 0 8 1
B write_resources_tree() 0 57 8
D check_visibility_tree() 0 43 10
D index_document() 17 192 31
A get_web_odf_extension_list() 0 4 1
D getJodconverterExtensionList() 30 111 19
A getFormatTypeListConvertor() 0 16 3
C is_folder_to_avoid() 7 53 10
A get_system_folders() 14 14 1
A getProtectedFolderFromStudent() 0 10 1
B getDocumentDefaultVisibility() 0 23 6
A updateVisibilityFromAllSessions() 0 22 3
A readNanogongFile() 0 11 1
A addFileToDocumentTool() 0 52 3
B convertWavToMp3() 0 23 6
C addAndConvertWavToMp3() 16 52 8
B generateAudioTempFile() 8 38 5
A removeGeneratedAudioTempFile() 7 10 4
A getDocumentByPathInCourse() 0 12 2
B createDefaultAudioFolder() 0 27 3
C generateDefaultCertificate() 0 90 7
A renameDocument() 0 17 1
A getDocumentSuffix() 0 10 3
A fixDocumentName() 0 15 3
A addSuffixToFileName() 0 17 4
B folderExists() 41 41 3
B documentExists() 44 44 3
A undoFixDocumentName() 0 20 3
A getUniqueFileName() 0 18 2
C build_directory_selector() 12 75 16
D build_document_icon_tag() 16 96 23
D file_send_for_download() 30 105 20
D upload_document() 9 124 13
C get_text_content() 0 73 20
B documents_total_space() 0 44 6
B display_quota() 0 43 5
A display_simple_quota() 0 10 1
A enough_space() 0 9 3
B generate_jplayer_jquery() 0 26 1
B generate_media_preview() 0 33 2
A generate_video_preview() 0 48 1
F get_document_preview() 49 282 33
F parseFile() 11 82 10
D parseFolder() 0 75 15
F create_document_link() 40 316 104
F build_edit_icons() 58 224 83
D build_move_to_selector() 17 89 29
B get_titles_of_path() 0 31 4
A create_dir_form() 0 14 1
A is_shared_folder() 0 11 3
A is_any_user_shared_folder() 0 11 3
A is_my_shared_folder() 0 16 3
A search_keyword() 0 8 2
C is_browser_viewable() 0 61 24
A getDeletedDocuments() 0 21 2
B getDeletedDocument() 0 26 3
A purgeDocument() 9 14 2
A purgeDocuments() 0 7 2
A downloadDeletedDocument() 8 12 3
B downloadAllDeletedDocument() 5 30 4
B deleteDocumentsFromSession() 0 55 5
A generateFinalItemDocument() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DocumentManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DocumentManager, and based on these observations, apply Extract Interface, too.

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

There are different options of fixing this problem.

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

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

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

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

There are different options of fixing this problem.

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

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

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

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

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

Consider the follow example

<?php

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

    return false;
}

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1026
        return $result['filetype'] == 'folder';
1027
    }
1028
1029
    /**
1030
     * @param int $document_id
1031
     * @param array $course_info
1032
     * @param int $session_id
1033
     * @param bool $remove_content_from_db
1034
     */
1035
    public static function deleteDocumentFromDb(
1036
        $document_id,
1037
        $course_info = array(),
1038
        $session_id = 0,
1039
        $remove_content_from_db = false
1040
    ) {
1041
        $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
1042
        $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
1043
1044
        // Deleting from the DB
1045
        $user_id = api_get_user_id();
1046
        $document_id = intval($document_id);
1047
1048
        if (empty($course_info)) {
1049
            $course_info = api_get_course_info();
1050
        }
1051
1052
        if (empty($session_id)) {
1053
            $session_id = api_get_session_id();
1054
        }
1055
1056
        // Soft DB delete
1057
        api_item_property_update(
1058
            $course_info,
1059
            TOOL_DOCUMENT,
1060
            $document_id,
1061
            'delete',
1062
            $user_id,
1063
            null,
1064
            null,
1065
            null,
1066
            null,
1067
            $session_id
1068
        );
1069
        self::delete_document_from_search_engine($course_info['code'], $document_id);
1070
        self::unset_document_as_template($document_id, $course_info['code'], $user_id);
1071
1072
        //Hard DB delete
1073
        if ($remove_content_from_db) {
1074
            $sql = "DELETE FROM $TABLE_ITEMPROPERTY
1075
                    WHERE
1076
                        c_id = {$course_info['real_id']} AND
1077
                        ref = ".$document_id." AND
1078
                        tool='".TOOL_DOCUMENT."'";
1079
            Database::query($sql);
1080
1081
            $sql = "DELETE FROM $TABLE_DOCUMENT
1082
                    WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
1083
            Database::query($sql);
1084
        }
1085
    }
1086
1087
    /**
1088
     * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
1089
     * Files/folders that are inside a deleted folder get visibility 2
1090
     *
1091
     * @param array $_course
1092
     * @param string $path, path stored in the database
0 ignored issues
show
Bug introduced by
There is no parameter named $path,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1093
     * @param string $base_work_dir, path to the documents folder (if not defined, $documentId must be used)
0 ignored issues
show
Documentation introduced by
There is no parameter named $base_work_dir,. Did you maybe mean $base_work_dir?

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

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

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

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

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

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

Consider the follow example

<?php

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

    return false;
}

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

Loading history...
1136
                $_course['code'],
1137
                false,
1138
                $sessionId
1139
            );
1140
            $path = $docInfo['path'];
1141 View Code Duplication
        } else {
1142
            $docInfo = self::get_document_data_by_id(
1143
                $documentId,
1144
                $_course['code'],
1145
                false,
1146
                $sessionId
1147
            );
1148
            if (empty($docInfo)) {
1149
                return false;
1150
            }
1151
            $path = $docInfo['path'];
1152
        }
1153
1154
        $documentId = intval($documentId);
1155
1156
        if (empty($path) || empty($docInfo) || empty($documentId)) {
1157
            return false;
1158
        }
1159
        $itemInfo = api_get_item_property_info(
1160
            $_course['real_id'],
1161
            TOOL_DOCUMENT,
1162
            $documentId,
1163
            $sessionId
1164
        );
1165
1166
        if (empty($itemInfo)) {
1167
            return false;
1168
        }
1169
1170
        // File was already deleted.
1171
        if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
1172
            $itemInfo['lastedit_type'] == 'delete' ||
1173
            $itemInfo['visibility'] == 2
1174
        ) {
1175
            return false;
1176
        }
1177
1178
        // Filtering by group.
1179
        if ($itemInfo['to_group_id'] != $groupId) {
1180
            return false;
1181
        }
1182
1183
        $document_exists_in_disk = file_exists($base_work_dir.$path);
1184
        $new_path = $path.'_DELETED_'.$documentId;
1185
1186
        $file_deleted_from_db = false;
1187
        $file_deleted_from_disk = false;
1188
        $file_renamed_from_disk = false;
1189
1190
        if ($documentId) {
1191
            // Deleting doc from the DB.
1192
            self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1193
            // Checking
1194
            // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
1195
            $file_deleted_from_db = true;
1196
        }
1197
1198
        // Looking for children.
1199
        if ($docInfo['filetype'] == 'folder') {
1200
            $cleanPath = Database::escape_string($path);
1201
1202
            // Deleted files inside this folder.
1203
            $sql = "SELECT id FROM $TABLE_DOCUMENT
1204
                    WHERE
1205
                        c_id = $course_id AND
1206
                        session_id = $sessionId AND
1207
                        path LIKE BINARY '".$cleanPath."/%'";
1208
1209
            // Get all id's of documents that are deleted.
1210
            $result = Database::query($sql);
1211
1212
            if ($result && Database::num_rows($result) != 0) {
1213
                // Recursive delete.
1214
                while ($row = Database::fetch_array($result)) {
1215
                    self::delete_document(
1216
                        $_course,
1217
                        null,
1218
                        $base_work_dir,
1219
                        $sessionId,
1220
                        $row['id']
1221
                    );
1222
                }
1223
            }
1224
        }
1225
1226
        if ($document_exists_in_disk) {
1227
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
1228
                // Delete documents, do it like this so metadata gets deleted too
1229
                my_delete($base_work_dir.$path);
1230
                // Hard delete.
1231
                self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
1232
                $file_deleted_from_disk = true;
1233
            } else {
1234
                // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
1235
1236
                if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
1237
                    if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
1238
                        $new_path = Database::escape_string($new_path);
1239
1240
                        $sql = "UPDATE $TABLE_DOCUMENT
1241
                                SET path = '".$new_path."'
1242
                                WHERE
1243
                                    c_id = $course_id AND
1244
                                    session_id = $sessionId AND
1245
                                    id = ".$documentId;
1246
                        Database::query($sql);
1247
1248
                        // Soft delete.
1249
                        self::deleteDocumentFromDb($documentId, $_course, $sessionId);
1250
1251
                        // Change path of sub folders and documents in database.
1252
                        $old_item_path = $docInfo['path'];
1253
                        $new_item_path = $new_path.substr($old_item_path, strlen($path));
1254
                        $new_item_path = Database::escape_string($new_item_path);
1255
1256
                        $sql = "UPDATE $TABLE_DOCUMENT
1257
                                SET path = '".$new_item_path."'
1258
                                WHERE
1259
                                    c_id = $course_id AND
1260
                                    session_id = $sessionId AND
1261
                                    id = ".$documentId;
1262
                        Database::query($sql);
1263
1264
                        $file_renamed_from_disk = true;
1265
                    } else {
1266
                        // Couldn't rename - file permissions problem?
1267
                        error_log(
1268
                            __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
1269
                            0
1270
                        );
1271
                    }
1272
                }
1273
            }
1274
        }
1275
        // Checking inconsistency
1276
        //error_log('Doc status: (1 del db :'.($file_deleted_from_db?'yes':'no').') - (2 del disk: '.($file_deleted_from_disk?'yes':'no').') - (3 ren disk: '.($file_renamed_from_disk?'yes':'no').')');
1277
        if ($file_deleted_from_db && $file_deleted_from_disk ||
1278
            $file_deleted_from_db && $file_renamed_from_disk
1279
        ) {
1280
            return true;
1281
        } else {
1282
            //Something went wrong
1283
            //The file or directory isn't there anymore (on the filesystem)
1284
            // This means it has been removed externally. To prevent a
1285
            // blocking error from happening, we drop the related items from the
1286
            // item_property and the document table.
1287
            error_log(
1288
                __FILE__.' '.__LINE__.': System inconsistency detected. The file or directory '.$base_work_dir.$path.' seems to have been removed from the filesystem independently from the web platform. To restore consistency, the elements using the same path will be removed from the database',
1289
                0
1290
            );
1291
            return false;
1292
        }
1293
    }
1294
1295
    /**
1296
     * Removes documents from search engine database
1297
     *
1298
     * @param string $course_id Course code
1299
     * @param int $document_id Document id to delete
1300
     */
1301 View Code Duplication
    public static function delete_document_from_search_engine($course_id, $document_id)
1302
    {
1303
        // remove from search engine if enabled
1304
        if (api_get_setting('search_enabled') == 'true') {
1305
            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
1306
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1307
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1308
            $res = Database::query($sql);
1309
            if (Database::num_rows($res) > 0) {
1310
                $row2 = Database::fetch_array($res);
1311
                require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
1312
                $di = new ChamiloIndexer();
1313
                $di->remove_document((int) $row2['search_did']);
1314
            }
1315
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
1316
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
1317
            Database::query($sql);
1318
1319
            // remove terms from db
1320
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
1321
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
1322
        }
1323
    }
1324
1325
    /**
1326
     * Gets the id of a document with a given path
1327
     *
1328
     * @param array $courseInfo
1329
     * @param string $path
1330
     * @param int $sessionId
1331
     * @return int id of document / false if no doc found
1332
     */
1333
    public static function get_document_id($courseInfo, $path, $sessionId = null)
1334
    {
1335
        $table = Database :: get_course_table(TABLE_DOCUMENT);
1336
        $courseId = $courseInfo['real_id'];
1337
1338
        if (!isset($sessionId)) {
1339
            $sessionId = api_get_session_id();
1340
        } else {
1341
            $sessionId = intval($sessionId);
1342
        }
1343
1344
        $path = Database::escape_string($path);
1345 View Code Duplication
        if (!empty($courseId) && !empty($path)) {
1346
            $sql = "SELECT id FROM $table
1347
                    WHERE
1348
                        c_id = $courseId AND
1349
                        path LIKE BINARY '$path' AND
1350
                        session_id = $sessionId
1351
                    LIMIT 1";
1352
1353
            $result = Database::query($sql);
1354
            if (Database::num_rows($result)) {
1355
                $row = Database::fetch_array($result);
1356
1357
                return intval($row['id']);
1358
            }
1359
        }
1360
1361
        return false;
1362
    }
1363
1364
    /**
1365
     * Gets the document data with a given id
1366
     *
1367
     * @param int $id Document Id (id field in c_document table)
1368
     * @param string $course_code Course code
1369
     * @param bool $load_parents load folder parents.
1370
     * @param int $session_id The session ID,
1371
     * 0 if requires context *out of* session, and null to use global context
1372
     * @return array document content
1373
     */
1374
    public static function get_document_data_by_id(
1375
        $id,
1376
        $course_code,
1377
        $load_parents = false,
1378
        $session_id = null
1379
    ) {
1380
        $course_info = api_get_course_info($course_code);
1381
        $course_id = $course_info['real_id'];
1382
1383
        if (empty($course_info)) {
1384
            return false;
1385
        }
1386
1387
        if (isset($session_id)) {
1388
            $session_id = intval($session_id);
1389
        } else {
1390
            $session_id = api_get_session_id();
1391
        }
1392
1393
        $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
1394
1395
        $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
1396
        $id = intval($id);
1397
        $sql = "SELECT * FROM $TABLE_DOCUMENT
1398
                WHERE c_id = $course_id AND session_id = $session_id AND id = $id";
1399
1400
        $result = Database::query($sql);
1401
        if ($result && Database::num_rows($result) == 1) {
1402
            $row = Database::fetch_array($result, 'ASSOC');
1403
1404
            //@todo need to clarify the name of the URLs not nice right now
1405
            $url_path = urlencode($row['path']);
1406
            $path = str_replace('%2F', '/', $url_path);
1407
            $pathinfo = pathinfo($row['path']);
1408
1409
            $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
1410
            $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
1411
            $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
1412
            $row['absolute_path_from_document'] = '/document' . $row['path'];
1413
            $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
1414
            $row['direct_url'] = $www . $path;
1415
1416
            if (dirname($row['path']) == '.') {
1417
                $row['parent_id'] = '0';
1418
            } else {
1419
                $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
1420
            }
1421
            $parents = array();
1422
1423
            //Use to generate parents (needed for the breadcrumb)
1424
            //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
1425
1426
            if ($load_parents) {
1427
                $dir_array = explode('/', $row['path']);
1428
                $dir_array = array_filter($dir_array);
1429
                $array_len = count($dir_array) + 1;
1430
                $real_dir = '';
1431
1432
                for ($i = 1; $i < $array_len; $i++) {
1433
                    $real_dir .= '/' . $dir_array[$i];
1434
                    $parent_id = self::get_document_id($course_info, $real_dir);
1435
                    if ($session_id != 0 && empty($parent_id)) {
1436
                        $parent_id = self::get_document_id($course_info, $real_dir, 0);
1437
                    }
1438
                    if (!empty($parent_id)) {
1439
                        $sub_document_data = self::get_document_data_by_id(
1440
                            $parent_id,
1441
                            $course_code,
1442
                            false,
1443
                            $session_id
1444
                        );
1445
                        if ($session_id != 0 and !$sub_document_data) {
1446
                            $sub_document_data = self::get_document_data_by_id(
1447
                                $parent_id,
1448
                                $course_code,
1449
                                false,
1450
                                0
1451
                            );
1452
                        }
1453
                        //@todo add visibility here
1454
                        $parents[] = $sub_document_data;
1455
                    }
1456
                }
1457
            }
1458
            $row['parents'] = $parents;
1459
1460
            return $row;
1461
        }
1462
1463
        return false;
1464
    }
1465
1466
    /**
1467
     * Allow to set a specific document as a new template for CKeditor
1468
     * for a particular user in a particular course
1469
     *
1470
     * @param string $title
1471
     * @param string $description
1472
     * @param int $document_id_for_template the document id
1473
     * @param string $course_code
1474
     * @param int $user_id
1475
     * @return bool
1476
     */
1477
    public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
1478
    {
1479
        // Database table definition
1480
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1481
        $params = [
1482
            'title' => $title,
1483
            'description' => $description,
1484
            'course_code' => $course_code,
1485
            'user_id' => $user_id,
1486
            'ref_doc' => $document_id_for_template,
1487
            'image' => $image,
1488
        ];
1489
        Database::insert($table_template, $params);
1490
        return true;
1491
    }
1492
1493
    /**
1494
     * Unset a document as template
1495
     *
1496
     * @param int $document_id
1497
     * @param string $course_code
1498
     * @param int $user_id
1499
     */
1500
    public static function unset_document_as_template($document_id, $course_code, $user_id)
1501
    {
1502
        $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
1503
        $course_code = Database::escape_string($course_code);
1504
        $user_id = intval($user_id);
1505
        $document_id = intval($document_id);
1506
1507
        $sql = 'SELECT id FROM ' . $table_template . '
1508
                WHERE
1509
                    course_code="' . $course_code . '" AND
1510
                    user_id="' . $user_id . '" AND
1511
                    ref_doc="' . $document_id . '"';
1512
        $result = Database::query($sql);
1513
        $template_id = Database::result($result, 0, 0);
1514
1515
        my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
1516
1517
        $sql = 'DELETE FROM ' . $table_template . '
1518
                WHERE
1519
                    course_code="' . $course_code . '" AND
1520
                    user_id="' . $user_id . '" AND
1521
                    ref_doc="' . $document_id . '"';
1522
1523
        Database::query($sql);
1524
    }
1525
1526
    /**
1527
     * Return true if the documentpath have visibility=1 as
1528
     * item_property (you should use the is_visible_by_id)
1529
     *
1530
     * @param string $document_path the relative complete path of the document
0 ignored issues
show
Bug introduced by
There is no parameter named $document_path. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1531
     * @param array  $course the _course array info of the document's course
1532
     * @param int
1533
     * @param string
1534
     * @return bool
1535
     */
1536
    public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
1537
    {
1538
        $docTable = Database::get_course_table(TABLE_DOCUMENT);
1539
        $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
1540
1541
        $course_id = $course['real_id'];
1542
        //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
1543
1544
        $session_id = intval($session_id);
1545
        $condition = "AND d.session_id IN  ('$session_id', '0') ";
1546
        // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
1547
1548
        /*
1549
          When using hotpotatoes files, a new html files are generated
1550
          in the hotpotatoes folder to display the test.
1551
          The genuine html file is copied to math4.htm(user_id).t.html
1552
          Images files are not copied, and keep same name.
1553
          To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
1554
          In this case, we have to remove (user_id).t.html to check the visibility of the file
1555
          For images, we just check the path of the image file.
1556
1557
          Exemple of hotpotatoes folder :
1558
          A.jpg
1559
          maths4-consigne.jpg
1560
          maths4.htm
1561
          maths4.htm1.t.html
1562
          maths4.htm52.t.html
1563
          maths4.htm654.t.html
1564
          omega.jpg
1565
          theta.jpg
1566
         */
1567
1568
        if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
1569
            $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
1570
        }
1571
1572
        if (!in_array($file_type, array('file', 'folder'))) {
1573
            $file_type = 'file';
1574
        }
1575
1576
        $sql = "SELECT visibility
1577
                FROM $docTable d
1578
                INNER JOIN $propTable ip
1579
                ON (d.id = ip.ref AND d.c_id  = $course_id AND ip.c_id = $course_id)
1580
        		WHERE
1581
        		    ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
1582
        			filetype = '$file_type' AND
1583
        			locate(concat(path,'/'), '" . Database::escape_string($doc_path.'/'). "')=1
1584
                ";
1585
1586
        $result = Database::query($sql);
1587
        $is_visible = false;
1588 View Code Duplication
        if (Database::num_rows($result) > 0) {
1589
            $row = Database::fetch_array($result, 'ASSOC');
1590
            if ($row['visibility'] == 1) {
1591
                $is_visible = api_is_allowed_in_course() || api_is_platform_admin();
1592
            }
1593
        }
1594
1595
        /* improved protection of documents viewable directly through the url:
1596
            incorporates the same protections of the course at the url of
1597
            documents:
1598
            access allowed for the whole world Open, access allowed for
1599
            users registered on the platform Private access, document accessible
1600
            only to course members (see the Users list), Completely closed;
1601
            the document is only accessible to the course admin and
1602
            teaching assistants.*/
1603
        //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
1604
        return $is_visible;
1605
    }
1606
1607
    /**
1608
     * Return true if user can see a file
1609
     *
1610
     * @param   int     document id
1611
     * @param   array   course info
1612
     * @param   int
1613
     * @param   int
1614
     * @param bool
1615
     * @return  bool
1616
     */
1617
    public static function is_visible_by_id(
1618
        $doc_id,
1619
        $course_info,
1620
        $session_id,
1621
        $user_id,
1622
        $admins_can_see_everything = true
1623
    ) {
1624
        $user_in_course = false;
1625
1626
        //1. Checking the course array
1627
        if (empty($course_info)) {
1628
            $course_info = api_get_course_info();
1629
            if (empty($course_info)) {
1630
                return false;
1631
            }
1632
        }
1633
1634
        $doc_id = intval($doc_id);
1635
        $session_id = intval($session_id);
1636
1637
        //2. Course and Session visibility are handle in local.inc.php/global.inc.php
1638
        //3. Checking if user exist in course/session
1639
1640
        if ($session_id == 0) {
1641
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']) || api_is_platform_admin()
1642
            ) {
1643
                $user_in_course = true;
1644
            }
1645
            // Check if course is open then we can consider that the student is registered to the course
1646
            if (isset($course_info) &&
1647
                in_array(
1648
                    $course_info['visibility'],
1649
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
1650
                )
1651
            ) {
1652
                $user_in_course = true;
1653
            }
1654 View Code Duplication
        } else {
1655
            $user_status = SessionManager::get_user_status_in_course_session(
1656
                $user_id,
1657
                $course_info['real_id'],
1658
                $session_id
1659
            );
1660
1661
            if (in_array($user_status, array('0', '2', '6'))) {
1662
                //is true if is an student, course session teacher or coach
1663
                $user_in_course = true;
1664
            }
1665
1666
            if (api_is_platform_admin()) {
1667
                $user_in_course = true;
1668
            }
1669
        }
1670
1671
        // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
1672
1673
        if ($user_in_course) {
1674
1675
            // 4.1 Checking document visibility for a Course
1676
            if ($session_id == 0) {
1677
                $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
1678
1679
                if (isset($item_info['visibility'])) {
1680
                    // True for admins if document exists
1681
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1682
                        return true;
1683
                    }
1684
                    if ($item_info['visibility'] == 1) {
1685
                        return true;
1686
                    }
1687
                }
1688
            } else {
1689
                // 4.2 Checking document visibility for a Course in a Session
1690
                $item_info = api_get_item_property_info(
1691
                    $course_info['real_id'],
1692
                    'document',
1693
                    $doc_id,
1694
                    0
1695
                );
1696
1697
                $item_info_in_session = api_get_item_property_info(
1698
                    $course_info['real_id'],
1699
                    'document',
1700
                    $doc_id,
1701
                    $session_id
1702
                );
1703
1704
                // True for admins if document exists
1705
                if (isset($item_info['visibility'])) {
1706
                    if ($admins_can_see_everything && api_is_platform_admin()) {
1707
                        return true;
1708
                    }
1709
                }
1710
1711
                if (isset($item_info_in_session['visibility'])) {
1712
                    if ($item_info_in_session['visibility'] == 1) {
1713
                        return true;
1714
                    }
1715
                } else {
1716
                    if ($item_info['visibility'] == 1) {
1717
                        return true;
1718
                    }
1719
                }
1720
            }
1721
        } elseif ($admins_can_see_everything && api_is_platform_admin()) {
1722
            return true;
1723
        }
1724
        return false;
1725
    }
1726
1727
    /**
1728
     * Allow attach a certificate to a course
1729
     * @param string $course_id
1730
     * @param int $document_id
1731
     * @param int $session_id
1732
     *
1733
     * @return void()
0 ignored issues
show
Documentation introduced by
The doc-type void() could not be parsed: Expected "|" or "end of type", but got "(" at position 4. (view supported doc-types)

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

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

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

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

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

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

There are different options of fixing this problem.

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

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

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

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