Source for file mdb2.php
Documentation is available at mdb2.php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
* Contains the Translation2_Admin_Container_mdb2 class
* LICENSE: Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @category Internationalization
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @copyright 2004-2007 Lorenzo Alberton
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @version CVS: $Id: mdb2.php,v 1.41 2008/05/03 09:17:59 quipo Exp $
* @link http://pear.php.net/package/Translation2
* require Translation2_Container_mdb2 class
require_once 'Translation2/Container/mdb2.php';
* Storage driver for storing/fetching data to/from a database
* This storage driver can use all databases which are supported
* by the PEAR::MDB2 abstraction layer to store and fetch data.
* @category Internationalization
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @copyright 2004-2007 Lorenzo Alberton
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @link http://pear.php.net/package/Translation2
* Fetch the table names from the db
* @return array|PEAR_Error
function _fetchTableNames ()
$this->db->loadModule ('Manager');
return $this->db->manager ->listTables ();
* Creates a new table to store the strings in this language.
* If the table is shared with other langs, it is ALTERed to
* hold strings in this lang too.
* @param array $langData array('lang_id' => 'en',
* 'table_name' => 'i18n',
* 'meta' => 'some meta info',
* 'error_text' => 'not available');
* @param array $options array('charset' => 'utf8',
* 'collation' => 'utf8_general_ci');
* @return true|PEAR_Error
function addLang($langData, $options = array ())
$tables = $this->_fetchTableNames ();
if (PEAR ::isError ($tables)) {
$lang_col = $this->_getLangCol ($langData['lang_id']);
$charset = empty ($options['charset']) ? null : $options['charset'];
$collation = empty ($options['collation']) ? null : $options['collation'];
$this->db->loadModule ('Manager');
if (in_array($langData['table_name'], $tables)) {
'collation' => $collation,
return $this->db->manager ->alterTable ($langData['table_name'], $table_changes, false );
$table_definition = array (
$this->options['string_page_id_col'] => array (
'length' => $this->options['string_page_id_col_length'],
'collation' => $collation,
$this->options['string_id_col'] => array (
'collation' => $collation,
'collation' => $collation,
$res = $this->db->manager ->createTable ($langData['table_name'], $table_definition);
if (PEAR ::isError ($res)) {
$mysqlClause = ($this->db->phptype == 'mysql') ? '(255)' : '';
$constraint_name = $langData['table_name']
. '_'. $this->options['string_page_id_col']
. '_'. $this->options['string_id_col'];
$constraint_definition = array (
$this->options['string_page_id_col'] => array (),
$this->options['string_id_col']. $mysqlClause => array (),
$res = $this->db->manager ->createConstraint ($langData['table_name'], $constraint_name, $constraint_definition);
if (PEAR ::isError ($res)) {
$index_name = $langData['table_name'] . '_'. $this->options['string_page_id_col'];
$index_definition = array (
'fields' => array ($this->options['string_page_id_col'] => array ())
$res = $this->db->manager ->createIndex ($langData['table_name'], $index_name, $index_definition);
if (PEAR ::isError ($res)) {
$index_name = $langData['table_name'] . '_'. $this->options['string_id_col'];
$index_definition = array (
'fields' => array ($this->options['string_id_col'] => array ('length' => 255 ))
$res = $this->db->manager ->createIndex ($langData['table_name'], $index_name, $index_definition);
if (PEAR ::isError ($res)) {
* Creates a new entry in the langsAvail table.
* If the table doesn't exist yet, it is created.
* @param array $langData array('lang_id' => 'en',
* 'table_name' => 'i18n',
* 'meta' => 'some meta info',
* 'error_text' => 'not available',
* 'encoding' => 'iso-8859-1');
* @return true|PEAR_Error
$tables = $this->_fetchTableNames ();
if (PEAR ::isError ($tables)) {
$queries[] = sprintf('CREATE TABLE %s ('
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_name_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_meta_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_errmsg_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_encoding_col'], true )
$queries[] = sprintf('CREATE UNIQUE INDEX %s_%s_index ON %s (%s)',
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true ),
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true )
foreach ($queries as $query) {
$res = $this->db->exec ($query);
if (PEAR ::isError ($res)) {
$query = sprintf('INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (%s, %s, %s, %s, %s)',
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_name_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_meta_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_errmsg_col'], true ),
$this->db->quoteIdentifier ($this->options['lang_encoding_col'], true ),
$this->db->quote ($langData['lang_id']),
$this->db->quote ($langData['name']),
$this->db->quote ($langData['meta']),
$this->db->quote ($langData['error_text']),
$this->db->quote ($langData['encoding'])
$res = $this->db->exec ($query);
$this->options['strings_tables'][$langData['lang_id']] = $langData['table_name'];
if (PEAR ::isError ($res)) {
* Remove the lang from the langsAvail table and drop the strings table.
* If the strings table holds other langs and $force==false, then
* only the lang column is dropped. If $force==true the whole
* table is dropped without any check
* @param string $langID language ID
* @param boolean $force if true, the whole table is dropped without checks
* @return true|PEAR_Error
$query = sprintf('DELETE FROM %s WHERE %s = %s',
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true ),
$this->db->quote ($langID, 'text')
$res = $this->db->exec ($query);
if (PEAR ::isError ($res)) {
$this->db->loadModule ('Manager');
$lang_table = $this->_getLangTable ($langID);
return $this->db->manager ->dropTable ($lang_table);
//drop only the column for this lang
'remove' => array ($this->_getLangCol ($langID) => array ())
return $this->db->manager ->alterTable ($lang_table, $table_changes, false );
* Update the lang info in the langsAvail table
* @param array $langData language data
* @return true|PEAR_Error
//'lang_id' => 'lang_id_col',
'name' => 'lang_name_col',
'meta' => 'lang_meta_col',
'error_text' => 'lang_errmsg_col',
'encoding' => 'lang_encoding_col',
foreach ($allFields as $field => $col) {
$langSet[] = $this->db->quoteIdentifier ($this->options[$col], true ) . ' = ' .
$this->db->quote ($langData[$field]);
$query = sprintf('UPDATE %s SET %s WHERE %s=%s',
$this->db->quoteIdentifier ($this->options['langs_avail_table'], true ),
$this->db->quoteIdentifier ($this->options['lang_id_col'], true ),
$this->db->quote ($langData['lang_id'])
$res = $this->db->exec ($query);
if (PEAR ::isError ($res)) {
* Add a new entry in the strings table.
* @param string $stringID string ID
* @param string $pageID page/group ID
* @param array $stringArray Associative array with string translations.
* Sample format: array('en' => 'sample', 'it' => 'esempio')
* @return true|PEAR_Error
function add($stringID, $pageID, $stringArray)
//return error: no valid lang provided
// Langs may be in different tables - we need to split up queries along
// table lines, so we can keep DB traffic to a minimum.
$unquoted_stringID = $stringID;
$unquoted_pageID = $pageID;
$stringID = $this->db->quote ($stringID, 'text');
$pageID = is_null($pageID) ? 'NULL' : $this->db->quote ($pageID, 'text');
// Loop over the tables we need to insert into.
foreach ($this->_tableLangs ($langs) as $table => $tableLangs) {
$exists = $this->_recordExists ($unquoted_stringID, $unquoted_pageID, $table);
if (PEAR ::isError ($exists)) {
$func = $exists ? '_getUpdateQuery' : '_getInsertQuery';
$query = $this->$func($table, $tableLangs, $stringID, $pageID, $stringArray);
$res = $this->db->exec ($query);
if (PEAR ::isError ($res)) {
* Update an existing entry in the strings table.
* @param string $stringID string ID
* @param string $pageID page/group ID
* @param array $stringArray Associative array with string translations.
* Sample format: array('en' => 'sample', 'it' => 'esempio')
* @return true|PEAR_Error
function update($stringID, $pageID, $stringArray)
return $this->add($stringID, $pageID, $stringArray);
* Build a SQL query to INSERT a record
* @param string $table table name
* @param array &$tableLangs tables containing the languages
* @param string $stringID string ID
* @param string $pageID page/group ID
* @param array &$stringArray array of strings
* @return string INSERT query
function _getInsertQuery ($table, &$tableLangs, $stringID, $pageID, &$stringArray)
$tableCols = $this->_getLangCols ($tableLangs);
foreach ($tableLangs as $lang) {
$langData[$lang] = $this->db->quote ($stringArray[$lang], 'text');
$tableCols[$k] = $this->db->quoteIdentifier ($tableCols[$k], true );
return sprintf('INSERT INTO %s (%s, %s, %s) VALUES (%s, %s, %s)',
$this->db->quoteIdentifier ($table, true ),
$this->db->quoteIdentifier ($this->options['string_id_col'], true ),
$this->db->quoteIdentifier ($this->options['string_page_id_col'], true ),
* Build a SQL query to UPDATE a record
* @param string $table table name
* @param array &$tableLangs tables containing the languages
* @param string $stringID string ID
* @param string $pageID page/group ID
* @param array &$stringArray array of strings
* @return string UPDATE query
function _getUpdateQuery ($table, &$tableLangs, $stringID, $pageID, &$stringArray)
$tableCols = $this->_getLangCols ($tableLangs);
foreach ($tableLangs as $lang) {
$langSet[] = $this->db->quoteIdentifier ($tableCols[$lang], true ) . ' = ' .
$this->db->quote ($stringArray[$lang], 'text');
return sprintf('UPDATE %s SET %s WHERE %s = %s AND %s = %s',
$this->db->quoteIdentifier ($table, true ),
$this->db->quoteIdentifier ($this->options['string_id_col'], true ),
$this->db->quoteIdentifier ($this->options['string_page_id_col'], true ),
* Remove an entry from the strings table.
* @param string $stringID string ID
* @param string $pageID page/group ID
* @return mixed true on success, PEAR_Error on failure
function remove($stringID, $pageID)
$stringID = $this->db->quote ($stringID, 'text');
// get the tables and skip the non existent ones
$dbTables = $this->_fetchTableNames ();
foreach ($tables as $table) {
$query = sprintf('DELETE FROM %s WHERE %s = %s AND %s',
$this->db->quoteIdentifier ($table, true ),
$this->db->quoteIdentifier ($this->options['string_id_col'], true ),
$this->db->quoteIdentifier ($this->options['string_page_id_col'], true )
$query .= ' = ' . $this->db->quote ($pageID, 'text');
$res = $this->db->exec ($query);
if (PEAR ::isError ($res)) {
* Remove all the strings in the given page/group
* @param string $pageID page/group ID
* @return mixed true on success, PEAR_Error on failu
|