Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
 
4
/**
5
 * Contains the Translation2_Admin_Container_xml class
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. The name of the author may not be used to endorse or promote products
17
 *    derived from this software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
23
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @category  Internationalization
31
 * @package   Translation2
32
 * @author    Lorenzo Alberton <l.alberton@quipo.it>
33
 * @author    Olivier Guilyardi <olivier@samalyse.com>
34
 * @copyright 2004-2007 Lorenzo Alberton, Olivier Guilyardi
35
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
36
 * @version   CVS: $Id: xml.php 305985 2010-12-05 22:55:33Z clockwerx $
37
 * @link      http://pear.php.net/package/Translation2
38
 */
39
 
40
/**
41
 * require Translation2_Container_xml class
42
 */
43
require_once 'Translation2/Container/xml.php';
44
 
45
require_once 'XML/Util.php';
46
 
47
/**
48
 * Storage driver for storing/fetching data to/from a XML file
49
 *
50
 * @category  Internationalization
51
 * @package   Translation2
52
 * @author    Lorenzo Alberton <l.alberton@quipo.it>
53
 * @author    Olivier Guilyardi <olivier@samalyse.com>
54
 * @copyright 2004-2007 Lorenzo Alberton, Olivier Guilyardi
55
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
56
 * @link      http://pear.php.net/package/Translation2
57
 */
