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('’', '\'', $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
|
|||
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
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 |
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: