PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.11
VikBooking Hotel Booking Engine & PMS v1.8.11
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / site / helpers / translator.php

translator.php in VikBooking Hotel Booking Engine & PMS 1.8.11, at site/helpers/translator.php

897 lines 23.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Global translator class for VikBooking contents.
15 */
16 class VikBookingTranslator
17 {
18 /**
19 * @var string
20 */
21 public $current_lang;
22
23 /**
24 * @var string
25 */
26 public $default_lang;
27
28 /**
29 * @var int
30 */
31 public $lim = 5;
32
33 /**
34 * @var int
35 */
36 public $lim0 = 0;
37
38 /**
39 * @var string
40 */
41 public $navigation = '';
42
43 /**
44 * @var string
45 */
46 public $error = '';
47
48 /**
49 * @var string
50 */
51 private $xml = '';
52
53 /**
54 * @var array
55 */
56 private $all_langs = [];
57
58 /**
59 * @var object
60 */
61 private $dbo;
62
63 /**
64 * @var string
65 */
66 private $translations_path_file;
67
68 /**
69 * @var array
70 */
71 private $translations_buffer = [];
72
73 /**
74 * @var string
75 *
76 * @since 1.16.6 (J) - 1.6.6 (WP)
77 */
78 private $keysearch = '';
79
80 /**
81 * @var array
82 *
83 * @since 1.16.6 (J) - 1.6.6 (WP)
84 */
85 private $cached_cols = [];
86
87 /**
88 * @var string
89 */
90 public static $force_tolang = null;
91
92 /**
93 * Class constructor.
94 */
95 public function __construct()
96 {
97 $app = JFactory::getApplication();
98
99 $this->current_lang = $this->getCurrentLang();
100 $this->default_lang = $this->getDefaultLang();
101 $this->lim = $app->input->getInt('limit', 5);
102 $this->lim0 = $app->input->getInt('limitstart', 0);
103 $this->dbo = JFactory::getDbo();
104 $this->translations_path_file = VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'fields' . DIRECTORY_SEPARATOR . 'translations.xml';
105 }
106
107 /**
108 * Gets the language for the current execution.
109 *
110 * @return string
111 */
112 public function getCurrentLang()
113 {
114 if (!$this->current_lang) {
115 $this->current_lang = JFactory::getLanguage()->getTag();
116 }
117
118 return $this->current_lang;
119 }
120
121 /**
122 * Gets the default language for the requested section.
123 *
124 * @param string $section either site or administrator.
125 *
126 * @return string
127 */
128 public function getDefaultLang($section = 'site')
129 {
130 if (VBOPlatformDetection::isWordPress()) {
131 /**
132 * @wponly import the JComponentHelper class
133 */
134 jimport('joomla.application.component.helper');
135 }
136
137 if (!$this->default_lang && $section == 'site') {
138 $this->default_lang = JComponentHelper::getParams('com_languages')->get($section);
139 }
140
141 if ($section == 'site') {
142 return $this->default_lang;
143 }
144
145 return JComponentHelper::getParams('com_languages')->get($section);
146 }
147
148 /**
149 * Returns a list of translation INI files.
150 *
151 * @return array
152 */
153 public function getIniFiles()
154 {
155 // Keys = Lang Def composed as VBINIEXPL.strtoupper(Key)
156 // Values = Paths to INI Files
157
158 if (VBOPlatformDetection::isWordPress()) {
159 /**
160 * @wponly nothing to return
161 */
162 return [];
163 }
164
165 return [
166 'com_vikbooking_front' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.ini'],
167 'com_vikbooking_admin' => ['path' => JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.ini'],
168 'com_vikbooking_admin_sys' => ['path' => JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.sys.ini'],
169 'mod_vikbooking_search' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.mod_vikbooking_search.ini'],
170 'mod_vikbooking_horizontalsearch' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.mod_vikbooking_horizontalsearch.ini'],
171 ];
172 }
173
174 /**
175 * Builds a list of known languages.
176 *
177 * @return array
178 */
179 public function getLanguagesList()
180 {
181 if ($this->all_langs) {
182 // return the cached languages
183 return $this->all_langs;
184 }
185
186 $langs = [];
187 $known_langs = VikBooking::getVboApplication()->getKnownLanguages();
188
189 foreach ($known_langs as $ltag => $ldet) {
190 if ($ltag == $this->default_lang) {
191 $langs = [$ltag => $ldet] + $langs;
192 } else {
193 $langs[$ltag] = $ldet;
194 }
195 }
196
197 // cache and return languages
198 $this->all_langs = $langs;
199
200 return $this->all_langs;
201 }
202
203 /**
204 * Returns a list of known language tags.
205 *
206 * @return array
207 */
208 public function getLanguagesTags()
209 {
210 if (!$this->all_langs) {
211 // set known languages
212 $this->getLanguagesList();
213 }
214
215 return array_keys($this->all_langs);
216 }
217
218 /**
219 * Replaces the prefix from a given table name.
220 *
221 * @param string $str the prefixed name.
222 *
223 * @return string
224 */
225 public function replacePrefix($str)
226 {
227 return $this->dbo->replacePrefix($str);
228 }
229
230 /**
231 * Helper method that makes sure the table name starts with the prefix placeholder.
232 * In order to avoid issues with queries containing the prefix placeholder ("#__"),
233 * the name of the table for the translated record is removed from the placeholder prefix.
234 *
235 * @param string $table_name the table name to adjust.
236 *
237 * @return string the adjust table name with the prefix placeholder.
238 *
239 * @since 1.16.0 (J) - 1.6.0 (WP)
240 */
241 public function adjustTablePrefix($table_name)
242 {
243 if (empty($table_name) || !is_string($table_name)) {
244 // nothing to do with the given value
245 return $table_name;
246 }
247
248 if (preg_match("/^#__/", $table_name)) {
249 // default prefix placeholder found at the beginning of the string
250 return $table_name;
251 }
252
253 if (strpos($table_name, 'vikbooking_') === false) {
254 // nothing to do with this table name
255 return $table_name;
256 }
257
258 // make the table name start with the prefix placeholder
259 $table_nm_parts = explode('vikbooking_', $table_name);
260 $table_nm_parts[0] = '#__';
261
262 return implode('vikbooking_', $table_nm_parts);
263 }
264
265 /**
266 * Fixer method for BC. The old structure was storing the table names for
267 * the translated records without the default prefix placeholder ('#__'),
268 * but this is invalid for the backup features. This method converts all
269 * table names for the translated records so that they will contain the
270 * default prefix placeholder at the beginning of the string.
271 *
272 * @return boolean
273 *
274 * @since 1.16.0 (J) - 1.6.0 (WP)
275 */
276 public function normalizeTnTableNames()
277 {
278 $query = $this->dbo->getQuery(true);
279
280 $query->select($this->dbo->qn('t.id'));
281 $query->select($this->dbo->qn('t.table'));
282
283 $query->from($this->dbo->qn('#__vikbooking_translations', 't'));
284
285 $this->dbo->setQuery($query);
286 $translations = $this->dbo->loadObjectList();
287
288 if (!$translations) {
289 // no translation records found
290 return false;
291 }
292
293 foreach ($translations as $tn_record) {
294 // normalize table name with prefix
295 $tn_record->table = $this->adjustTablePrefix($tn_record->table);
296
297 // update record on db
298 $this->dbo->updateObject('#__vikbooking_translations', $tn_record, 'id');
299 }
300
301 return true;
302 }
303
304 /**
305 * Builds an associative list of translation tables.
306 *
307 * @return mixed array or false.
308 */
309 public function getTranslationTables()
310 {
311 $xml = $this->getTranslationsXML();
312 if ($xml === false) {
313 return false;
314 }
315 $tables = [];
316 foreach ($xml->Translation as $translation) {
317 $attr = $translation->attributes();
318 $tables[(string)$attr->table] = JText::translate((string)$attr->name);
319 }
320
321 return $tables;
322 }
323
324 /**
325 * Returns the translated name of the table given the prefix
326 *
327 * @param string $table
328 */
329 public function getTranslationTableName($table)
330 {
331 $xml = $this->getTranslationsXML();
332 $table_name = '';
333 foreach ($xml->Translation as $translation) {
334 $attr = $translation->attributes();
335 if ((string)$attr->table == $table) {
336 return JText::translate((string)$attr->name);
337 }
338 }
339 return $table_name;
340 }
341
342 /**
343 * Returns an array with the XML Columns of the given table
344 *
345 * @param string $table
346 *
347 * @return array
348 */
349 public function getTableColumns($table)
350 {
351 if (isset($this->cached_cols[$table])) {
352 return $this->cached_cols[$table];
353 }
354
355 $xml = $this->getTranslationsXML();
356 $cols = [];
357 foreach ($xml->Translation as $translation) {
358 $attr = $translation->attributes();
359 if ((string)$attr->table == $table) {
360 foreach ($translation->Column as $column) {
361 $col_attr = $column->attributes();
362 if (!property_exists($col_attr, 'name')) {
363 continue;
364 }
365 $ind = (string)$col_attr->name;
366 $cols[$ind]['jlang'] = JText::translate((string)$column);
367 foreach ($col_attr as $key => $val) {
368 $cols[$ind][(string)$key] = (string)$val;
369 }
370 }
371 }
372 }
373
374 // cache table columns
375 $this->cached_cols[$table] = $cols;
376
377 return $cols;
378 }
379
380 /**
381 * Gets the name of the reference column for the given table.
382 *
383 * @param string $table the name of the table.
384 *
385 * @return string
386 *
387 * @since 1.16.6 (J) - 1.6.6 (WP)
388 */
389 public function getTableReferenceColumn($table)
390 {
391 foreach ($this->getTableColumns($table) as $col_name => $col_values) {
392 if (isset($col_values['reference'])) {
393 return $col_name;
394 }
395 }
396
397 return '';
398 }
399
400 /**
401 * Returns the db column marked as reference, of the record. Ex. the name of the Room in this record
402 *
403 * @param array $cols
404 * @param array $record
405 */
406 public function getRecordReferenceName($cols, $record)
407 {
408 foreach ($cols as $key => $values) {
409 if (array_key_exists('reference', $values)) {
410 if (array_key_exists($key, $record)) {
411 return $record[$key];
412 }
413 }
414 }
415 // if not found, not present or empty, return first value of the record
416 return $record[key($record)];
417 }
418
419 /**
420 * Returns the current records for the default language and this table
421 *
422 * @param string $table the name of the table.
423 * @param array $cols array containing the db fields to fetch,
424 * result of array_keys($this->getTableColumns()).
425 *
426 * @return array
427 */
428 public function getTableDefaultDbValues($table, $cols = [])
429 {
430 $def_vals = [];
431
432 if (!$cols) {
433 $cols = array_keys($this->getTableColumns($table));
434 if (!$cols) {
435 $this->setError("Table $table has no Columns.");
436 }
437 }
438
439 if ($cols) {
440 $cols = array_map([$this->dbo, 'qn'], $cols);
441
442 $reference_column = $this->getTableReferenceColumn($table);
443
444 $q = $this->dbo->getQuery(true)
445 ->select('SQL_CALC_FOUND_ROWS ' . $this->dbo->qn('id'))
446 ->select($cols)
447 ->from($this->dbo->qn($table))
448 ->order($this->dbo->qn(($reference_column ?: 'id')) . ' ASC');
449
450 if (!empty($this->keysearch) && $reference_column) {
451 $q->where($this->dbo->qn($reference_column) . ' LIKE ' . $this->dbo->q("%{$this->keysearch}%"));
452 }
453
454 $this->dbo->setQuery($q, $this->lim0, $this->lim);
455 $records = $this->dbo->loadAssocList();
456
457 if ($records) {
458 $this->dbo->setQuery('SELECT FOUND_ROWS();');
459 $this->setPagination($this->dbo->loadResult());
460 foreach ($records as $record) {
461 $ref_id = $record['id'];
462 unset($record['id']);
463 $def_vals[$ref_id] = $record;
464 }
465 } else {
466 $this->setError("Table " . $this->getTranslationTableName($table) . " has no Records.");
467 }
468 }
469
470 return $def_vals;
471 }
472
473 /**
474 * Sets the pagination HTML value for the current
475 * translation list, by using the Joomla native functions.
476 *
477 * @param int $tot_rows
478 */
479 private function setPagination($tot_rows)
480 {
481 jimport('joomla.html.pagination');
482 $pageNav = new JPagination($tot_rows, $this->lim0, $this->lim);
483 $this->navigation = $pageNav->getListFooter();
484 }
485
486 /**
487 * Returns the current pagination HTML value.
488 */
489 public function getPagination()
490 {
491 return $this->navigation;
492 }
493
494 /**
495 * Returns the translated records for this table and language
496 *
497 * @param string $table
498 * @param string $lang
499 *
500 * @return array
501 */
502 public function getTranslatedTable($table, $lang)
503 {
504 $translated = [];
505
506 $q = $this->dbo->getQuery(true);
507
508 $q->select($this->dbo->qn('t') . '.*')
509 ->from($this->dbo->qn('#__vikbooking_translations', 't'))
510 ->where($this->dbo->qn('t.table') . ' = ' . $this->dbo->q($this->adjustTablePrefix($table)))
511 ->where($this->dbo->qn('t.lang') . ' = ' . $this->dbo->q($lang))
512 ->order($this->dbo->qn('t.reference_id') . ' ASC');
513
514 $this->dbo->setQuery($q);
515
516 foreach ($this->dbo->loadAssocList() as $record) {
517 $record['content'] = json_decode($record['content'], true);
518 $translated[$record['reference_id']] = $record;
519 }
520
521 return $translated;
522 }
523
524 /**
525 * Main function to translate contents saved in the database.
526 *
527 * @param array $content The array taken from the database with the default values to be translated, passed as reference.
528 * @param string $table The name of the table containing the translation values, should match with the XML table name.
529 * @param array $alias_keys Key-Value pairs where Key is the ALIAS used and Value is the original field name. Opposite instead for the ID (reference_id).
530 * The key 'id' is always treated differently than the other keys. Correct usage: array('id' => 'idroom', 'room_name' => 'name')
531 * @param array $ids The reference_IDs to be translated, the IDs of the records. Taken from the content array if empty array passed.
532 * @param string $lang Force the translation to a specific language tag like it-IT.
533 *
534 * @return array The initial array with translated values (if applicable).
535 */
536 public function translateContents(&$content, $table, array $alias_keys = [], array $ids = [], $lang = null)
537 {
538 $to_lang = is_null($lang) ? $this->current_lang : $lang;
539 $to_lang = !is_null(self::$force_tolang) ? self::$force_tolang : $to_lang;
540
541 // multilang may be disabled
542 if (!$this->allowMultiLanguage()) {
543 return $content;
544 }
545
546 // check that requested lang is not the default lang
547 if ($to_lang == $this->default_lang || !$content) {
548 return $content;
549 }
550
551 // get all translatable columns of this table
552 $cols = $this->getTableColumns($table);
553
554 // get the reference ids to be translated
555 if (!count($ids)) {
556 $ids = $this->getReferencesFromContents($content, $alias_keys);
557 }
558
559 // load translations buffer for this table or set the var to an empty array
560 $translated = $this->getTranslationsBuffer($table, $ids, $to_lang);
561
562 if (!count($translated)) {
563 // load translations from db
564 $q = "SELECT * FROM `#__vikbooking_translations` WHERE `table`=" . $this->dbo->quote($this->adjustTablePrefix($table)) . " AND `lang`=" . $this->dbo->quote($to_lang) . (count($ids) ? " AND `reference_id` IN (" . implode(",", $ids) . ")" : "") . ";";
565 $this->dbo->setQuery($q);
566 $records = $this->dbo->loadAssocList();
567 foreach ($records as $record) {
568 $record['content'] = json_decode($record['content'], true);
569 if (is_array($record['content']) && $record['content']) {
570 $translated[$record['reference_id']] = $record['content'];
571 }
572 }
573 }
574
575 if ($translated) {
576 // set translations buffer
577 $this->translations_buffer[$table][$to_lang] = $translated;
578
579 // fetch reference_id to be translated and replace default lang values
580 $reference_key = array_key_exists('id', $alias_keys) ? $alias_keys['id'] : 'id';
581 foreach ($content as $ckey => $cvals) {
582 $reference_id = 0;
583 if (is_array($cvals)) {
584 foreach ($cvals as $subckey => $subcvals) {
585 if ($subckey == $reference_key) {
586 $reference_id = (int)$subcvals;
587 break;
588 }
589 }
590 $content[$ckey] = $this->translateArrayValues($cvals, $cols, $reference_id, $alias_keys, $translated);
591 } elseif ($ckey == $reference_key) {
592 $reference_id = (int)$cvals;
593 $content = $this->translateArrayValues($content, $cols, $reference_id, $alias_keys, $translated);
594 break;
595 }
596 }
597 }
598
599 return $content;
600 }
601
602 /**
603 * Translates a single database record with no reference as a proxy for the records list translations.
604 *
605 * @param array|object $record The record (associative or object) to translate.
606 * @param string $table The database table to which the record belongs.
607 * @param string $lang Force the translation to a specific language tag like it-IT.
608 * @param array $alias_keys Key-Value pairs where Key is the ALIAS used and Value is the original field name.
609 * @param array $ids The reference_IDs to be translated, the IDs of the records.
610 *
611 * @return array|object The original record translated or identical.
612 *
613 * @uses translateContents()
614 *
615 * @since 1.17.2 (J) - 1.7.2 (WP)
616 */
617 public function translateRecord($record, $table, $lang = null, array $alias_keys = [], array $ids = [])
618 {
619 $is_assoc = is_array($record);
620 $is_object = is_object($record);
621
622 if ((!$is_assoc && !$is_object) || !$record) {
623 // abort
624 return $record;
625 }
626
627 if ($lang) {
628 // ensure the given language tag exists
629 $known_tags = $this->getLanguagesTags();
630
631 if (!in_array($lang, $known_tags)) {
632 // try to normalize the given language tag
633 $main_lang = substr($lang, 0, 2);
634 $main_langs = [];
635 foreach ($known_tags as $tag) {
636 $main_langs[$tag] = substr($tag, 0, 2);
637 }
638
639 // try to find the first matching 2-char language tag
640 $match_tag = array_search($main_lang, $main_langs);
641
642 if ($match_tag) {
643 // swap given lang
644 $lang = $match_tag;
645 }
646 }
647 }
648
649 // always cast the record to array and treat it as a list
650 $records = [(array) $record];
651
652 // translate record as a list
653 $this->translateContents($records, $table, $alias_keys, $ids, $lang);
654
655 // get the translated (or identical) record
656 $record = $records[0];
657
658 if ($is_object) {
659 // cast back to object
660 $record = (object) $record;
661 }
662
663 // return the evnetually translated original record
664 return $record;
665 }
666
667 /**
668 * Compares the array to be translated with the translation and replaces the array values if not empty.
669 *
670 * @param array $content default lang values to be translated.
671 * @param array $alias_keys Key_Values pairs where Key is the ALIAS used and Value is the original
672 * field name. Opposite instead for the ID (reference_id).
673 *
674 * @return array
675 */
676 private function getReferencesFromContents($content, $alias_keys)
677 {
678 $references = [];
679 $reference_key = array_key_exists('id', $alias_keys) ? $alias_keys['id'] : 'id';
680
681 if (!is_array($content) || !$content) {
682 return [];
683 }
684
685 foreach ($content as $ckey => $cvals) {
686 if (is_array($cvals)) {
687 foreach ($cvals as $subckey => $subcvals) {
688 if ($subckey == $reference_key) {
689 $references[] = (int)$subcvals;
690 break;
691 }
692 }
693 } elseif ($ckey == $reference_key) {
694 $references[] = (int)$cvals;
695 break;
696 }
697 }
698
699 if ($references) {
700 $references = array_unique($references);
701 }
702
703 return $references;
704 }
705
706 /**
707 * Check whether these reference IDs were already fetched from the db for this table
708 *
709 * @param string $table
710 * @param array $ids
711 * @param string $lang
712 *
713 * @return array
714 */
715 private function getTranslationsBuffer($table, $ids, $lang)
716 {
717 if (!count($this->translations_buffer) || !isset($this->translations_buffer[$table]) || !isset($this->translations_buffer[$table][$lang])) {
718 return array();
719 }
720
721 $missing = false;
722 foreach ($ids as $id) {
723 if (!isset($this->translations_buffer[$table][$lang][$id])) {
724 $missing = true;
725 break;
726 }
727 }
728
729 return $missing === false ? $this->translations_buffer[$table][$lang] : array();
730 }
731
732 /**
733 * Compares the array to be translated with the translation and replaces the array values if not empty.
734 *
735 * @param array $content default lang values to be translated.
736 * @param array $cols the columns of this table.
737 * @param int $reference_id reference_id.
738 * @param array $alias_keys Key_Values pairs where Key is the ALIAS used and Value is the original field name.
739 * Opposite instead for the ID (reference_id).
740 * @param array $translated translated.
741 */
742 private function translateArrayValues($content, $cols, $reference_id, $alias_keys, $translated)
743 {
744 if (empty($reference_id)) {
745 return $content;
746 }
747
748 if (!array_key_exists($reference_id, $translated)) {
749 return $content;
750 }
751
752 foreach ($content as $key => $value) {
753 $native_key = $key;
754 if (count($alias_keys) > 0 && array_key_exists($key, $alias_keys) && $key != 'id') {
755 $key = $alias_keys[$key];
756 }
757 if (!array_key_exists($key, $cols)) {
758 continue;
759 }
760 if (array_key_exists($key, $translated[$reference_id]) && strlen($translated[$reference_id][$key]) > 0) {
761 $type = $cols[$key]['type'];
762 if ($type == 'json') {
763 // only the translated and not empty keys will be taken from the translation
764 $tn_json = json_decode($translated[$reference_id][$key], true);
765 $content_json = json_decode($value, true);
766 $jkeys = !empty($cols[$key]['keys']) ? explode(',', $cols[$key]['keys']) : array();
767 if (is_array($tn_json) && $tn_json && is_array($content_json) && $content_json) {
768 foreach ($content_json as $jk => $jv) {
769 if (array_key_exists($jk, $tn_json) && strlen($tn_json[$jk]) > 0) {
770 $content_json[$jk] = $tn_json[$jk];
771 }
772 }
773 $content[$native_key] = json_encode($content_json);
774 }
775 } else {
776 // field is a text type or a text-derived one
777 $content[$native_key] = $translated[$reference_id][$key];
778 }
779 }
780 }
781
782 return $content;
783 }
784
785 /**
786 * Sets and Returns the SimpleXML object for the translations
787 */
788 public function getTranslationsXML()
789 {
790 if (!is_file($this->translations_path_file)) {
791 $this->setError($this->translations_path_file . ' does not exist or is not readable');
792 return false;
793 }
794 if (!function_exists('simplexml_load_file')) {
795 $this->setError('Function simplexml_load_file is not available on the server.');
796 return false;
797 }
798 if (is_object($this->xml)) {
799 return $this->xml;
800 }
801 libxml_use_internal_errors(true);
802 if (($xml = simplexml_load_file($this->translations_path_file)) === false) {
803 $this->setError("Error reading XML:\n".$this->libxml_display_errors());
804 return false;
805 }
806 $this->xml = $xml;
807 return $xml;
808 }
809
810 /**
811 * Tells if the multi-language environment is enabled.
812 *
813 * @return bool
814 */
815 private function allowMultiLanguage()
816 {
817 return VikBooking::allowMultiLanguage();
818 }
819
820 /**
821 * Explanation of the XML error
822 *
823 * @param $error
824 */
825 public function libxml_display_error($error)
826 {
827 $return = "\n";
828 switch ($error->level) {
829 case LIBXML_ERR_WARNING :
830 $return .= "Warning ".$error->code.": ";
831 break;
832 case LIBXML_ERR_ERROR :
833 $return .= "Error ".$error->code.": ";
834 break;
835 case LIBXML_ERR_FATAL :
836 $return .= "Fatal Error ".$error->code.": ";
837 break;
838 }
839 $return .= trim($error->message);
840 if ($error->file) {
841 $return .= " in ".$error->file;
842 }
843 $return .= " on line ".$error->line."\n";
844 return $return;
845 }
846
847 /**
848 * Get the XML errors occurred
849 */
850 public function libxml_display_errors()
851 {
852 $errorstr = "";
853 $errors = libxml_get_errors();
854 foreach ($errors as $error) {
855 $errorstr .= $this->libxml_display_error($error);
856 }
857 libxml_clear_errors();
858 return $errorstr;
859 }
860
861 /**
862 * Concatenates an error to the errors string.
863 *
864 * @param string $str the error string to add.
865 *
866 * @return void
867 */
868 private function setError($str)
869 {
870 $this->error .= $str."\n";
871 }
872
873 /**
874 * Returns the current error string in HTML format.
875 *
876 * @return string
877 */
878 public function getError()
879 {
880 return nl2br(rtrim($this->error, "\n"));
881 }
882
883 /**
884 * Sets a key value to search/filter translations for.
885 *
886 * @param string $key the term to search/filter.
887 *
888 * @return self
889 */
890 public function setKeySearch($key)
891 {
892 $this->keysearch = (string) $key;
893
894 return $this;
895 }
896 }
897