<?php
/**
* Project: CWF: Cricava Web Framework
* File: XmlDataSource.class.php
*
* @link http://www.cricava.com/
* @copyright 2005-2009 Cricava Technologies, Inc.
* @author Mariano Iglesias <hide@address.com>
* @package com.cricava.cwf
* @version 1.0
*/
/**#@+
* Includes
*/
require_once(dirname(__FILE__) . '/DataSource.class.php');
require_once(dirname(__FILE__) . '/Dommer.class.php');
/**#@-*/
/**
* This class implements a file based data source.
*
* @author Mariano Iglesias
* @package com.cricava.cwf
* @subpackage i18n
* @since 1.0
*/
class XmlDataSource extends DataSource
{
/**
* The settings, along with languages & locales
*
* @access private
* @since 1.0
* @var array
*/
var $settings;
/**
* Creates a new instance of XmlDataSource.
*
* @param string Path to the XML configuration file
*
* @access public
* @since 1.0
*/
function & XmlDataSource($configurationFile)
{
$this->databaseConnection =& $databaseConnection;
$this->settings =& $this->parseSettings($configurationFile);
}
/**
* Function that handles the fetching of elements.
* <ul>
* <li>If no element specified, it will load all elements for a section.</li>
* <li>If no section specified, it will load all sections for the current container.</li>
* </ul>
*
* @param string The language to use
* @param string The locale to use (can be null)
* @param string The container to use
* @param string The section from where to get elements
* @param string The element to obtain
*
* @return array An indexed array by container, section, and elements
*
* @access public
* @since 1.0
*/
function & fetch($language, $locale, $container, $section = null, $element = null)
{
if (!isset($this->settings) || !isset($this->settings['path']) || !isset($this->settings['extension']))
{
return $elements;
}
$fileNames = array();
if ($dirHandle = opendir($this->settings['path']))
{
// Get all file paths that are language files, and leave only those for current container
while (($currentFileName = readdir($dirHandle)) !== false)
{
$currentFile = $this->settings['path'] . '/' . $currentFileName;
if (strlen($currentFileName) > strlen($this->settings['extension']))
{
$currentExtension = substr($currentFile, strlen($currentFile) - strlen($this->settings['extension']));
if (strcasecmp($currentExtension, $this->settings['extension']) == 0)
{
$currentFileName = basename($currentFile, '.' . $this->settings['extension']);
$currentFileName = substr($currentFileName, 0, strrpos($currentFileName, '.'));
if (strcasecmp($currentFileName, $container) == 0)
{
$fileNames[] = $currentFile;
}
}
}
}
closedir($dirHandle);
}
if (count($fileNames) > 0)
{
$currentLanguageFile = $this->settings['path'] . '/' . $container;
$currentLanguageFile .= '.' . $language;
if (isset($locale))
{
$currentLanguageFile .= '_' . $locale;
}
$currentLanguageFile .= '.' . $this->settings['extension'];
// Look if there's a language file that matches localization
if (!in_array($currentLanguageFile, $fileNames))
{
// There's not, a language file just for current language
$currentLanguageFile = $this->settings['path'] . '/' . $container . '.' . $language . '.' . $this->settings['extension'];
if (!in_array($currentLanguageFile, $fileNames))
{
// There's not, look for first language file that matches current language
$found = false;
for ($i=0; $found == false && $i < count($fileNames); $i++)
{
$currentFileName = $fileNames[$i];
$currentLanguageFile = baseName($currentFileName, '.' . $this->settings['extension']);
if (strpos($currentLanguageFile, $language) !== false && strpos($currentLanguageFile, $language) == 0)
{
$found = true;
$currentLanguageFile = $currentFileName;
}
}
if ($found == false)
{
$currentLanguageFile = null;
}
}
}
}
if (isset($currentLanguageFile))
{
$result =& $this->parse($currentLanguageFile);
$elements[$container] = $result;
}
return $elements;
}
/**
* Obtain the list of languages and their locales.
*
* @param string The language to use when obtaining language & locale names
* @param boolean true if you want to obtain only active languages & locales, false otherwise
*
* @return array The list of languages
*
* @access public
* @since 1.0
*/
function & fetchLanguages($language, $onlyActive = true)
{
if (!isset($this->settings) || !isset($this->settings['languages']) || count($this->settings['languages']) == 0)
{
return $languages;
}
$languages = $this->settings['languages'];
if (isset($languages) && is_array($languages))
{
foreach ($languages as $code=>$currentLanguage)
{
$languages[$code]['name'] = isset($currentLanguage['name'][$language]) ? $currentLanguage['name'][$language] : '';
if ($onlyActive == true)
{
unset($languages[$code]['active']);
}
if (isset($currentLanguage['locales']) && is_array($currentLanguage['locales']))
{
foreach ($currentLanguage['locales'] as $localeCode=>$currentLocale)
{
$languages[$code]['locales'][$localeCode]['name'] = isset($currentLocale['name'][$language]) ? $currentLocale['name'][$language] : '';
if ($onlyActive == true)
{
unset($languages[$code]['locales'][$localeCode]['active']);
}
}
$languages[$code]['locales'] = $this->sabsi($languages[$code]['locales'], 'name');
}
}
$languages = $this->sabsi($languages, 'name');
}
return $languages;
}
/**
* Returns the path to language files.
*
* @return string Path to language files.
*
* @access public
* @since 1.0
*/
function getPath()
{
return $this->settings['path'];
}
/**
* Sets the path to language files.
*
* @param string Path to language files.
*
* @access public
* @since 1.0
*/
function setPath($path)
{
$this->settings['path'] = $path;
}
/**
* Parses the XML file that holds the data.
*
* @param string Path to the XML data file
*
* @return array The parsed data
*
* @access private
* @since 1.0
*/
function & parse($xmlFile)
{
$result = array();
if (is_file($xmlFile) && is_readable($xmlFile))
{
$dommer =& new Dommer($xmlFile);
$rootElement =& $dommer->dominate();
$rootElementName = $dommer->getNodeName($rootElement);
if (strcasecmp($rootElementName, 'i18n-data') == 0)
{
$rootElementChildren =& $dommer->getChildren($rootElement);
foreach ($rootElementChildren as $mainElement)
{
$mainElementName = $dommer->getNodeName($mainElement);
$mainElementChildren =& $dommer->getChildren($mainElement);
$currentSectionName = $mainElementName;
$elements = array();
if (isset($mainElementChildren) && is_array($mainElementChildren))
{
foreach ($mainElementChildren as $sectionElement)
{
$elementName = $dommer->getNodeName($sectionElement);
$content = null;
$children =& $dommer->getChildren($sectionElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
}
if (isset($elementName) && trim($elementName) != '')
{
$elements[$elementName] = $content;
}
}
}
if (isset($currentSectionName) && trim($currentSectionName) != '' && isset($elements))
{
$result[$currentSectionName] = $elements;
}
}
}
}
return $result;
}
/**
* Parses the XML configuration file for the file data source.
*
* @param string Path to the XML configuration file
*
* @return array The parsed configuration file
*
* @access private
* @since 1.0
*/
function & parseSettings($configurationFile)
{
$settings = null;
if (is_file($configurationFile) && is_readable($configurationFile))
{
$settings = array();
$dommer =& new Dommer($configurationFile);
$rootElement =& $dommer->dominate();
$rootElementName = $dommer->getNodeName($rootElement);
if (strcasecmp($rootElementName, 'i18n') == 0)
{
$rootElementChildren =& $dommer->getChildren($rootElement);
foreach ($rootElementChildren as $mainElement)
{
$mainElementName = $dommer->getNodeName($mainElement);
$mainElementChildren =& $dommer->getChildren($mainElement);
if (strcasecmp($mainElementName, 'settings') == 0)
{
foreach ($mainElementChildren as $settingsElement)
{
$settingsElementName = $dommer->getNodeName($settingsElement);
$content = null;
if (strcasecmp($settingsElementName, 'path') == 0)
{
$children =& $dommer->getChildren($settingsElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
}
}
else if (strcasecmp($settingsElementName, 'extension') == 0)
{
$children =& $dommer->getChildren($settingsElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
}
}
if (isset($content))
{
$settings[$settingsElementName] = $content;
}
}
}
else if (strcasecmp($mainElementName, 'languages') == 0)
{
foreach ($mainElementChildren as $languagesElement)
{
$languagesElementName = $dommer->getNodeName($languagesElement);
if (strcasecmp($languagesElementName, 'language') == 0)
{
$language = array();
$languagesChildren =& $dommer->getChildren($languagesElement);
foreach ($languagesChildren as $languageElement)
{
$languageElementName = $dommer->getNodeName($languageElement);
$content = null;
if (strcasecmp($languageElementName, 'code') == 0)
{
$children =& $dommer->getChildren($languageElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
$language[$languageElementName] = $content;
}
}
else if (strcasecmp($languageElementName, 'active') == 0)
{
$children =& $dommer->getChildren($languageElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
if (strcasecmp($content, 'true') == 0)
{
$content = true;
}
else
{
$content = false;
}
$language[$languageElementName] = $content;
}
}
else if (strcasecmp($languageElementName, 'name') == 0)
{
$nameChildren =& $dommer->getChildren($languageElement);
foreach($nameChildren as $element)
{
$content = null;
$elementName = $dommer->getNodeName($element);
$children =& $dommer->getChildren($element);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
}
if (isset($content))
{
if (!isset($language['name']))
{
$language['name'] = array();
}
$language['name'][$elementName] = $content;
}
}
}
else if (strcasecmp($languageElementName, 'locales') == 0)
{
$localesElementChildren =& $dommer->getChildren($languageElement);
foreach ($localesElementChildren as $localesElement)
{
$localesElementName = $dommer->getNodeName($localesElement);
if (strcasecmp($localesElementName, 'locale') == 0)
{
$locale = array();
$localesChildren =& $dommer->getChildren($localesElement);
foreach ($localesChildren as $localeElement)
{
$localeElementName = $dommer->getNodeName($localeElement);
$content = null;
if (strcasecmp($localeElementName, 'code') == 0)
{
$children =& $dommer->getChildren($localeElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
$locale[$localeElementName] = $content;
}
}
else if (strcasecmp($localeElementName, 'active') == 0)
{
$children =& $dommer->getChildren($localeElement);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
if (strcasecmp($content, 'true') == 0)
{
$content = true;
}
else
{
$content = false;
}
$locale[$localeElementName] = $content;
}
}
else if (strcasecmp($localeElementName, 'name') == 0)
{
$nameChildren =& $dommer->getChildren($localeElement);
foreach($nameChildren as $element)
{
$content = null;
$elementName = $dommer->getNodeName($element);
$children =& $dommer->getChildren($element);
if (isset($children) && count($children) > 0)
{
$content = $dommer->getNodeValue($children[0]);
}
if (isset($content))
{
if (!isset($locale['name']))
{
$locale['name'] = array();
}
$locale['name'][$elementName] = $content;
}
}
}
}
if (count($locale) > 0 && isset($locale['code']))
{
if (!isset($language['locales']))
{
$language['locales'] = array();
}
$language['locales'][$locale['code']] = $locale;
}
}
}
}
}
if (count($language) > 0 && isset($language['code']))
{
if (!isset($settings['languages']))
{
$settings['languages'] = array();
}
$settings['languages'][$language['code']] = $language;
}
}
}
}
}
}
}
return $settings;
}
/**
* Orders an indexed array on a specific key
*
* @param array The array to order
* @param string The index on which to sort
* @param string The order ('asc' or 'desc')
* @param boolean Wether to use natsort, or not
* @param boolean If case should be distinguished when sorting
*
* @return array The sorted array
*
* @access private
* @since 1.0
*/
function & sabsi (&$array, $index, $order='asc', $natsort=false, $case_sensitive=false)
{
if(is_array($array) && count($array)>0)
{
foreach(array_keys($array) as $key)
{
$temp[$key]=$array[$key][$index];
}
if(!$natsort)
{
($order=='asc')? asort($temp) : arsort($temp);
}
else
{
($case_sensitive)? natsort($temp) : natcasesort($temp);
if($order!='asc')
{
$temp=array_reverse($temp,TRUE);
}
}
foreach(array_keys($temp) as $key)
{
(is_numeric($key))? $sorted[]=$array[$key] : $sorted[$key]=$array[$key];
}
return $sorted;
}
return $array;
}
}
?>