1<?php
2
3/* Copyright (c) 1998-2014 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5/**
6 * Class handles translation mode for an object.
7 *
8 * Objects may not use any translations at all
9 * - use translations for title/description only or
10 * - use translation for (the page editing) content, too.
11 *
12 * Currently supported by container objects and ILIAS learning modules.
13 *
14 * Content master lang vs. default language
15 * - If no translation mode for the content is active no master lang will be
16 *   set and no record in table obj_content_master_lng will be saved. For the
17 *   title/descriptions the default will be marked by field lang_default in table
18 *   object_translation.
19 * - If translation for content is activated a master language must be set (since
20 *   concent may already exist the language of this content is defined through
21 *   setting the master language (in obj_content_master_lng). Modules that use
22 *   this mode will not get informed about this, so they can not internally
23 *   assign existing content to the master lang
24 *
25 * @author Alex Killing <alex.killing@gmx.de>
26 * @version $Id$
27 * @ingroup ServicesObject
28 */
29class ilMultilingualism
30{
31    /**
32     * @var ilLanguage
33     */
34    protected $lng;
35
36    protected $db;
37    protected $obj_id;
38    protected $languages = array();
39    protected $type = "";
40    protected static $instances = array();
41
42    /**
43     * Constructor
44     *
45     * @param int $a_obj_id object id
46     * @param string $a_type id type
47     * @throws ilObjectException
48     */
49    private function __construct($a_obj_id, $a_type)
50    {
51        global $DIC;
52
53        $this->lng = $DIC->language();
54        $ilDB = $DIC->database();
55
56        $this->db = $ilDB;
57
58        $this->setObjId($a_obj_id);
59        $this->setType($a_type);
60
61        if ($this->getObjId() <= 0) {
62            include_once("./Services/Object/exceptions/class.ilObjectException.php");
63            throw new ilObjectException("ilObjectTranslation: No object ID passed.");
64        }
65
66        $this->read();
67    }
68
69    /**
70     * Get instance
71     *
72     * @param integer $a_obj_id (repository) object id
73     * @return ilMultilingualism translation object
74     */
75    public static function getInstance($a_obj_id, $a_type)
76    {
77        if (!isset(self::$instances[$a_type][$a_obj_id])) {
78            self::$instances[$a_type][$a_obj_id] = new self($a_obj_id, $a_type);
79        }
80
81        return self::$instances[$a_type][$a_obj_id];
82    }
83
84
85    /**
86     * Set object id
87     *
88     * @param int $a_val object id
89     */
90    public function setObjId($a_val)
91    {
92        $this->obj_id = $a_val;
93    }
94
95    /**
96     * Get object id
97     *
98     * @return int object id
99     */
100    public function getObjId()
101    {
102        return $this->obj_id;
103    }
104
105    /**
106     * Set languages
107     *
108     * @param array $a_val array of language codes
109     */
110    public function setLanguages(array $a_val)
111    {
112        $this->languages = $a_val;
113    }
114
115    /**
116     * Get languages
117     *
118     * @return array array of language codes
119     */
120    public function getLanguages()
121    {
122        return $this->languages;
123    }
124
125    /**
126     * @return string
127     */
128    public function getType()
129    {
130        return $this->type;
131    }
132
133    /**
134     * @param string $type
135     */
136    public function setType($type)
137    {
138        $this->type = $type;
139    }
140
141    public function getDefaultLanguage()
142    {
143        $lng = $this->lng;
144
145        foreach ($this->languages as $k => $v) {
146            if ($v["lang_default"]) {
147                return $k;
148            }
149        }
150
151        return $lng->getDefaultLanguage();
152    }
153
154
155    /**
156     * Add language
157     *
158     * @param string $a_lang language
159     * @param string $a_title title
160     * @param string $a_description description
161     * @param bool $a_default default language?
162     */
163    public function addLanguage($a_lang, $a_title, $a_description, $a_default, $a_force = false)
164    {
165        if ($a_lang != "" && (!isset($this->languages[$a_lang]) || $a_force)) {
166            if ($a_default) {
167                foreach ($this->languages as $k => $l) {
168                    $this->languages[$k]["lang_default"] = false;
169                }
170            }
171            $this->languages[$a_lang] = array("lang_code" => $a_lang, "lang_default" => $a_default,
172                "title" => $a_title, "description" => $a_description);
173        }
174    }
175
176    /**
177     * Get default title
178     *
179     * @return string title of default language
180     */
181    public function getDefaultTitle()
182    {
183        foreach ($this->languages as $l) {
184            if ($l["lang_default"]) {
185                return $l["title"];
186            }
187        }
188        return "";
189    }
190
191    /**
192     * Set default title
193     *
194     * @param string $a_title title
195     */
196    public function setDefaultTitle($a_title)
197    {
198        foreach ($this->languages as $k => $l) {
199            if ($l["lang_default"]) {
200                $this->languages[$k]["title"] = $a_title;
201            }
202        }
203    }
204
205    /**
206     * Get default description
207     *
208     * @return string description of default language
209     */
210    public function getDefaultDescription()
211    {
212        foreach ($this->languages as $l) {
213            if ($l["lang_default"]) {
214                return $l["description"];
215            }
216        }
217        return "";
218    }
219
220    /**
221     * Set default description
222     *
223     * @param string $a_description description
224     */
225    public function setDefaultDescription($a_description)
226    {
227        foreach ($this->languages as $k => $l) {
228            if ($l["lang_default"]) {
229                $this->languages[$k]["description"] = $a_description;
230            }
231        }
232    }
233
234
235    /**
236     * Remove language
237     *
238     * @param string $a_lang language code
239     */
240    public function removeLanguage($a_lang)
241    {
242        if ($a_lang != $this->getDefaultLanguage()) {
243            unset($this->languages[$a_lang]);
244        }
245    }
246
247    /**
248     * Read
249     */
250    public function read()
251    {
252        $this->setLanguages(array());
253        $set = $this->db->query(
254            "SELECT * FROM il_translations " .
255            " WHERE id = " . $this->db->quote($this->getObjId(), "integer") .
256            " AND id_type = " . $this->db->quote($this->getType(), "text")
257        );
258        while ($rec = $this->db->fetchAssoc($set)) {
259            $this->addLanguage($rec["lang_code"], $rec["title"], $rec["description"], $rec["lang_default"]);
260        }
261    }
262
263    /**
264     * Delete
265     */
266    public function delete()
267    {
268        $this->db->manipulate(
269            "DELETE FROM il_translations " .
270            " WHERE id = " . $this->db->quote($this->getObjId(), "integer") .
271            " AND id_type = " . $this->db->quote($this->getType(), "text")
272        );
273    }
274
275    /**
276     * Save
277     */
278    public function save()
279    {
280        $this->delete();
281
282        foreach ($this->getLanguages() as $l => $trans) {
283            $this->db->manipulate($t = "INSERT INTO il_translations " .
284                "(id, id_type, title, description, lang_code, lang_default) VALUES (" .
285                $this->db->quote($this->getObjId(), "integer") . "," .
286                $this->db->quote($this->getType(), "text") . "," .
287                $this->db->quote($trans["title"], "text") . "," .
288                $this->db->quote($trans["description"], "text") . "," .
289                $this->db->quote($l, "text") . "," .
290                $this->db->quote($trans["lang_default"], "integer") .
291                ")");
292        }
293    }
294
295    /**
296     * Copy multilinguality settings
297     *
298     * @param string $a_type parent object type
299     * @param int $a_obj_id parent object id
300     * @return ilObjectTranslation target multilang object
301     */
302    public function copy($a_obj_id)
303    {
304        $target_ml = new self($a_obj_id, $this->getType());
305        $target_ml->setLanguages($this->getLanguages());
306        $target_ml->save();
307        return $target_ml;
308    }
309
310
311
312    /**
313     * Export
314     * @param ilXmlWriter $writer
315     * @return ilXmlWriter
316     */
317    public function toXml(ilXmlWriter $writer)
318    {
319        $writer->xmlStartTag('translations');
320
321        foreach ($this->getLanguages() as $k => $v) {
322            $writer->xmlStartTag('translation', array('language' => $k, 'default' => $v['lang_default'] ? 1 : 0));
323            $writer->xmlElement('title', array(), $v['title']);
324            $writer->xmlElement('description', array(), $v['description']);
325            $writer->xmlEndTag('translation');
326        }
327        $writer->xmlEndTag('translations');
328
329        return $writer;
330    }
331
332    /**
333     * xml import
334     *
335     * @param SimpleXMLElement $root
336     * @return mixed
337     */
338    public function fromXML(SimpleXMLElement $root)
339    {
340        if ($root->translations) {
341            $root = $root->translations;
342        }
343
344        foreach ($root->translation as $trans) {
345            $this->addLanguage(
346                (string) trim($trans["language"]),
347                (string) trim($trans->title),
348                (string) trim($trans->description),
349                (int) $trans["default"] != 0?true:false
350            );
351        }
352    }
353}
354