Issues (2037)

main/lp/openoffice_text_document.class.php (1 issue)

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
 * Defines the "OpenOfficeTextDocument" child of class "learnpath".
16
 */
17
require_once 'openoffice_document.class.php';
18
require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
19
20
/**
21
 * @package chamilo.learnpath.openofficedocument
22
 */
23
class OpenOfficeTextDocument extends OpenofficeDocument
24
{
25
    public $split_steps;
26
27
    /**
28
     * Class constructor. Calls the parent class and initialises the local attribute split_steps.
29
     *
30
     * @param    bool    Whether to split steps (true) or make one large page (false)
31
     * @param    string    Course code
32
     * @param    int    Resource ID
33
     * @param    int Creator user id
34
     */
35
    public function __construct(
36
        $split_steps = false,
37
        $course_code = null,
38
        $resource_id = null,
39
        $user_id = null
40
    ) {
41
        $this->split_steps = $split_steps;
42
        parent::__construct($course_code, $resource_id, $user_id);
43
    }
44
45
    /**
46
     * Gets html pages and compose them into a learning path.
47
     *
48
     * @param    array    The files that will compose the generated learning path. Unused so far.
49
     *
50
     * @return bool False if file does not exit. Nothing otherwise.
51
     */
52
    public function make_lp($files = [])
53
    {
54
        $_course = api_get_course_info();
55
        // We get a content where ||page_break|| indicates where the page is broken.
56
        if (!file_exists($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html')) {
57
            return false;
58
        }
59
        $content = file_get_contents($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
60
61
        unlink($this->base_work_dir.'/'.$this->file_path);
62
        unlink($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
63
64
        // The file is utf8 encoded and it seems to make problems with special quotes.
65
        // then we htmlentities that, we replace these quotes and html_entity_decode that in good charset.
66
        $charset = api_get_system_encoding();
67
        $content = api_htmlentities($content, ENT_COMPAT, $this->original_charset);
68
        $content = str_replace('&rsquo;', '\'', $content);
69
        $content = api_convert_encoding($content, $charset, $this->original_charset);
70
        $content = str_replace($this->original_charset, $charset, $content);
71
        $content = api_html_entity_decode($content, ENT_COMPAT, $charset);
72
73
        // Set the path to pictures to absolute (so that it can be modified in fckeditor).
74
        $content = preg_replace("|src=\"([^\"]*)|i", "src=\"".api_get_path(REL_COURSE_PATH).$_course['path'].'/document'.$this->created_dir."/\\1", $content);
75
76
        list($header, $body) = explode('<BODY', $content);
77
78
        $body = '<BODY'.$body;
79
80
        // Remove font-family styles.
81
        $header = preg_replace("|font\-family[^;]*;|i", '', $header);
82
83
        // Chamilo styles.
84
        $my_style = api_get_setting('stylesheets');
85
        if (empty($my_style)) {
86
            $my_style = 'chamilo';
87
        }
88
        $style_to_import = "<style type=\"text/css\">\r\n";
89
        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";
90
        $style_to_import .= "</style>\r\n";
91
        $header = preg_replace("|</head>|i", "\r\n$style_to_import\r\n\\0", $header);
92
93
        // Line break before and after picture.
94
        $header = str_replace('p {', 'p {clear:both;', $header);
95
96
        $header = str_replace('absolute', 'relative', $header);
97
98
        switch ($this->split_steps) {
99
            case 'per_page':
100
                $this->dealPerPage($header, $body);
101
                break;
102
            case 'per_chapter':
103
                $this->dealPerChapter($header, $body);
104
                break;
105
        }
106
    }
107
108
    /**
109
     * Manages dir/chapter splitting.
110
     *
111
     * @param    string    Chapter header
112
     * @param    string    Content
113
     */
114
    public function dealPerChapter($header, $content)
115
    {
116
        $_course = api_get_course_info();
117
        $content = str_replace('||page_break||', '', $content);
118
119
        // Get all the h1.
120
        preg_match_all("|<h1[^>]*>([^(h1)+]*)</h1>|is", $content, $matches_temp);
121
122
        // Empty the fake dir/chapters.
123
        $new_index = 0;
124
        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...
125
            if (trim($matches_temp[1][$i]) !== '') {
126
                $matches[0][$new_index] = $matches_temp[0][$i];
127
                $matches[1][$new_index] = $matches_temp[1][$i];
128
                $new_index++;
129
            }
130
        }
131
132
        // Add intro item.
133
        $intro_content = api_substr($content, 0, api_strpos($content, $matches[0][0]));
134
        $items_to_create[get_lang('Introduction')] = $intro_content;
135
136
        for ($i = 0; $i < count($matches[0]); $i++) {
137
            if (empty($matches[1][$i])) {
138
                continue;
139
            }
140
141
            $content = api_strstr($content, $matches[0][$i]);
142
            if ($i + 1 !== count($matches[0])) {
143
                $dir_content = api_substr($content, 0, api_strpos($content, $matches[0][$i + 1]));
144
            } else {
145
                $dir_content = $content;
146
            }
147
            $items_to_create[$matches[1][$i]] = $dir_content;
148
        }
149
150
        $i = 0;
151
        $previous = 0; // @todo define this variable properly
152
        foreach ($items_to_create as $item_title => $item_content) {
153
            $i++;
154
            $page_content = $this->format_page_content($header, $item_content);
155
156
            $html_file = $this->created_dir.'-'.$i.'.html';
157
            $handle = fopen($this->base_work_dir.$this->created_dir.'/'.$html_file, 'w+');
158
            fwrite($handle, $page_content);
159
            fclose($handle);
160
161
            $document_id = add_document(
162
                $_course,
163
                $this->created_dir.'/'.$html_file,
164
                'file',
165
                filesize($this->base_work_dir.$this->created_dir.'/'.$html_file),
166
                $html_file
167
            );
168
169
            if ($document_id) {
170
                // Put the document in item_property update.
171
                api_item_property_update(
172
                    $_course,
173
                    TOOL_DOCUMENT,
174
                    $document_id,
175
                    'DocumentAdded',
176
                    api_get_user_id(),
177
                    0,
178
                    0,
179
                    null,
180
                    null,
181
                    api_get_session_id()
182
                );
183
184
                $infos = pathinfo($this->filepath);
185
                $slide_name = strip_tags(nl2br($item_title));
186
                $slide_name = str_replace(["\r\n", "\r", "\n"], '', $slide_name);
187
                $slide_name = api_html_entity_decode($slide_name, ENT_COMPAT, api_get_system_encoding());
188
                $previous = learnpath::add_item(
189
                    0,
190
                    $previous,
191
                    'document',
192
                    $document_id,
193
                    $slide_name,
194
                    ''
195
                );
196
                if ($this->first_item == 0) {
197
                    $this->first_item = (int) $previous;
198
                }
199
            }
200
        }
201
    }
202
203
    /**
204
     * Manages page splitting.
205
     *
206
     * @param    string    Page header
207
     * @param    string    Page body
208
     */
209
    public function dealPerPage($header, $body)
210
    {
211
        $_course = api_get_course_info();
212
        // Split document to pages.
213
        $pages = explode('||page_break||', $body);
214
        foreach ($pages as $key => $page_content) {
215
            // For every pages, we create a new file.
216
            $key++;
217
            $page_content = $this->format_page_content(
218
                $header,
219
                $page_content,
220
                $this->base_work_dir.$this->created_dir
221
            );
222
            $html_file = $this->created_dir.'-'.$key.'.html';
223
            $handle = fopen($this->base_work_dir.$this->created_dir.'/'.$html_file, 'w+');
224
            fwrite($handle, $page_content);
225
            fclose($handle);
226
227
            $document_id = add_document(
228
                $_course,
229
                $this->created_dir.$html_file,
230
                'file',
231
                filesize($this->base_work_dir.$this->created_dir.$html_file),
232
                $html_file
233
            );
234
235
            $slide_name = '';
236
            $previous = 0; // @todo define this variable properly
237
            if ($document_id) {
238
                // Put the document in item_property update.
239
                api_item_property_update(
240
                    $_course,
241
                    TOOL_DOCUMENT,
242
                    $document_id,
243
                    'DocumentAdded',
244
                    api_get_user_id(),
245
                    0,
246
                    0,
247
                    null,
248
                    null,
249
                    api_get_session_id()
250
                );
251
252
                $infos = pathinfo($this->filepath);
253
                $slide_name = 'Page '.str_repeat('0', 2 - strlen($key)).$key;
254
                $previous = learnpath::add_item(
255
                    0,
256
                    $previous,
257
                    'document',
258
                    $document_id,
259
                    $slide_name,
260
                    ''
261
                );
262
                if ($this->first_item == 0) {
263
                    $this->first_item = (int) $previous;
264
                }
265
                // Code for text indexing.
266
                if (isset($_POST['index_document']) && $_POST['index_document']) {
267
                    //echo Display::return_message(print_r($_POST));
268
                    $di = new ChamiloIndexer();
269
                    isset($_POST['language']) ? $lang = Database::escape_string($_POST['language']) : $lang = 'english';
270
                    $di->connectDb(null, null, $lang);
271
                    $ic_slide = new IndexableChunk();
272
                    $ic_slide->addValue('title', $slide_name);
273
                    $specific_fields = get_specific_field_list();
274
                    $all_specific_terms = '';
275
                    foreach ($specific_fields as $specific_field) {
276
                        if (isset($_REQUEST[$specific_field['code']])) {
277
                            $sterms = trim($_REQUEST[$specific_field['code']]);
278
                            $all_specific_terms .= ' '.$sterms;
279
                            if (!empty($sterms)) {
280
                                $sterms = explode(',', $sterms);
281
                                foreach ($sterms as $sterm) {
282
                                    $ic_slide->addTerm(trim($sterm), $specific_field['code']);
283
                                }
284
                            }
285
                        }
286
                    }
287
                    $page_content = $all_specific_terms.' '.$page_content;
288
                    $ic_slide->addValue('content', $page_content);
289
                    // Add a comment to say terms separated by commas.
290
                    $courseid = api_get_course_id();
291
                    $ic_slide->addCourseId($courseid);
292
                    $ic_slide->addToolId(TOOL_LEARNPATH);
293
                    $lp_id = $this->lp_id;
294
                    $xapian_data = [
295
                        SE_COURSE_ID => $courseid,
296
                        SE_TOOL_ID => TOOL_LEARNPATH,
297
                        SE_DATA => [
298
                            'lp_id' => $lp_id,
299
                            'lp_item' => $previous,
300
                            'document_id' => $document_id,
301
                        ],
302
                        SE_USER => (int) api_get_user_id(),
303
                    ];
304
                    $ic_slide->xapian_data = serialize($xapian_data);
305
                    $di->addChunk($ic_slide);
306
                    // Index and return search engine document id.
307
                    $did = $di->index();
308
                    if ($did) {
309
                        // Save it to db.
310
                        $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
311
                        $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did)
312
                                VALUES (NULL , \'%s\', \'%s\', %s, %s, %s)';
313
                        $sql = sprintf(
314
                            $sql,
315
                            $tbl_se_ref,
316
                            api_get_course_id(),
317
                            TOOL_LEARNPATH,
318
                            $lp_id,
319
                            $previous,
320
                            $did
321
                        );
322
                        Database::query($sql);
323
                    }
324
                }
325
            }
326
        }
327
    }
328
329
    /**
330
     * Returns additional Java command parameters.
331
     *
332
     * @return string The additional parameters to be used in the Java call
333
     */
334
    public function add_command_parameters()
335
    {
336
        return ' -d woogie '
337
            .Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
338
            .'  '
339
            .Security::sanitizeExecParam($this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html');
340
    }
341
342
    /**
343
     * Formats a page content by reorganising the HTML code a little.
344
     *
345
     * @param    string    Page header
346
     * @param    string    Page content
347
     *
348
     * @return string Formatted page content
349
     */
350
    public function format_page_content($header, $content)
351
    {
352
        // Limit the width of the doc.
353
        list($max_width, $max_height) = explode('x', api_get_setting('service_ppt2lp', 'size'));
354
355
        $content = preg_replace("|<body[^>]*>|i", "\\0\r\n<div style=\"width:".$max_width."\">", $content, -1, $count);
356
        if ($count < 1) {
357
            $content = '<body><div style="width:'.$max_width.'">'.$content;
358
        }
359
360
        $content = preg_replace('|</body>|i', '</div>\\0', $content, -1, $count);
361
        if ($count < 1) {
362
            $content = $content.'</div></body>';
363
        }
364
365
        // Add the headers.
366
        $content = $header.$content;
367
368
        // Resize all the picture to the max_width-10
369
        preg_match_all("|<img[^src]*src=\"([^\"]*)\"[^>]*>|i", $content, $images);
370
371
        foreach ($images[1] as $key => $image) {
372
            // Check if the <img tag soon has a width attribute.
373
            $defined_width = preg_match("|width=([^\s]*)|i", $images[0][$key], $img_width);
374
            $img_width = $img_width[1];
375
            if (!$defined_width) {
376
                $image_size = api_getimagesize($this->base_work_dir.$this->created_dir.'/'.$image);
377
                $img_width = $image_size['width'];
378
                $img_height = $image_size['height'];
379
380
                $new_width = $max_width - 10;
381
                if ($img_width > $new_width) {
382
                    $picture_resized = str_ireplace('<img', '<img width="'.$new_width.'" ', $images[0][$key]);
383
                    $content = str_replace($images[0][$key], $picture_resized, $content);
384
                }
385
            } elseif ($img_width > $max_width - 10) {
386
                $picture_resized = str_ireplace(
387
                    'width='.$img_width,
388
                    'width="'.($max_width - 10).'"',
389
                    $images[0][$key]
390
                );
391
                $content = str_replace(
392
                    $images[0][$key],
393
                    $picture_resized,
394
                    $content
395
                );
396
            }
397
        }
398
399
        return $content;
400
    }
401
402
    /**
403
     * Add documents to the visioconference (to be implemented).
404
     */
405
    public function add_docs_to_visio()
406
    {
407
    }
408
}
409