Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Dir structure

git-svn-id: http://svn.php.net/repository/pear/packages/Translation2/trunk@305985 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
commit b61731fef54652a258681269c01295a691e10625 1 parent bf9bb2f
Daniel O'Connor CloCkWeRX authored

Showing 26 changed files with 7,512 additions and 2 deletions. Show diff stats Hide diff stats

  1. 0  { → Translation2}/Admin.php
  2. +241 0 Translation2/Admin/Container/dataobjectsimple.php
  3. +721 0 Translation2/Admin/Container/db.php
  4. +640 0 Translation2/Admin/Container/gettext.php
  5. +714 0 Translation2/Admin/Container/mdb.php
  6. +758 0 Translation2/Admin/Container/mdb2.php
  7. +408 0 Translation2/Admin/Container/xml.php
  8. +221 0 Translation2/Admin/Decorator.php
  9. +112 0 Translation2/Admin/Decorator/Autoadd.php
  10. 0  { → Translation2}/Container.php
  11. +255 0 Translation2/Container/dataobjectsimple.php
  12. +359 0 Translation2/Container/db.php
  13. +351 0 Translation2/Container/gettext.php
  14. +339 0 Translation2/Container/mdb.php
  15. +362 0 Translation2/Container/mdb2.php
  16. +500 0 Translation2/Container/xml.php
  17. 0  { → Translation2}/Decorator.php
  18. +452 0 Translation2/Decorator/CacheLiteFunction.php
  19. +229 0 Translation2/Decorator/CacheMemory.php
  20. +196 0 Translation2/Decorator/DefaultText.php
  21. +108 0 Translation2/Decorator/ErrorText.php
  22. +156 0 Translation2/Decorator/Iconv.php
  23. +149 0 Translation2/Decorator/Lang.php
  24. +125 0 Translation2/Decorator/SpecialChars.php
  25. +114 0 Translation2/Decorator/UTF8.php
  26. +2 2 package.xml
0  Admin.php → Translation2/Admin.php
File renamed without changes
241 Translation2/Admin/Container/dataobjectsimple.php
... ... @@ -0,0 +1,241 @@
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * Contains the Translation2_Admin_Container_dataobjectsimple 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 Alan Knowles <alan@akbkhome.com>
  33 + * @copyright 2004-2007 Alan Knowles
  34 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  35 + * @version CVS: $Id$
  36 + * @link http://pear.php.net/package/Translation2
  37 + */
  38 +
  39 +/**
  40 + * require Translation2_Container_dataobjectsimple class
  41 + */
  42 +require_once 'Translation2/Container/dataobjectsimple.php';
  43 +
  44 +/**
  45 + * Storage driver for storing/fetching data to/from a database
  46 + *
  47 + * This storage driver can use all databases which are supported
  48 + * by PEAR::DB_DataObject to fetch data.
  49 + *
  50 + * Database Structure:
  51 + *
  52 + * <pre>
  53 + * // meta data etc. not supported
  54 + *
  55 + * table: translations
  56 + * id // not null primary key autoincrement..
  57 + * string_id // translation id
  58 + * page // indexed varchar eg. (mytemplate.html)
  59 + * lang // index varchar (eg. en|fr|.....)
  60 + * translation // the translated value in language lang.
  61 + * </pre>
  62 + *
  63 + * @category Internationalization
  64 + * @package Translation2
  65 + * @author Alan Knowles <alan@akbkhome.com>
  66 + * @copyright 2004-2007 Alan Knowles
  67 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  68 + * @link http://pear.php.net/package/Translation2
  69 + */
  70 +class Translation2_Admin_Container_dataobjectsimple extends Translation2_Container_dataobjectsimple
  71 +{
  72 + // {{{ addLang()
  73 +
  74 + /**
  75 + * Creates a new table to store the strings in this language.
  76 + * If the table is shared with other langs, it is ALTERed to
  77 + * hold strings in this lang too.
  78 + *
  79 + * @param array $langData array('lang_id' => 'en',
  80 + * 'table_name' => 'i18n',
  81 + * 'name' => 'english',
  82 + * 'meta' => 'some meta info',
  83 + * 'error_text' => 'not available');
  84 + * @param array $options DB_DataObject options
  85 + *
  86 + * @return true|PEAR_Error
  87 + */
  88 + function addLang($langData, $options = array())
  89 + {
  90 + $do = DB_DataObject::factory($this->options['table']);
  91 + $do->lang = $langData['lang_id'];
  92 + if (!$do->find()) {
  93 + $do->insert();
  94 + }
  95 + }
  96 +
  97 + // }}}
  98 + // {{{ addLangToList()
  99 +
  100 + /**
  101 + * Creates a new entry in the langsAvail table.
  102 + * If the table doesn't exist yet, it is created.
  103 + *
  104 + * @param array $langData array('lang_id' => 'en',
  105 + * 'table_name' => 'i18n',
  106 + * 'name' => 'english',
  107 + * 'meta' => 'some meta info',
  108 + * 'error_text' => 'not available');
  109 + *
  110 + * @return true|PEAR_Error
  111 + */
  112 + function addLangToList($langData)
  113 + {
  114 + return true;
  115 + }
  116 +
  117 + // }}}
  118 + // {{{ add()
  119 +
  120 + /**
  121 + * Add a new entry in the strings table.
  122 + *
  123 + * @param string $string string
  124 + * @param string $pageID page/group ID
  125 + * @param array $stringArray Associative array with string translations.
  126 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  127 + *
  128 + * @return true|PEAR_Error
  129 + */
  130 + function add($string, $pageID, $stringArray)
  131 + {
  132 + //look up the string id first..
  133 + $do = DB_DataObject::factory($this->options['table']);
  134 + $do->lang = '-';
  135 + $do->translation = $string;
  136 + $do->page = $page;
  137 + if ($do->find(true)) {
  138 + $stringID = $do->string_id;
  139 + } else {
  140 + // insert it and use the 'id' as the string id
  141 + $stringID = $do->insert();
  142 + $do->string_id = $stringID;
  143 + $do->update();
  144 + }
  145 +
  146 + foreach ($stringArray as $lang=>$value) {
  147 + $do = DB_DataObject::factory($this->options['table']);
  148 + $do->string_id = $stringID;
  149 + $do->page = $pageID;
  150 + $do->lang = $lang;
  151 + if ($do->find(true)) {
  152 + $do->translation = $value;
  153 + $do->update();
  154 + continue;
  155 + }
  156 + $do->translation = $value;
  157 + $do->insert();
  158 + }
  159 +
  160 + return true;
  161 + }
  162 +
  163 + // }}}
  164 + // {{{ update()
  165 +
  166 + /**
  167 + * Update an existing entry in the strings table.
  168 + *
  169 + * @param string $stringID string ID
  170 + * @param string $pageID page/group ID
  171 + * @param array $stringArray Associative array with string translations.
  172 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  173 + *
  174 + * @return true|PEAR_Error
  175 + */
  176 + function update($stringID, $pageID, $stringArray)
  177 + {
  178 + $this->add($stringID, $pageID, $stringArray);
  179 + return true;
  180 + }
  181 +
  182 + // }}}
  183 + // {{{ remove()
  184 +
  185 + /**
  186 + * Remove an entry from the strings table.
  187 + *
  188 + * @param string $stringID string ID
  189 + * @param string $pageID page/group ID
  190 + *
  191 + * @return true|PEAR_Error
  192 + */
  193 + function remove($stringID, $pageID)
  194 + {
  195 + // get the string id
  196 + $do = DB_DataObject::factory($this->options['table']);
  197 + $do->page = $pageID;
  198 + $do->translation = $stringID;
  199 + // we don't have the base language translation..
  200 + if (!$do->find()) {
  201 + return '';
  202 + }
  203 +
  204 + while ($do->fetch()) {
  205 + $do2 = DB_DataObject::factory($this->options['table']);
  206 + $do2->get($do->id);
  207 + $do2->delete();
  208 + }
  209 + return true;
  210 + }
  211 +
  212 + // }}}
  213 + // {{{ removePage()
  214 +
  215 + /**
  216 + * Remove all the strings in the given page/group
  217 + *
  218 + * @param string $pageID page/group ID
  219 + *
  220 + * @return mixed true on success, PEAR_Error on failure
  221 + */
  222 + function removePage($pageID = null)
  223 + {
  224 + $do = DB_DataObject::factory($this->options['table']);
  225 + $do->page = $pageID;
  226 + // we don't have the base language translation..
  227 + if (!$do->find()) {
  228 + return '';
  229 + }
  230 +
  231 + while ($do->fetch()) {
  232 + $do2 = DB_DataObject::factory($this->options['table']);
  233 + $do2->get($do->id);
  234 + $do2->delete();
  235 + }
  236 + return true;
  237 + }
  238 +
  239 + // }}}
  240 +}
  241 +?>
721 Translation2/Admin/Container/db.php
... ... @@ -0,0 +1,721 @@
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * Contains the Translation2_Admin_Container_db class
  6 + *
  7 + * This storage driver can use all databases which are supported
  8 + * by the PEAR::DB abstraction layer to fetch data.
  9 + *
  10 + * PHP versions 4 and 5
  11 + *
  12 + * LICENSE: Redistribution and use in source and binary forms, with or without
  13 + * modification, are permitted provided that the following conditions are met:
  14 + * 1. Redistributions of source code must retain the above copyright
  15 + * notice, this list of conditions and the following disclaimer.
  16 + * 2. Redistributions in binary form must reproduce the above copyright
  17 + * notice, this list of conditions and the following disclaimer in the
  18 + * documentation and/or other materials provided with the distribution.
  19 + * 3. The name of the author may not be used to endorse or promote products
  20 + * derived from this software without specific prior written permission.
  21 + *
  22 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
  23 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  24 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25 + * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
  26 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32 + *
  33 + * @category Internationalization
  34 + * @package Translation2
  35 + * @author Lorenzo Alberton <l.alberton@quipo.it>
  36 + * @author Ian Eure <ieure@php.net>
  37 + * @copyright 2004-2007 Lorenzo Alberton, Ian Eure
  38 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  39 + * @version CVS: $Id$
  40 + * @link http://pear.php.net/package/Translation2
  41 + */
  42 +
  43 +/**
  44 + * require Translation2_Container_db class
  45 + */
  46 +require_once 'Translation2/Container/db.php';
  47 +
  48 +/**
  49 + * Storage driver for storing/fetching data to/from a database
  50 + *
  51 + * This storage driver can use all databases which are supported
  52 + * by the PEAR::DB abstraction layer to store and fetch data.
  53 + *
  54 + * @category Internationalization
  55 + * @package Translation2
  56 + * @author Lorenzo Alberton <l.alberton@quipo.it>
  57 + * @author Ian Eure <ieure@php.net>
  58 + * @copyright 2004-2007 Lorenzo Alberton, Ian Eure
  59 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  60 + * @link http://pear.php.net/package/Translation2
  61 + */
  62 +class Translation2_Admin_Container_db extends Translation2_Container_db
  63 +{
  64 +
  65 + // {{{ class vars
  66 +
  67 + // }}}
  68 + // {{{ addLang()
  69 +
  70 + /**
  71 + * Creates a new table to store the strings in this language.
  72 + * If the table is shared with other langs, it is ALTERed to
  73 + * hold strings in this lang too.
  74 + *
  75 + * @param array $langData language data
  76 + * @param array $options options
  77 + *
  78 + * @return true|PEAR_Error
  79 + */
  80 + function addLang($langData, $options = array())
  81 + {
  82 + $tables = $this->db->getListOf('tables');
  83 + if (PEAR::isError($tables)) {
  84 + return $tables;
  85 + }
  86 +
  87 + $lang_col = $this->_getLangCol($langData['lang_id']);
  88 +
  89 + if (in_array($langData['table_name'], $tables)) {
  90 + // table exists
  91 + $query = sprintf('ALTER TABLE %s ADD %s%s TEXT',
  92 + $this->db->quoteIdentifier($langData['table_name']),
  93 + $this->db->phptype == 'mssql' ? '' : 'COLUMN ',
  94 + $this->db->quoteIdentifier($lang_col)
  95 + );
  96 + ++$this->_queries;
  97 + return $this->db->query($query);
  98 + }
  99 +
  100 + //table does not exist
  101 + $queries = array();
  102 + $queries[] = sprintf('CREATE TABLE %s ( '
  103 + .'%s VARCHAR(%d) default NULL, '
  104 + .'%s TEXT NOT NULL, '
  105 + .'%s TEXT )',
  106 + $this->db->quoteIdentifier($langData['table_name']),
  107 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  108 + (int)$this->options['string_page_id_col_length'],
  109 + $this->db->quoteIdentifier($this->options['string_id_col']),
  110 + $this->db->quoteIdentifier($lang_col)
  111 + );
  112 + $mysqlClause = ($this->db->phptype == 'mysql') ? '(255)' : '';
  113 +
  114 + $index_name = sprintf('%s_%s_%s_index',
  115 + $langData['table_name'],
  116 + $this->options['string_page_id_col'],
  117 + $this->options['string_id_col']
  118 + );
  119 + $queries[] = sprintf('CREATE UNIQUE INDEX %s ON %s (%s, %s%s)',
  120 + $this->db->quoteIdentifier($index_name),
  121 + $this->db->quoteIdentifier($langData['table_name']),
  122 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  123 + $this->db->quoteIdentifier($this->options['string_id_col']),
  124 + $mysqlClause
  125 + );
  126 +
  127 + $index_name = sprintf('%s_%s_index',
  128 + $langData['table_name'],
  129 + $this->options['string_page_id_col']
  130 + );
  131 + $queries[] = sprintf('CREATE INDEX %s ON %s (%s)',
  132 + $this->db->quoteIdentifier($index_name),
  133 + $this->db->quoteIdentifier($langData['table_name']),
  134 + $this->db->quoteIdentifier($this->options['string_page_id_col'])
  135 + );
  136 +
  137 + $index_name = sprintf('%s_%s_index',
  138 + $langData['table_name'],
  139 + $this->options['string_id_col']
  140 + );
  141 + $queries[] = sprintf('CREATE INDEX %s ON %s (%s%s)',
  142 + $this->db->quoteIdentifier($index_name),
  143 + $this->db->quoteIdentifier($langData['table_name']),
  144 + $this->db->quoteIdentifier($this->options['string_id_col']),
  145 + $mysqlClause
  146 + );
  147 +
  148 + foreach ($queries as $query) {
  149 + ++$this->_queries;
  150 + $res = $this->db->query($query);
  151 + if (PEAR::isError($res)) {
  152 + return $res;
  153 + }
  154 + }
  155 + return true;
  156 + }
  157 +
  158 + // }}}
  159 + // {{{ addLangToList()
  160 +
  161 + /**
  162 + * Creates a new entry in the langsAvail table.
  163 + * If the table doesn't exist yet, it is created.
  164 + *
  165 + * @param array $langData array('lang_id' => 'en',
  166 + * 'table_name' => 'i18n',
  167 + * 'name' => 'english',
  168 + * 'meta' => 'some meta info',
  169 + * 'error_text' => 'not available',
  170 + * 'encoding' => 'iso-8859-1');
  171 + *
  172 + * @return true|PEAR_Error
  173 + */
  174 + function addLangToList($langData)
  175 + {
  176 + $tables = $this->db->getListOf('tables');
  177 + if (PEAR::isError($tables)) {
  178 + return $tables;
  179 + }
  180 +
  181 + if (!in_array($this->options['langs_avail_table'], $tables)) {
  182 + $queries = array();
  183 + $queries[] = sprintf('CREATE TABLE %s ('
  184 + .'%s VARCHAR(16), '
  185 + .'%s VARCHAR(200), '
  186 + .'%s TEXT, '
  187 + .'%s VARCHAR(250), '
  188 + .'%s VARCHAR(16) )',
  189 + $this->db->quoteIdentifier($this->options['langs_avail_table']),
  190 + $this->db->quoteIdentifier($this->options['lang_id_col']),
  191 + $this->db->quoteIdentifier($this->options['lang_name_col']),
  192 + $this->db->quoteIdentifier($this->options['lang_meta_col']),
  193 + $this->db->quoteIdentifier($this->options['lang_errmsg_col']),
  194 + $this->db->quoteIdentifier($this->options['lang_encoding_col'])
  195 + );
  196 + $queries[] = sprintf('CREATE UNIQUE INDEX %s_%s_index ON %s (%s)',
  197 + $this->options['langs_avail_table'],
  198 + $this->options['lang_id_col'],
  199 + $this->db->quoteIdentifier($this->options['langs_avail_table']),
  200 + $this->db->quoteIdentifier($this->options['lang_id_col'])
  201 + );
  202 +
  203 + foreach ($queries as $query) {
  204 + ++$this->_queries;
  205 + $res = $this->db->query($query);
  206 + if (PEAR::isError($res)) {
  207 + return $res;
  208 + }
  209 + }
  210 + }
  211 +
  212 + $query = sprintf('INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (%s, %s, %s, %s, %s)',
  213 + $this->db->quoteIdentifier($this->options['langs_avail_table']),
  214 + $this->db->quoteIdentifier($this->options['lang_id_col']),
  215 + $this->db->quoteIdentifier($this->options['lang_name_col']),
  216 + $this->db->quoteIdentifier($this->options['lang_meta_col']),
  217 + $this->db->quoteIdentifier($this->options['lang_errmsg_col']),
  218 + $this->db->quoteIdentifier($this->options['lang_encoding_col']),
  219 + $this->db->quote($langData['lang_id']),
  220 + $this->db->quote($langData['name']),
  221 + $this->db->quote($langData['meta']),
  222 + $this->db->quote($langData['error_text']),
  223 + $this->db->quote($langData['encoding'])
  224 + );
  225 +
  226 + ++$this->_queries;
  227 + $success = $this->db->query($query);
  228 + $this->options['strings_tables'][$langData['lang_id']] = $langData['table_name'];
  229 + return $success;
  230 + }
  231 +
  232 + // }}}
  233 + // {{{ removeLang()
  234 +
  235 + /**
  236 + * Remove the lang from the langsAvail table and drop the strings table.
  237 + * If the strings table holds other langs and $force==false, then
  238 + * only the lang column is dropped. If $force==true the whole
  239 + * table is dropped without any check
  240 + *
  241 + * @param string $langID language ID
  242 + * @param boolean $force if true, the whole table is dropped without checks
  243 + *
  244 + * @return true|PEAR_Error
  245 + */
  246 + function removeLang($langID, $force)
  247 + {
  248 + //remove from langsAvail
  249 + $query = sprintf('DELETE FROM %s WHERE %s = %s',
  250 + $this->db->quoteIdentifier($this->options['langs_avail_table']),
  251 + $this->db->quoteIdentifier($this->options['lang_id_col']),
  252 + $this->db->quote($langID)
  253 + );
  254 + ++$this->_queries;
  255 + $res = $this->db->query($query);
  256 + if (PEAR::isError($res)) {
  257 + return $res;
  258 + }
  259 +
  260 + $lang_table = $this->_getLangTable($langID);
  261 + if ($force) {
  262 + //remove the whole table
  263 + ++$this->_queries;
  264 + return $this->db->query('DROP TABLE ' . $this->db->quoteIdentifier($lang_table));
  265 + }
  266 +
  267 + //drop only the column for this lang
  268 + $query = sprintf('ALTER TABLE %s DROP COLUMN %s',
  269 + $lang_table,
  270 + $this->_getLangCol($langID)
  271 + );
  272 + ++$this->_queries;
  273 + return $this->db->query($query);
  274 + }
  275 +
  276 + // }}}
  277 + // {{{ updateLang()
  278 +
  279 + /**
  280 + * Update the lang info in the langsAvail table
  281 + *
  282 + * @param array $langData language data
  283 + *
  284 + * @return true|PEAR_Error
  285 + */
  286 + function updateLang($langData)
  287 + {
  288 + $allFields = array(
  289 + //'lang_id' => 'lang_id_col',
  290 + 'name' => 'lang_name_col',
  291 + 'meta' => 'lang_meta_col',
  292 + 'error_text' => 'lang_errmsg_col',
  293 + 'encoding' => 'lang_encoding_col',
  294 + );
  295 + $updateFields = array_keys($langData);
  296 + $langSet = array();
  297 + foreach ($allFields as $field => $col) {
  298 + if (in_array($field, $updateFields)) {
  299 + $langSet[] = $this->db->quoteIdentifier($this->options[$col]) . ' = ' .
  300 + $this->db->quote($langData[$field]);
  301 + }
  302 + }
  303 + $query = sprintf('UPDATE %s SET %s WHERE %s=%s',
  304 + $this->db->quoteIdentifier($this->options['langs_avail_table']),
  305 + implode(', ', $langSet),
  306 + $this->db->quoteIdentifier($this->options['lang_id_col']),
  307 + $this->db->quote($langData['lang_id'])
  308 + );
  309 +
  310 + ++$this->_queries;
  311 + $success = $this->db->query($query);
  312 + $this->fetchLangs(); //update memory cache
  313 + return $success;
  314 + }
  315 +
  316 + // }}}
  317 + // {{{ add()
  318 +
  319 + /**
  320 + * Add a new entry in the strings table.
  321 + *
  322 + * @param string $stringID string ID
  323 + * @param string $pageID page/group ID
  324 + * @param array $stringArray Associative array with string translations.
  325 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  326 + *
  327 + * @return true|PEAR_Error
  328 + */
  329 + function add($stringID, $pageID, $stringArray)
  330 + {
  331 + $langs = array_intersect(
  332 + array_keys($stringArray),
  333 + $this->getLangs('ids')
  334 + );
  335 +
  336 + if (!count($langs)) {
  337 + //return error: no valid lang provided
  338 + return true;
  339 + }
  340 +
  341 + // Langs may be in different tables - we need to split up queries along
  342 + // table lines, so we can keep DB traffic to a minimum.
  343 +
  344 + $unquoted_stringID = $stringID;
  345 + $unquoted_pageID = $pageID;
  346 + $stringID = $this->db->quote($stringID);
  347 + $pageID = is_null($pageID) ? 'NULL' : $this->db->quote($pageID);
  348 + // Loop over the tables we need to insert into.
  349 + foreach ($this->_tableLangs($langs) as $table => $tableLangs) {
  350 + $exists = $this->_recordExists($unquoted_stringID, $unquoted_pageID, $table);
  351 + if (PEAR::isError($exists)) {
  352 + return $exists;
  353 + }
  354 + $func = $exists ? '_getUpdateQuery' : '_getInsertQuery';
  355 + $query = $this->$func($table, $tableLangs, $stringID, $pageID, $stringArray);
  356 +
  357 + ++$this->_queries;
  358 + $res = $this->db->query($query);
  359 + if (PEAR::isError($res)) {
  360 + return $res;
  361 + }
  362 + }
  363 +
  364 + return true;
  365 + }
  366 +
  367 + // }}}
  368 + // {{{ update()
  369 +
  370 + /**
  371 + * Update an existing entry in the strings table.
  372 + *
  373 + * @param string $stringID string ID
  374 + * @param string $pageID page/group ID
  375 + * @param array $stringArray Associative array with string translations.
  376 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  377 + *
  378 + * @return true|PEAR_Error
  379 + */
  380 + function update($stringID, $pageID, $stringArray)
  381 + {
  382 + return $this->add($stringID, $pageID, $stringArray);
  383 + }
  384 +
  385 + // }}}
  386 + // {{{ _getInsertQuery()
  387 +
  388 + /**
  389 + * Build a SQL query to INSERT a record
  390 + *
  391 + * @param string $table table name
  392 + * @param array &$tableLangs tables containing the languages
  393 + * @param string $stringID string ID
  394 + * @param string $pageID page/group ID
  395 + * @param array &$stringArray array of strings
  396 + *
  397 + * @return string INSERT query
  398 + * @access private
  399 + */
  400 + function _getInsertQuery($table, &$tableLangs, $stringID, $pageID, &$stringArray)
  401 + {
  402 + $tableCols = $this->_getLangCols($tableLangs);
  403 + $langData = array();
  404 + foreach ($tableLangs as $lang) {
  405 + $langData[$lang] = $this->db->quote($stringArray[$lang]);
  406 + }
  407 + foreach (array_keys($tableCols) as $k) {
  408 + $tableCols[$k] = $this->db->quoteIdentifier($tableCols[$k]);
  409 + }
  410 +
  411 + return sprintf('INSERT INTO %s (%s, %s, %s) VALUES (%s, %s, %s)',
  412 + $this->db->quoteIdentifier($table),
  413 + $this->db->quoteIdentifier($this->options['string_id_col']),
  414 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  415 + implode(', ', $tableCols),
  416 + $stringID,
  417 + $pageID,
  418 + implode(', ', $langData)
  419 + );
  420 + }
  421 +
  422 + // }}}
  423 + // {{{ _getUpdateQuery()
  424 +
  425 + /**
  426 + * Build a SQL query to UPDATE a record
  427 + *
  428 + * @param string $table table name
  429 + * @param array &$tableLangs tables containing the languages
  430 + * @param string $stringID string ID
  431 + * @param string $pageID page/group ID
  432 + * @param array &$stringArray array of strings
  433 + *
  434 + * @return string UPDATE query
  435 + * @access private
  436 + */
  437 + function _getUpdateQuery($table, &$tableLangs, $stringID, $pageID, &$stringArray)
  438 + {
  439 + $tableCols = $this->_getLangCols($tableLangs);
  440 + $langSet = array();
  441 + foreach ($tableLangs as $lang) {
  442 + $langSet[] = $this->db->quoteIdentifier($tableCols[$lang]) . ' = ' .
  443 + $this->db->quote($stringArray[$lang]);
  444 + }
  445 +
  446 + return sprintf('UPDATE %s SET %s WHERE %s = %s AND %s = %s',
  447 + $this->db->quoteIdentifier($table),
  448 + implode(', ', $langSet),
  449 + $this->db->quoteIdentifier($this->options['string_id_col']),
  450 + $stringID,
  451 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  452 + $pageID
  453 + );
  454 + }
  455 +
  456 + // }}}
  457 + // {{{ remove()
  458 +
  459 + /**
  460 + * Remove an entry from the strings table.
  461 + *
  462 + * @param string $stringID string ID
  463 + * @param string $pageID page/group ID
  464 + *
  465 + * @return true|PEAR_Error
  466 + */
  467 + function remove($stringID, $pageID)
  468 + {
  469 + $tables = array_unique($this->_getLangTables());
  470 +
  471 + $stringID = $this->db->quote($stringID);
  472 + // get the tables and skip the non existent ones
  473 + $dbTables = $this->db->getListOf('tables');
  474 + foreach ($tables as $table) {
  475 + if (!in_array($table, $dbTables)) {
  476 + continue;
  477 + }
  478 + $query = sprintf('DELETE FROM %s WHERE %s = %s AND %s',
  479 + $this->db->quoteIdentifier($table),
  480 + $this->db->quoteIdentifier($this->options['string_id_col']),
  481 + $stringID,
  482 + $this->db->quoteIdentifier($this->options['string_page_id_col'])
  483 + );
  484 + if (is_null($pageID)) {
  485 + $query .= ' IS NULL';
  486 + } else {
  487 + $query .= ' = ' . $this->db->quote($pageID);
  488 + }
  489 +
  490 + ++$this->_queries;
  491 + $res = $this->db->query($query);
  492 + if (PEAR::isError($res)) {
  493 + return $res;
  494 + }
  495 + }
  496 +
  497 + return true;
  498 + }
  499 +
  500 + // }}}
  501 + // {{{ removePage
  502 +
  503 + /**
  504 + * Remove all the strings in the given page/group
  505 + *
  506 + * @param string $pageID page/group ID
  507 + *
  508 + * @return mixed true on success, PEAR_Error on failure
  509 + */
  510 + function removePage($pageID = null)
  511 + {
  512 + $tables = array_unique($this->_getLangTables());
  513 +
  514 + // get the tables and skip the non existent ones
  515 + $dbTables = $this->db->getListOf('tables');
  516 + foreach ($tables as $table) {
  517 + if (!in_array($table, $dbTables)) {
  518 + continue;
  519 + }
  520 + $query = sprintf('DELETE FROM %s WHERE %s',
  521 + $this->db->quoteIdentifier($table, true),
  522 + $this->db->quoteIdentifier($this->options['string_page_id_col'])
  523 + );
  524 + if (is_null($pageID)) {
  525 + $query .= ' IS NULL';
  526 + } else {
  527 + $query .= ' = ' . $this->db->quote($pageID, 'text');
  528 + }
  529 +
  530 + ++$this->_queries;
  531 + $res = $this->db->query($query);
  532 + if (PEAR::isError($res)) {
  533 + return $res;
  534 + }
  535 + }
  536 +
  537 + return true;
  538 + }
  539 +
  540 + // }}}
  541 + // {{{ getPageNames()
  542 +
  543 + /**
  544 + * Get a list of all the pageIDs in any table.
  545 + *
  546 + * @return array
  547 + */
  548 + function getPageNames()
  549 + {
  550 + $pages = array();
  551 + foreach ($this->_getLangTables() as $table) {
  552 + $query = sprintf('SELECT DISTINCT %s FROM %s',
  553 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  554 + $this->db->quoteIdentifier($table)
  555 + );
  556 + ++$this->_queries;
  557 + $res = $this->db->getCol($query);
  558 + if (PEAR::isError($res)) {
  559 + return $res;
  560 + }
  561 + $pages = array_merge($pages, $res);
  562 + }
  563 + return array_unique($pages);
  564 + }
  565 +
  566 + // }}}
  567 + // {{{ _tableLangs()
  568 +
  569 + /**
  570 + * Get table -> language mapping
  571 + *
  572 + * The key of the array is the table that a language is stored in;
  573 + * the value is an /array/ of languages stored in that table.
  574 + *
  575 + * @param array $langs Languages to get mapping for
  576 + *
  577 + * @return array Table -> language mapping
  578 + * @access private
  579 + * @see Translation2_Container_DB::_getLangTable()
  580 + */
  581 + function &_tableLangs($langs)
  582 + {
  583 + $tables = array();
  584 + foreach ($langs as $lang) {
  585 + $table = $this->_getLangTable($lang);
  586 + $tables[$table][] = $lang;
  587 + }
  588 + return $tables;
  589 + }
  590 +
  591 + // }}}
  592 + // {{{ _getLangTables()
  593 +
  594 + /**
  595 + * Get tables for languages
  596 + *
  597 + * This is like _getLangTable(), but it returns an array of the tables for
  598 + * multiple languages.
  599 + *
  600 + * @param array $langs Languages to get tables for
  601 + *
  602 + * @return array
  603 + * @access private
  604 + */
  605 + function &_getLangTables($langs = null)
  606 + {
  607 + $tables = array();
  608 + $langs = !is_array($langs) ? $this->getLangs('ids') : $langs;
  609 + foreach ($langs as $lang) {
  610 + $tables[] = $this->_getLangTable($lang);
  611 + }
  612 + $tables = array_unique($tables);
  613 + return $tables;
  614 + }
  615 +
  616 + // }}}
  617 + // {{{ _getLangCols()
  618 +
  619 + /**
  620 + * Get table columns strings are stored in
  621 + *
  622 + * This is like _getLangCol(), except it returns an array which contains
  623 + * the mapping for multiple languages.
  624 + *
  625 + * @param array $langs Languages to get mapping for
  626 + *
  627 + * @return array Language -> column mapping
  628 + * @access private
  629 + * @see Translation2_Container_DB::_getLangCol()
  630 + */
  631 + function &_getLangCols($langs)
  632 + {
  633 + $cols = array();
  634 + foreach ($langs as $lang) {
  635 + $cols[$lang] = $this->_getLangCol($lang);
  636 + }
  637 + return $cols;
  638 + }
  639 +
  640 + // }}}
  641 + // {{{ _recordExists()
  642 +
  643 + /**
  644 + * Check if there's already a record in the table with the
  645 + * given (pageID, stringID) pair.
  646 + *
  647 + * @param string $stringID string ID
  648 + * @param string $pageID page/group ID
  649 + * @param string $table table name
  650 + *
  651 + * @return boolean
  652 + * @access private
  653 + */
  654 + function _recordExists($stringID, $pageID, $table)
  655 + {
  656 + $stringID = $this->db->quote($stringID, 'text');
  657 + $pageID = is_null($pageID) ? ' IS NULL' : ' = ' . $this->db->quote($pageID);
  658 + $query = sprintf('SELECT COUNT(*) FROM %s WHERE %s=%s AND %s%s',
  659 + $this->db->quoteIdentifier($table),
  660 + $this->db->quoteIdentifier($this->options['string_id_col']),
  661 + $stringID,
  662 + $this->db->quoteIdentifier($this->options['string_page_id_col']),
  663 + $pageID
  664 + );
  665 + ++$this->_queries;
  666 + $res = $this->db->getOne($query);
  667 + if (PEAR::isError($res)) {
  668 + return $res;
  669 + }
  670 + return ($res > 0);
  671 + }
  672 +
  673 + // }}}
  674 + // {{{ _filterStringsByTable()
  675 +
  676 + /**
  677 + * Get only the strings for the langs in the given table
  678 + *
  679 + * @param array $stringArray Associative array with string translations.
  680 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  681 + * @param string $table table name
  682 + *
  683 + * @return array
  684 + * @access private
  685 + */
  686 + function &_filterStringsByTable($stringArray, $table)
  687 + {
  688 + $strings = array();
  689 + foreach ($stringArray as $lang => $string) {
  690 + if ($table == $this->_getLangTable($lang)) {
  691 + $strings[$lang] = $string;
  692 + }
  693 + }
  694 + return $strings;
  695 + }
  696 +
  697 + // }}}
  698 + // {{{ _getLangsInTable()
  699 +
  700 + /**
  701 + * Get the languages sharing the given table
  702 + *
  703 + * @param string $table table name
  704 + *
  705 + * @return array
  706 + */
  707 + function &_getLangsInTable($table)
  708 + {
  709 + $this->fetchLangs(); // force cache refresh
  710 + $langsInTable = array();
  711 + foreach (array_keys($this->langs) as $lang) {
  712 + if ($table == $this->_getLangTable($lang)) {
  713 + $langsInTable[] = $lang;
  714 + }
  715 + }
  716 + return $langsInTable;
  717 + }
  718 +
  719 + // }}}
  720 +}
  721 +?>
