1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * Contains the Translation2_Decorator_CacheLiteFunction 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 * @copyright 2004-2007 Lorenzo Alberton
34 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
35 * @version   CVS: $Id: CacheLiteFunction.php 305985 2010-12-05 22:55:33Z clockwerx $
36 * @link      http://pear.php.net/package/Translation2
37 */
38
39/**
40 * Load Translation2 decorator base class
41 * and Cache_Lite_Function class
42 */
43require_once 'Translation2/Decorator.php';
44require_once 'Cache/Lite/Function.php';
45
46/**
47 * Decorator to cache fetched data using the Cache_Lite_Function class.
48 *
49 * @category  Internationalization
50 * @package   Translation2
51 * @author    Lorenzo Alberton <l.alberton@quipo.it>
52 * @copyright 2004-2007 Lorenzo Alberton
53 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
54 * @version   CVS: $Id: CacheLiteFunction.php 305985 2010-12-05 22:55:33Z clockwerx $
55 * @link      http://pear.php.net/package/Translation2
56 */
57class Translation2_Decorator_CacheLiteFunction extends Translation2_Decorator
58{
59    // {{{ class vars
60
61    /**
62     * Cache_Lite_Function object
63     * @var object
64     */
65    var $cacheLiteFunction = null;
66
67    /**
68     * @var int (default 1)
69     * @access private
70     */
71    var $tempVarNameGenerator = 1;
72
73    /**
74     * @var string
75     * @access private
76     */
77    var $tempVarName = null;
78
79    /**
80     * Cache lifetime (in seconds)
81     * @var int $lifeTime
82     * @access private
83     */
84    var $lifeTime = 3600;
85
86    /**
87     * Directory where to put the cache files
88     * (make sure to add a trailing slash)
89     * @var string $cacheDir
90     * @access private
91     */
92    var $cacheDir = '/tmp/';
93
94    /**
95     * Enable / disable fileLocking. Can avoid cache corruption under bad
96     * circumstances.
97     * @var string $cacheDir
98     * @access private
99     */
100    var $fileLocking = true;
101
102    /**
103     * Enable / disable caching
104     * (can be very useful to debug cached scripts)
105     * @var boolean $caching
106     */
107    var $caching = true;
108
109    /**
110     * Frequency of cache cleaning.
111     * Higher values mean lower cleaning probability.
112     * Set 0 to disable. Set 1 to clean at every request.
113     * @var boolean $caching
114     */
115    var $cleaningFrequency = 0;
116
117    /**
118     * Name of default cache group.
119     * @var	string	$defaultGroup
120     */
121     var $defaultGroup = 'Translation2';
122
123    // }}}
124    // {{{ _prepare()
125
126    /**
127     * Istanciate a new Cache_Lite_Function object
128     * and get the name for an unused global variable,
129     * needed by Cache_Lite_Function
130     *
131     * @return void
132     * @access private
133     */
134    function _prepare()
135    {
136        if (is_null($this->cacheLiteFunction)) {
137            $cache_options = array(
138                'caching'      => $this->caching,
139                'cacheDir'     => $this->cacheDir,
140                'lifeTime'     => $this->lifeTime,
141                'fileLocking'  => $this->fileLocking,
142                'defaultGroup' => $this->defaultGroup,
143
144            );
145            $this->cacheLiteFunction = new Cache_Lite_Function($cache_options);
146        }
147
148        $this->_cleanCache();
149    }
150
151    // }}}
152    // {{{ setLang()
153
154    /**
155     * Set default lang
156     *
157     * Set the language that shall be used when retrieving strings.
158     *
159     * @param string $langID language code (for instance, 'en' or 'it')
160     *
161     * @return void
162     */
163    function setLang($langID)
164    {
165        // WITHOUT THIS, IT DOESN'T WORK
166        global $translation2_storage_cachelitefunction_temp;
167        //generate temp variable
168        $translation2_storage_cachelitefunction_temp = $this->translation2->storage;
169
170        $this->_prepare();
171        $res = $this->cacheLiteFunction->call(
172            'translation2_storage_cachelitefunction_temp->setLang', $langID);
173        if (PEAR::isError($res)) {
174            return $res;
175        }
176        $this->translation2->lang = $res;
177
178    }
179
180    // }}}
181    // {{{ setCacheOption()
182
183    /**
184     * Set a Cache_Lite option
185     *
186     * Passes a Cache_Lite option forward to the Cache_Lite object
187     * See Cache_Lite constructor for available options
188     *
189     * @param string $name  name of the option
190     * @param string $value new value of the option
191     *
192     * @return self
193     * @access public
194     * @see Cache_Lite::setOption()
195     */
196    function setCacheOption($name, $value)
197    {
198        $this->_prepare();
199        $this->cacheLiteFunction->setOption($name, $value);
200        return $this;
201    }
202
203    // }}}
204    // {{{ getLang()
205
206    /**
207     * get lang info
208     *
209     * Get some extra information about the language (its full name,
210     * the localized error text, ...)
211     *
212     * @param string $langID language ID
213     * @param string $format ['name', 'meta', 'error_text', 'array']
214     *
215     * @return mixed [string | array], depending on $format
216     */
217    function getLang($langID = null, $format = 'name')
218    {
219        $langs = $this->getLangs('array');
220
221        if (is_null($langID)) {
222            if (!isset($this->lang['id']) || !array_key_exists($this->lang['id'], $langs)) {
223                $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
224                      .' Use Translation2::setLang() to set a default language.';
225                return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
226            }
227            $langID = $this->lang['id'];
228        }
229
230        if ($format == 'array') {
231            return $langs[$langID];
232        } elseif (isset($langs[$langID][$format])) {
233            return $langs[$langID][$format];
234        } elseif (isset($langs[$langID]['name'])) {
235            return $langs[$langID]['name'];
236        }
237        $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
238              .' Use Translation2::setLang() to set a default language.';
239        return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
240    }
241
242    // }}}
243    // {{{ getLangs()
244
245    /**
246     * get langs
247     *
248     * Get some extra information about the languages (their full names,
249     * the localized error text, their codes, ...)
250     *
251     * @param string $format ['ids', 'names', 'array']
252     *
253     * @return array
254     */
255    function getLangs($format = 'name')
256    {
257        // WITHOUT THIS, IT DOESN'T WORK
258        global $translation2_cachelitefunction_temp;
259        //generate temp variable
260        $translation2_cachelitefunction_temp = $this->translation2;
261
262        $this->_prepare();
263        return $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getLangs',
264            $format);
265    }
266
267    // }}}
268    // {{{ getRaw()
269
270    /**
271     * Get translated string (as-is)
272     *
273     * First check if the string is cached, if not => fetch the page
274     * from the container and cache it for later use.
275     *
276     * @param string $stringID    string ID
277     * @param string $pageID      page/group ID
278     * @param string $langID      language ID
279     * @param string $defaultText Text to display when the strings in both
280     *                            the default and the fallback lang are empty
281     *
282     * @return string
283     */
284    function getRaw($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
285    {
286        // WITHOUT THIS, IT DOESN'T WORK
287        global $translation2_cachelitefunction_temp;
288        //generate temp variable
289        $translation2_cachelitefunction_temp = $this->translation2;
290
291        if ($pageID == TRANSLATION2_DEFAULT_PAGEID) {
292            $pageID = $this->translation2->currentPageID;
293        }
294        $langID = empty($langID) ? $this->translation2->lang['id'] : $langID;
295
296        $this->_prepare();
297
298        return $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getRaw',
299            $stringID, $pageID, $langID, $defaultText);
300    }
301
302    // }}}
303    // {{{ get()
304
305    /**
306     * Get translated string
307     *
308     * First check if the string is cached, if not => fetch the page
309     * from the container and cache it for later use.
310     *
311     * @param string $stringID    string ID
312     * @param string $pageID      page/group ID
313     * @param string $langID      language ID
314     * @param string $defaultText Text to display when the strings in both
315     *                            the default and the fallback lang are empty
316     *
317     * @return string
318     */
319    function get($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
320    {
321        // WITHOUT THIS, IT DOESN'T WORK
322        global $translation2_cachelitefunction_temp;
323        //generate temp variable
324        $translation2_cachelitefunction_temp = $this->translation2->storage;
325
326        if ($pageID == TRANSLATION2_DEFAULT_PAGEID) {
327            $pageID = $this->translation2->currentPageID;
328        }
329        $langID = empty($langID) ? $this->translation2->lang['id'] : $langID;
330
331        $this->_prepare();
332
333        $string = $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getOne',
334            $stringID, $pageID, $langID);
335        if (empty($string)) {
336            return $defaultText;
337        }
338        return $this->translation2->_replaceParams($string);
339    }
340
341    // }}}
342    // {{{ getRawPage()
343
344    /**
345     * Get the array of strings in a page
346     *
347     * First check if the strings are cached, if not => fetch the page
348     * from the container and cache it for later use.
349     *
350     * @param string $pageID page/group ID
351     * @param string $langID language ID
352     *
353     * @return array
354     */
355    function getRawPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
356    {
357        // WITHOUT THIS, IT DOESN'T WORK
358        global $translation2_cachelitefunction_temp;
359        //generate temp variable
360        $translation2_cachelitefunction_temp = $this->translation2;
361
362        if ($pageID == TRANSLATION2_DEFAULT_PAGEID) {
363            $pageID = $this->translation2->currentPageID;
364        }
365        $langID = empty($langID) ? $this->translation2->lang['id'] : $langID;
366
367        $this->_prepare();
368
369        return $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getRawPage',
370            $pageID, $langID);
371    }
372
373    // }}}
374    // {{{ getPage()
375
376    /**
377     * Same as getRawPage, but resort to fallback language and
378     * replace parameters when needed
379     *
380     * @param string $pageID page/group ID
381     * @param string $langID language ID
382     *
383     * @return array
384     */
385    function getPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
386    {
387        // WITHOUT THIS, IT DOESN'T WORK
388        global $translation2_cachelitefunction_temp;
389        //generate temp variable
390        $translation2_cachelitefunction_temp = $this->translation2;
391
392        if ($pageID == TRANSLATION2_DEFAULT_PAGEID) {
393            $pageID = $this->translation2->currentPageID;
394        }
395        $langID = empty($langID) ? $this->translation2->lang['id'] : $langID;
396
397        $this->_prepare();
398
399        return $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getPage',
400            $pageID, $langID);
401    }
402
403    // }}}
404    // {{{ getStringID()
405
406    /**
407     * Get translated string
408     *
409     * @param string $string This is NOT the stringID, this is a real string.
410     *                       The method will search for its matching stringID,
411     *                       and then it will return the associate string in the
412     *                       selected language.
413     * @param string $pageID page/group ID
414     *
415     * @return string
416     */
417    function getStringID($string, $pageID=TRANSLATION2_DEFAULT_PAGEID)
418    {
419        // WITHOUT THIS, IT DOESN'T WORK
420        global $translation2_cachelitefunction_temp;
421        //generate temp variable
422        $translation2_cachelitefunction_temp = $this->translation2;
423
424        if ($pageID == TRANSLATION2_DEFAULT_PAGEID) {
425            $pageID = $this->translation2->currentPageID;
426        }
427        $this->_prepare();
428
429        return $this->cacheLiteFunction->call('translation2_cachelitefunction_temp->getStringID',
430            $string, $pageID);
431    }
432
433    // }}}
434    // {{{ _cleanCache()
435
436    /**
437     * Statistically purge the cache
438     *
439     * @return void
440     */
441    function _cleanCache()
442    {
443        if ($this->cleaningFrequency > 0) {
444            if (mt_rand(1, $this->cleaningFrequency) == 1) {
445                $this->cacheLiteFunction->clean($this->defaultGroup);
446            }
447        }
448    }
449
450    // }}}
451}
452?>