Issues (2037)

main/lp/openoffice_text.class.php (2 issues)

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Defines the OpenofficeDocument class, which is meant as a conversion
6
 * tool from Office text documents (.doc, .sxw, .odt, .docx) to
7
 * learning paths.
8
 *
9
 * @package chamilo.learnpath
10
 *
11
 * @author  Eric Marguin <[email protected]>
12
 * @license GNU/GPL
13
 */
14
15
/**
16
 * Defines the "OpenofficeText" child of class "learnpath".
17
 */
18
require_once 'openoffice_document.class.php';
19
if (api_get_setting('search_enabled') == 'true') {
20
    require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
21
}
22
23
/**
24
 * @package chamilo.learnpath.OpenofficeDocument
25
 */
26
class OpenofficeText extends OpenofficeDocument
27
{
28
    public $split_steps;
29
30
    /**
31
     * Class constructor. Calls the parent class and initialises the local attribute split_steps.
32
     *
33
     * @param    bool    Whether to split steps (true) or make one large page (false)
34
     * @param    string    Course code
35
     * @param    int    Resource ID
36
     * @param    int Creator user id
37
     */
38
    public function __construct(
39
        $split_steps = false,
40
        $course_code = null,
41
        $resource_id = null,
42
        $user_id = null
43
    ) {
44
        $this->split_steps = $split_steps;
45
        parent::__construct($course_code, $resource_id, $user_id);
46
    }
47
48
    /**
49
     * Gets html pages and compose them into a learning path.
50
     *
51
     * @param    array    The files that will compose the generated learning path. Unused so far.
52
     *
53
     * @return bool False if file does not exit. Nothing otherwise.
54
     */
55
    public function make_lp($files = [])
56
    {
57
        $_course = api_get_course_info();
58
        // We get a content where ||page_break|| indicates where the page is broken.
59
        if (!file_exists($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html')) {
60
            return false;
61
        }
62
        $content = file_get_contents($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
63
64
        unlink($this->base_work_dir.'/'.$this->file_path);
65
        unlink($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
66
67
        // The file is utf8 encoded and it seems to make problems with special quotes.
68
        // Then we htmlentities that, we replace these quotes and html_entity_decode that in good charset.
69
        $charset = api_get_system_encoding();
70
        $content = api_htmlentities($content, ENT_COMPAT, $this->original_charset);
71
        $content = str_replace('&rsquo;', '\'', $content);
72
        $content = api_convert_encoding($content, $charset, $this->original_charset);
73
        $content = str_replace($this->original_charset, $charset, $content);
74
        $content = api_html_entity_decode($content, ENT_COMPAT, $charset);
75
76
        // Set the path to pictures to absolute (so that it can be modified in fckeditor).
77
        $content = preg_replace(
78
            "|src=\"([^\"]*)|i",
79
            "src=\"".api_get_path(REL_COURSE_PATH).$_course['path'].'/document'.$this->created_dir."/\\1",
80
            $content
81
        );
82
83
        list($header, $body) = explode('<BODY', $content);
84
85
        $body = '<BODY'.$body;
86
87
        // Remove font-family styles.
88
        $header = preg_replace("|font\-family[^;]*;|i", '', $header);
89
90
        // Chamilo styles.
91
        $my_style = api_get_setting('stylesheets');
92
        if (empty($my_style)) {
93
            $my_style = 'chamilo';
94
        }
95
        $style_to_import = "<style type=\"text/css\">\r\n";
96
        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";
97
        $style_to_import .= "</style>\r\n";
98
        $header = preg_replace("|</head>|i", "\r\n$style_to_import\r\n\\0", $header);
99
100
        // Line break before and after picture.
101
        $header = str_replace('p {', 'p {clear:both;', $header);
102
103
        $header = str_replace('absolute', 'relative', $header);
104
105
        switch ($this->split_steps) {
106
            case 'per_page':
107
                $this->dealPerPage($header, $body);
108
                break;
109
            case 'per_chapter':
110
                $this->dealPerChapter($header, $body);
111
                break;
112
        }
113
    }
114
115
    /**
116
     * Manages dir/chapter splitting.
117
     *
118
     * @param    string    Chapter header
119
     * @param    string    Content
120
     */
121
    public function dealPerChapter($header, $content)
122
    {
123
        $_course = api_get_course_info();
124
        $content = str_replace('||page_break||', '', $content);
125
126
        // Get all the h1.
127
        preg_match_all("|<h1[^>]*>([^(h1)+]*)</h1>|is", $content, $matches_temp);
128
129
        // Empty the fake chapters.
130
        $new_index = 0;
131
        for ($i = 0; $i < count($matches_temp[0]); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
132
            if (trim($matches_temp[1][$i]) !== '') {
133
                $matches[0][$new_index] = $matches_temp[0][$i];
134
                $matches[1][$new_index] = $matches_temp[1][$i];
135
                $new_index++;
136
            }
137
        }
138
139
        // Add intro item.
140
        $intro_content = substr($content, 0, strpos($content, $matches[0][0]));
141
        $items_to_create[get_lang('Introduction')] = $intro_content;
142
143
        for ($i = 0; $i < count($matches[0]); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
144
            if (empty($matches[1][$i])) {
145
                continue;
146
            }
147
148
            $content = strstr($content, $matches[0][$i]);
149
            if ($i + 1 !== count($matches[0])) {
150
                $dir_content = substr($content, 0, strpos($content, $matches[0][$i + 1]));
151
            } else {
152
                $dir_content = $content;
153
            }
154
            $items_to_create[$matches[1][$i]] = $dir_content;
155
        }
156
157
        $i = 0;
158
        foreach ($items_to_create as $item_title => $item_content) {
159
            $i++;
160
            $page_content = $this->format_page_content($header, $item_content);
161
162
            $html_file = $this->created_dir.'-'.$i.'.html';
163
            $handle = fopen($this->base_work_dir.$this->created_dir.'/'.$html_file, 'w+');
164
            fwrite($handle, $page_content);
165
            fclose($handle);
166
167
            $document_id = add_document(
168
                $_course,
169
                $this->created_dir.'/'.$html_file,
170
                'file',
171
                filesize(
172
                    $this->base_work_dir.$this->created_dir.'/'.$html_file
173
                ),
174
                $html_file
175
            );
176
177
            if ($document_id) {
178
                // Put the document in item_property update.
179
                api_item_property_update(
180
                    $_course,
181
                    TOOL_DOCUMENT,
182
                    $document_id,
183
                    'DocumentAdded',
184
                    api_get_user_id(),
185
                    0,
186
                    0,
187
                    null,
188
                    null,
189
                    api_get_session_id()
190
                );
191
192
                $infos = pathinfo($this->filepath);
193
                $slide_name = strip_tags(nl2br($item_title));
194
                $slide_name = str_replace(["\r\n", "\r", "\n"], '', $slide_name);
195
                $slide_name = html_entity_decode($slide_name);
196
                $previous = learnpath::add_item(
197
                    0,
198
                    $previous,
199
                    'document',
200
                    $document_id,
201
                    $slide_name,
202
                    ''
203
                );
204
                if ($this->first_item == 0) {
205
                    $this->first_item = $previous;
206
                }
207
            }
208
        }
209
    }
210
211
    /**
212
     * Manages page splitting.
213
     *
214
     * @param    string    Page header
215
     * @param    string    Page body
216
     */
217
    public function dealPerPage($header, $body)
218
    {
219
        $_course = api_get_course_info();
220
        // Split document to pages.
221
        $pages = explode('||page_break||', $body);
222
223
        $first_item = 0;
224
        foreach ($pages as $key => $page_content) {
225
            // For every pages, we create a new file.
226
            $key++;
227
            $page_content = $this->format_page_content($header, $page_content, $this->base_work_dir.$this->created_dir);
228
            $html_file = $this->created_dir.'-'.$key.'.html';
229
            $handle = fopen($this->base_work_dir.$this->created_dir.'/'.$html_file, 'w+');
230
            fwrite($handle, $page_content);
231
            fclose($handle);
232
233
            $document_id = add_document(
234
                $_course,
235
                $this->created_dir.$html_file,
236
                'file',
237
                filesize($this->base_work_dir.$this->created_dir.$html_file),
238
                $html_file
239
            );
240
241
            $slide_name = '';
242
            if ($document_id) {
243
                // Put the document in item_property update.
244
                api_item_property_update(
245
                    $_course,
246
                    TOOL_DOCUMENT,
247
                    $document_id,
248
                    'DocumentAdded',
249
                    api_get_user_id(),
250
                    0,
251
                    0,
252
                    null,
253
                    null,
254
                    api_get_session_id()
255
                );
256
257
                $infos = pathinfo($this->filepath);
258
                $slide_name = 'Page '.str_repeat('0', 2 - strlen($key)).$key;
259
                $previous = learnpath::add_item(0, $previous, 'document', $document_id, $slide_name, '');
260
                if ($this->first_item == 0) {
261
                    $this->first_item = $previous;
262
                }
263
                // Code for text indexing.
264
                if (api_get_setting('search_enabled') == 'true') {
265
                    if (isset($_POST['index_document']) && $_POST['index_document']) {
266
                        //echo Display::return_message(print_r($_POST));
267
                        $di = new ChamiloIndexer();
268
                        isset($_POST['language']) ? $lang = Database::escape_string(
269
                            $_POST['language']
270
                        ) : $lang = 'english';
271
                        $di->connectDb(null, null, $lang);
272
                        $ic_slide = new IndexableChunk();
273
                        $ic_slide->addValue('title', $slide_name);
274
                        $specific_fields = get_specific_field_list();
275
                        $all_specific_terms = '';
276
                        foreach ($specific_fields as $specific_field) {
277
                            if (isset($_REQUEST[$specific_field['code']])) {
278
                                $sterms = trim($_REQUEST[$specific_field['code']]);
279
                                $all_specific_terms .= ' '.$sterms;
280
                                if (!empty($sterms)) {
281
                                    $sterms = explode(',', $sterms);
282
                                    foreach ($sterms as $sterm) {
283
                                        $ic_slide->addTerm(trim($sterm), $specific_field['code']);
284
                                    }
285
                                }
286
                            }
287
                        }
288
                        $page_content = $all_specific_terms.' '.$page_content;
289
                        $ic_slide->addValue('content', $page_content);
290
                        // Add a comment to say terms separated by commas.
291
                        $courseid = api_get_course_id();
292
                        $ic_slide->addCourseId($courseid);
293
                        $ic_slide->addToolId(TOOL_LEARNPATH);
294
                        $lp_id = $this->lp_id;
295
                        $xapian_data = [
296
                            SE_COURSE_ID => $courseid,
297
                            SE_TOOL_ID => TOOL_LEARNPATH,
298
                            SE_DATA => ['lp_id' => $lp_id, 'lp_item' => $previous, 'document_id' => $document_id],
299
                            SE_USER => (int) api_get_user_id(),
300
                        ];
301
                        $ic_slide->xapian_data = serialize($xapian_data);
302
                        $di->addChunk($ic_slide);
303
                        // Index and return search engine document id.
304
                        $did = $di->index();
305
                        if ($did) {
306
                            // Save it to db.
307
                            $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
308
                            $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did)
309
                                    VALUES (NULL , \'%s\', \'%s\', %s, %s, %s)';
310
                            $sql = sprintf(
311
                                $sql,
312
                                $tbl_se_ref,
313
                                api_get_course_id(),
314
                                TOOL_LEARNPATH,
315
                                $lp_id,
316
                                $previous,
317
                                $did
318
                            );
319
                            Database::query($sql);
320
                        }
321
                    }
322
                }
323
            }
324
        }
325
    }
326
327
    /**
328
     * Returns additional Java command parameters.
329
     *
330
     * @return string The additional parameters to be used in the Java call
331
     */
332
    public function add_command_parameters()
333
    {
334
        return ' -d woogie '
335
            .Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
336
            .'  '
337
            .Security::sanitizeExecParam($this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html');
338
    }
339
340
    /**
341
     * Formats a page content by reorganising the HTML code a little.
342
     *
343
     * @param    string    Page header
344
     * @param    string    Page content
345
     *
346
     * @return string Formatted page content
347
     */
348
    public function format_page_content($header, $content)
349
    {
350
        // Limit the width of the doc.
351
        list($max_width, $max_height) = explode('x', api_get_setting('service_ppt2lp', 'size'));
352
353
        $content = preg_replace("|<body[^>]*>|i", "\\0\r\n<div style=\"width:".$max_width."\">", $content, -1, $count);
354
        if ($count < 1) {
355
            $content = '<body><div style="width:'.$max_width.'">'.$content;
356
        }
357
358
        $content = preg_replace('|</body>|i', '</div>\\0', $content, -1, $count);
359
        if ($count < 1) {
360
            $content = $content.'</div></body>';
361
        }
362
363
        // Add the headers.
364
        $content = $header.$content;
365
366
        // Resize all the picture to the max_width-10
367
        preg_match_all("|<img[^src]*src=\"([^\"]*)\"[^>]*>|i", $content, $images);
368
369
        foreach ($images[1] as $key => $image) {
370
            // Check if the <img tag soon has a width attribute.
371
            $defined_width = preg_match("|width=([^\s]*)|i", $images[0][$key], $img_width);
372
            $img_width = $img_width[1];
373
            if (!$defined_width) {
374
                list($img_width, $img_height, $type) = getimagesize($this->base_work_dir.$this->created_dir.'/'.$image);
375
376
                $new_width = $max_width - 10;
377
                if ($img_width > $new_width) {
378
                    $picture_resized = str_ireplace('<img', '<img width="'.$new_width.'" ', $images[0][$key]);
379
                    $content = str_replace($images[0][$key], $picture_resized, $content);
380
                }
381
            } elseif ($img_width > $max_width - 10) {
382
                $picture_resized = str_ireplace('width='.$img_width, 'width="'.($max_width - 10).'"', $images[0][$key]);
383
                $content = str_replace($images[0][$key], $picture_resized, $content);
384
            }
385
        }
386
387
        return $content;
388
    }
389
390
    /**
391
     * Add documents to the visioconference (to be implemented).
392
     */
393
    public function add_docs_to_visio()
394
    {
395
    }
396
}
397