58
class Translation2_Admin_Container_xml extends Translation2_Container_xml
59
{
60
    // {{{ class vars
61
 
62
    /**
63
     * Whether _saveData() is already registered at shutdown or not
64
     * @var boolean
65
     */
66
    var $_isScheduledSaving = false;
67
 
68
    // }}}
69
    // {{{ addLang()
70
 
71
    /**
72
     * Does nothing (here for compatibility with the container interface)
73
     *
74
     * @param array $langData language data
75
     * @param array $options  language options
76
     *
77
     * @return true|PEAR_Error
78
     */
79
    function addLang($langData, $options = array())
80
    {
81
        return true;
82
    }
83
 
84
    // }}}
85
    // {{{ addLangToList()
86
 
87
    /**
88
     * Creates a new entry in the <languages> section
89
     *
90
     * @param array $langData array('lang_id'    => 'en',
91
     *                              'name'       => 'english',
92
     *                              'meta'       => 'some meta info',
93
     *                              'error_text' => 'not available',
94
     *                              'encoding'   => 'iso-8859-1',
95
     *              );
96
     *
97
     * @return true|PEAR_Error
98
     */
99
    function addLangToList($langData)
100
    {
101
        $validInput = array(
102
            'name'       => '',
103
            'meta'       => '',
104
            'error_text' => '',
105
            'encoding'   => 'iso-8859-1',
106
        );
107
 
108
        foreach ($validInput as $key => $val) {
109
            if (isset($langData[$key])) $validInput[$key] = $langData[$key];
110
        }
111
 
112
        $this->_data['languages'][$langData['lang_id']] = $validInput;
113
        return $this->_scheduleSaving();
114
    }
115
 
116
    // }}}
117
    // {{{ updateLang()
118
 
119
    /**
120
     * Update the lang info in the langsAvail table
121
     *
122
     * @param array $langData array [@see addLangToList()]
123
     *
124
     * @return true|PEAR_Error
125
     */
126
    function updateLang($langData)
127
    {
128
        $allFields = array( //'lang_id',
129
            'name', 'meta', 'error_text', 'encoding',
130
        );
131
        foreach ($allFields as $field) {
132
            if (isset($this->_data['languages'][$langData['lang_id']][$field])) {
133
                $this->_data['languages'][$langData['lang_id']][$field] = $langData[$field];
134
            }
135
        }
136
        $success = $this->_scheduleSaving();
137
        $this->fetchLangs();  //update memory cache
138
        return $success;
139
    }
140
 
141
    // }}}
142
    // {{{ add()
143
 
144
    /**
145
     * Add a new entry in the strings table.
146
     *
147
     * @param string $stringID    string ID
148
     * @param string $pageID      page/group ID
149
     * @param array  $stringArray Associative array with string translations.
150
     *               Sample format: array('en' => 'sample', 'it' => 'esempio')
151
     *
152
     * @return true|PEAR_Error
153
     */
154
    function add($stringID, $pageID, $stringArray)
155
    {
156
        $langs = array_intersect(
157
            array_keys($stringArray),
158
            $this->getLangs('ids')
159
        );
160
 
161
        $pageID = is_null($pageID) ? '#NULL'  : $pageID;
162
        $pageID = empty($pageID)   ? '#EMPTY' : $pageID;
163
 
164
        if (!array_key_exists($pageID, $this->_data['pages'])) {
165
            $this->_data['pages'][$pageID] = array();
166
        }
167
        if (!array_key_exists($stringID, $this->_data['pages'][$pageID])) {
168
            $this->_data['pages'][$pageID][$stringID] = array();
169
        }
170
        foreach ($langs as $lang) {
171
            $this->_data['pages'][$pageID][$stringID][$lang] = $stringArray[$lang];
172
        }
173
 
174
        return $this->_scheduleSaving();
175
    }
176
 
177
    // }}}
178
    // {{{ update()
179
 
180
    /**
181
     * Update an existing entry in the strings table.
182
     *
183
     * @param string $stringID    string ID
184
     * @param string $pageID      page/group ID
185
     * @param array  $stringArray Associative array with string translations.
186
     *               Sample format: array('en' => 'sample', 'it' => 'esempio')
187
     *
188
     * @return true|PEAR_Error
189
     */
190
    function update($stringID, $pageID, $stringArray)
191
    {
192
        return $this->add($stringID, $pageID, $stringArray);
193
    }
194
 
195
    // }}}
196
    // {{{ remove()
197
 
198
    /**
199
     * Remove an entry from the strings table.
200
     *
201
     * @param string $stringID string ID
202
     * @param string $pageID   page/group ID
203
     *
204
     * @return true|PEAR_Error
205
     */
206
    function remove($stringID, $pageID)
207
    {
208
        $pageID = is_null($pageID) ? '#NULL' : $pageID;
209
        $pageID = empty($pageID) ? '#EMPTY' : $pageID;
210
 
211
        unset ($this->_data['pages'][$pageID][$stringID]);
212
        if (!count($this->_data['pages'][$pageID])) {
213
            unset ($this->_data['pages'][$pageID]);
214
        }
215
 
216
        return $this->_scheduleSaving();
217
    }
218
 
219
    // }}}
220
    // {{{ removeLang()
221
 
222
    /**
223
     * Remove all the entries for the given lang from the strings table.
224
     *
225
     * @param string  $langID language ID
226
     * @param boolean $force  (ignored)
227
     *
228
     * @return true|PEAR_Error
229
     */
230
    function removeLang($langID, $force = true)
231
    {
232
        // remove lang metadata
233
        unset($this->_data['languages'][$langID]);
234
 
235
        // remove the entries
236
        foreach (array_keys($this->_data['pages']) as $pageID) {
237
            foreach (array_keys($this->_data['pages'][$pageID]) as $stringID) {
238
                if (array_key_exists($langID, $this->_data['pages'][$pageID][$stringID])) {
239
                    unset($this->_data['pages'][$pageID][$stringID][$langID]);
240
                }
241
            }
242
        }
243
        return $this->_scheduleSaving();
244
    }
245
 
246
    // }}}
247
    // {{{ removePage()
248
 
249
    /**
250
     * Remove all the strings in the given page/group
251
     *
252
     * @param string $pageID page/group ID
253
     *
254
     * @return true|PEAR_Error
255
     */
256
    function removePage($pageID = null)
257
    {
258
        $pageID = is_null($pageID) ? '#NULL' : $pageID;
259
        $pageID = empty($pageID) ? '#EMPTY' : $pageID;
260
 
261
        unset ($this->_data['pages'][$pageID]);
262
 
263
        return $this->_scheduleSaving();
264
    }
265
 
266
    // }}}
267
    // {{{ getPageNames()
268
 
269
    /**
270
     * Get a list of all the pageIDs.
271
     *
272
     * @return array
273
     */
274
    function getPageNames()
275
    {
276
        $pages = array_keys($this->_data['pages']);
277
        $k = array_search('#NULL', $pages);
278
        if ($k !== false && !is_null($k)) {
279
            $pages[$k] = null;
280
        }
281
        $k = array_search('#EMPTY', $pages);
282
        if ($k !== false && !is_null($k)) {
283
            $pages[$k] = '';
284
        }
285
        return $pages;
286
    }
287
 
288
    // }}}
289
    // {{{ _scheduleSaving()
290
 
291
    /**
292
     * Prepare data saving
293
     *
294
     * This methods registers _saveData() as a PEAR shutdown function. This
295
     * is to avoid saving multiple times if the programmer makes several
296
     * changes.
297
     *
298
     * @return true|PEAR_Error
299
     * @access private
300
     * @see Translation2_Admin_Container_xml::_saveData()
301
     */
302
    function _scheduleSaving()
303
    {
304
        if ($this->options['save_on_shutdown']) {
305
            if (!$this->_isScheduledSaving) {
306
                // save the changes on shutdown
307
                register_shutdown_function(array(&$this, '_saveData'));
308
                $this->_isScheduledSaving = true;
309
            }
310
            return true;
311
        }
312
 
313
        // save the changes now
314
        return $this->_saveData();
315
    }
316
 
317
    // }}}
318
    // {{{ _saveData()
319
 
320
    /**
321
     * Serialize and save the updated tranlation data to the XML file
322
     *
323
     * @return boolean | PEAR_Error
324
     * @access private
325
     * @see Translation2_Admin_Container_xml::_scheduleSaving()
326
     */
327
    function _saveData()
328
    {
329
        if ($this->options['save_on_shutdown']) {
330
            $data =& $this->_data;
331
        } else {
332
            $data =  $this->_data;
333
        }
334
 
335
        $this->_convertEncodings('to_xml', $data);
336
        $this->_convertLangEncodings('to_xml', $data);
337
 
338
        // Serializing
339
 
340
        $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" .
341
               "<!DOCTYPE translation2 [\n" . TRANSLATION2_DTD . "]>\n\n" .
342
               "<translation2>\n" .
343
               "  <languages>\n";
344
 
345
        foreach ($data['languages'] as $lang => $spec) {
346
            extract ($spec);
347
            $xml .= "    <lang id=\"$lang\">\n" .
348
                    "      <name>" .
349
                    ($name ? ' ' . XML_Util::replaceEntities($name) . ' ' : '') .
350
                    "</name>\n" .
351
                    "      <meta>" .
352
                    ($meta ? ' ' . XML_Util::replaceEntities($meta) . ' ' : "") .
353
                    "</meta>\n" .
354
                    "      <error_text>" .
355
                    ($error_text
356
                        ? ' ' . XML_Util::replaceEntities($error_text) . ' '
357
                        : "") .
358
                    "</error_text>\n" .
359
                    "      <encoding>" . ($encoding ? " $encoding " : "") .
360
                    "</encoding>\n" .
361
                    "    </lang>\n";
362
        }
363
 
364
        $xml .= "  </languages>\n" .
365
                "  <pages>\n";
366
 
367
        foreach ($data['pages'] as $page => $strings) {
368
            $xml .= "    <page key=\"" . XML_Util::replaceEntities($page) .
369
                    "\">\n";
370
            foreach ($strings as $str_id => $translations) {
371
                $xml .= "      <string key=\"" .
372
                        XML_Util::replaceEntities($str_id) . "\">\n";
373
                foreach ($translations as $lang => $str) {
374
                    $xml .= "        <tr lang=\"$lang\"> " .
375
                            XML_Util::replaceEntities($str) . " </tr>\n";
376
                }
377
                $xml .= "      </string>\n";
378
            }
379
            $xml .= "    </page>\n";
380
        }
381
 
382
        $xml .= "  </pages>\n" .
383
                "</translation2>\n";
384
 
385
        unset ($data);
386
 
387
        // Saving
388
 
389
        if (!$f = fopen ($this->_filename, 'w')) {
390
            return $this->raiseError(sprintf(
391
                    'Unable to open the XML file ("%s") for writing',
392
                    $this->_filename
393
                ),
394
                TRANSLATION2_ERROR_CANNOT_WRITE_FILE,
395
                PEAR_ERROR_TRIGGER,
396
                E_USER_ERROR
397
            );
398
        }
399
        @flock($f, LOCK_EX);
400
        fwrite ($f, $xml);
401
        //@flock($f, LOCK_UN);
402
        fclose ($f);
403
        return true;
404
    }
405
 
406
    // }}}
407
}
408
?>