640 Translation2/Admin/Container/gettext.php
... ... @@ -0,0 +1,640 @@
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * Contains the Translation2_Admin_Container_gettext 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 Michael Wallner <mike@php.net>
  34 + * @copyright 2004-2007 Lorenzo Alberton, Michael Wallner
  35 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  36 + * @version CVS: $Id$
  37 + * @link http://pear.php.net/package/Translation2
  38 + */
  39 +
  40 +/**
  41 + * require Translation2_Container_gettext class
  42 + */
  43 +require_once 'Translation2/Container/gettext.php';
  44 +
  45 +/**
  46 + * Storage driver for storing/fetching data to/from a gettext file
  47 + *
  48 + * This storage driver requires the gettext extension
  49 + *
  50 + * @category Internationalization
  51 + * @package Translation2
  52 + * @author Lorenzo Alberton <l.alberton@quipo.it>
  53 + * @author Michael Wallner <mike@php.net>
  54 + * @copyright 2004-2007 Lorenzo Alberton, Michael Wallner
  55 + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  56 + * @version CVS: $Id$
  57 + * @link http://pear.php.net/package/Translation2
  58 + */
  59 +class Translation2_Admin_Container_gettext extends Translation2_Container_gettext
  60 +{
  61 + // {{{ class vars
  62 +
  63 + var $_bulk = false;
  64 + var $_queue = array();
  65 + var $_fields = array('name', 'meta', 'error_text', 'encoding');
  66 +
  67 + // }}}
  68 + // {{{ addLang()
  69 +
  70 + /**
  71 + * Creates a new entry in the langs_avail .ini file.
  72 + *
  73 + * @param array $langData language data
  74 + * @param string $path path to gettext data dir
  75 + *
  76 + * @return mixed Returns true on success or PEAR_Error on failure.
  77 + */
  78 + function addLang($langData, $path = null)
  79 + {
  80 + if (!isset($path) || !is_string($path)) {
  81 + $path = $this->_domains[$this->options['default_domain']];
  82 + }
  83 +
  84 + $path .= '/'. $langData['lang_id'] . '/LC_MESSAGES';
  85 +
  86 + if (!is_dir($path)) {
  87 + include_once 'System.php';
  88 + if (!System::mkdir(array('-p', $path))) {
  89 + return $this->raiseError(sprintf(
  90 + 'Cannot create new language in path "%s"', $path
  91 + ),
  92 + TRANSLATION2_ERROR_CANNOT_CREATE_DIR
  93 + );
  94 + }
  95 + }
  96 +
  97 + return true;
  98 + }
  99 +
  100 + // }}}
  101 + // {{{ addLangToList()
  102 +
  103 + /**
  104 + * Creates a new entry in the langsAvail .ini file.
  105 + * If the file doesn't exist yet, it is created.
  106 + *
  107 + * @param array $langData array('lang_id' => 'en',
  108 + * 'name' => 'english',
  109 + * 'meta' => 'some meta info',
  110 + * 'error_text' => 'not available'
  111 + * 'encoding' => 'iso-8859-1',
  112 + * );
  113 + *
  114 + * @return true|PEAR_Error on failure
  115 + */
  116 + function addLangToList($langData)
  117 + {
  118 + if (PEAR::isError($changed = $this->_updateLangData($langData))) {
  119 + return $changed;
  120 + }
  121 + return $changed ? $this->_writeLangsAvailFile() : true;
  122 + }
  123 +
  124 + // }}}
  125 + // {{{ add()
  126 +
  127 + /**
  128 + * Add a new entry in the strings domain.
  129 + *
  130 + * @param string $stringID string ID
  131 + * @param string $pageID page/group ID
  132 + * @param array $strings Associative array with string translations.
  133 + * Sample format: array('en' => 'sample', 'it' => 'esempio')
  134 + *
  135 + * @return true|PEAR_Error on failure
  136 + */
  137 + function add($stringID, $pageID, $strings)
  138 + {
  139 + if (!isset($pageID)) {
  140 + $pageID = $this->options['default_domain'];
  141 + }
  142 +
  143 + $langs = array_intersect(array_keys($strings), $this->getLangs('ids'));
  144 +
  145 + if (!count($langs)) {
  146 + return true; // really?
  147 + }
  148 +
  149 + if ($this->_bulk) {
  150 + foreach ($strings as $lang => $string) {
  151 + if (in_array($lang, $langs)) {
  152 + $this->_queue['add'][$pageID][$lang][$stringID] = $string;
  153 + }
  154 + }
  155 + return true;
  156 + } else {
  157 + $add = array();
  158 + foreach ($strings as $lang => $string) {
  159 + if (in_array($lang, $langs)) {
  160 + $add[$pageID][$lang][$stringID] = $string;
  161 + }