name)."x.php");
class JFalangDatabase extends JOverrideDatabase {
/** @var array list of multi lingual tables */
var $_mlTableList=null;
/** @var Internal variable to hold array of unique tablenames and mapping data*/
var $_refTables=null;
/** @var Internal variable to hold flag about whether setRefTables is needed - JF queries don't need it */
var $_skipSetRefTables = false;
var $orig_limit = 0;
var $orig_offset = 0;
var $_table_prefix = null;
var $profileData = array();
public function JFalangDatabase($options)
{
parent::__construct($options);
$this->_table_prefix = $options['prefix'];
$pfunc = $this->_profile();
$query = "select distinct reference_table from #__falang_content";
$this->setQuery( $query );
$this->_skipSetRefTables = true;
$this->_mlTableList = $this->loadColumn(0,false);
$this->_skipSetRefTables = false;
if( !$this->_mlTableList ){
if ($this->getErrorNum()>0){
JError::raiseWarning( 200, JTEXT::_('No valid table list:') .$this->getErrorMsg());
}
}
$pfunc = $this->_profile($pfunc);
}
/**
* Description
*
* @access public
* @return int The number of rows returned from the most recent query.
*/
function getNumRows( $cur=null, $translate=true, $language=null )
{
$count = parent::getNumRows($cur);
if (!$translate) return $count;
// setup falang plugins
$dispatcher = JDispatcher::getInstance();
jimport('joomla.plugin.helper');
JPluginHelper::importPlugin('falang');
// must allow fall back for contnent table localisation to work
$allowfallback = true;
$refTablePrimaryKey = "";
$reference_table = "";
$ids="";
//$this->setLanguage($language);
$registry = JFactory::getConfig();
$defaultLang = $registry->get("config.defaultlang");
if ($defaultLang == $language){
$rows = array($count);
$dispatcher->trigger('onBeforeTranslation', array (&$rows, &$ids, $reference_table, $language, $refTablePrimaryKey, $this->getRefTables(), $this->sql, $allowfallback));
$count = $rows[0];
return $count;
}
$rows = array($count);
$dispatcher->trigger('onBeforeTranslation', array (&$rows, &$ids, $reference_table, $language, $refTablePrimaryKey, $this->getRefTables(), $this->sql, $allowfallback));
$dispatcher->trigger('onAfterTranslation', array (&$rows, &$ids, $reference_table, $language, $refTablePrimaryKey, $this->getRefTables(), $this->sql, $allowfallback));
$count = $rows[0];
return $count;
}
/**
* Execute the SQL statement. New query() name since 2.5.5
*
* @return mixed A database cursor resource on success, boolean false on failure.
*
* @since 11.1
* @throws DatabaseException
*/
public function execute()
{
if ( version_compare( JVERSION, '2.5.5', '<' ) == 1) {
$success = parent::query();
} else {
$success = parent::execute();
}
if ($success && !$this->_skipSetRefTables){
$this->setRefTables();
}
return $this->cursor;
}
/**
* Execute the SQL statement. query() become execute since 2.5.5
*
* @return mixed A database cursor resource on success, boolean false on failure.
*
* @since 11.1
* @throws DatabaseException
*/
public function query()
{
return $this->execute();
}
//sbou falang method
/**
* Overwritten Database method to loads the first field of the first row returned by the query.
*
* @return The value returned in the query or null if the query failed.
*/
function loadResult( $translate=true, $language=null ) {
if (!$translate){
$this->_skipSetRefTables=true;
$result = parent::loadResult();
$this->_skipSetRefTables=false;
return $result;
}
$result=null;
$ret=null;
$result = $this->_loadObject( $translate, $language );
$pfunc = $this->_profile();
if( $result != null ) {
$fields = get_object_vars( $result );
$field = each($fields);
$ret = $field[1];
}
$pfunc = $this->_profile($pfunc);
return $ret;
}
function loadResultArray($offset = 0, $translate=true, $language=null){
return $this->loadColumn($offset,$translate,$language);
}
/**
* Overwritten Method to get an array of values from the $offset field in each row of the result set from
* the database query.
*
* @param integer $offset The row offset to use to build the result array.
*
* @return mixed The return value or null if the query failed.
*
* @since 11.1
* @throws DatabaseException
*/
function loadColumn($offset = 0, $translate=true, $language=null){
if (!$translate){
return parent::loadColumn($offset);
}
$results=array();
$ret=array();
$results = $this->loadObjectList( '','stdClass', $translate, $language );
$pfunc = $this->_profile();
if( $results != null && count($results)>0) {
foreach ($results as $row) {
$fields = get_object_vars( $row );
$keycount = 0;
foreach ($fields as $k=>$v) {
if ($keycount==$offset){
$key = $k;
break;
}
}
$ret[] = $fields[$key];
}
}
$pfunc = $this->_profile($pfunc);
return $ret;
}
/**
* Overwritten
*
* @access public
* @return The first row of the query.
*/
function loadRow( $translate=true, $language=null)
{
if (!$translate){
return parent::loadRow();
}
$result=null;
$result = $this->_loadObject( $translate, $language );
$pfunc = $this->_profile();
$row = array();
if( $result != null ) {
$fields = get_object_vars( $result );
foreach ($fields as $val) {
$row[] = $val;
}
return $row;
}
return $row;
}
/**
* Overwritten Load a list of database rows (numeric column indexing)
*
* @access public
* @param string The field name of a primary key
* @return array If key is empty as sequential list of returned records.
* If key is not empty then the returned array is indexed by the value
* the database key. Returns null if the query fails.
*/
function loadRowList( $key=null , $translate=true, $language=null)
{
if (!$translate){
return parent::loadRowList($key);
}
$results=array();
if (is_null($key)) $key="";
$rows = $this->loadObjectList($key,'stdClass', $translate, $language );
$pfunc = $this->_profile();
$row = array();
if( $rows != null ) {
foreach ($rows as $row) {
$fields = get_object_vars( $row );
$result = array();
foreach ($fields as $val) {
$result[] = $val;
}
if ($key!="") {
$results[$row->$key] = $result;
}
else {
$results[] = $result;
}
}
}
$pfunc = $this->_profile($pfunc);
return $results;
}
function loadObjectList( $key='',$class = 'stdClass', $translate=true, $language=null ) {
//sbou
//sbou TODO check r�cursive pb
//$jfManager = FalangManager::getInstance();
if (!$translate) {
$this->_skipSetRefTables=true;
$result = parent::loadObjectList( $key ,empty($class)?'stdClass':$class);
$this->_skipSetRefTables=false;
return $result;
}
$result = parent::loadObjectList( $key, empty($class)?'stdClass':$class);
// if( isset($jfManager)) {
// $this->_setLanguage($language);
// }
// TODO check the impact of this on frontend translation
// It does stop Joomfish plugins from working on missing translations e.g. regional content so disable for now
// Don't do it for now since translation caching is so effective
/*
$registry = JFactory::getConfig();
$defaultLang = $registry->getValue("config.defaultlang");
if ($defaultLang == $language){
$translate = false;
}
*/
//sbou TODO this is not the right solution.
// if( isset($jfManager)) {
if (true){
$doTranslate=false;
$tables =$this->getRefTables();
if ($tables == null) return $result; // an unstranslatable query to return result as is
// if we don't have "fieldTablePairs" then we can't translate
if (!array_key_exists("fieldTablePairs",$tables)){
return $result;
}
foreach ($tables["fieldTablePairs"] as $i=>$table) {
if ($this->translatedContentAvailable($table)) {
$doTranslate=true;
break;
}
}
if ($doTranslate ) {
$pfunc = $this->_profile();
//sbou TODO cache desactived
// if ($jfManager->getCfg("transcaching",1)){
if (false) {
// cache the results
// TODO call based on config
//$cache = JFactory::getCache('jfquery');
$cache = $jfManager->getCache($language);
$this->orig_limit = $this->limit;
$this->orig_offset = $this->offset;
$result = $cache->get( array("FaLang", 'translateListCached'), array($result, $language, $this->getRefTables() ));
$this->orig_limit = 0;
$this->orig_offset = 0;
}
else {
$this->orig_limit = $this->limit;
$this->orig_offset = $this->offset;
Falang::translateList( $result, $language, $this->getRefTables() );
$this->orig_limit = 0;
$this->orig_offset = 0;
}
$pfunc = $this->_profile($pfunc);
}
}
return $result;
}
/**
* private function to handle the requirement to call different loadObject version based on class
*
* @param boolran $translate
* @param string $language
*/
function _loadObject( $translate=true, $language=null ) {
return $this->loadObject();
}
function _profile($func = "", $forcestart=false){
if (!$this->debug) return "";
// start of function
if ($func==="" || $forcestart){
if (!$forcestart){
$backtrace = debug_backtrace();
if (count($backtrace)>1){
if (array_key_exists("class",$backtrace[1])){
$func = $backtrace[1]["class"]."::".$backtrace[1]["function"];
}
else {
$func = $backtrace[1]["function"];
}
}
}
if (!array_key_exists($func,$this->profileData)){
$this->profileData[$func]=array("total"=>0, "count"=>0);
}
if (!array_key_exists("start",$this->profileData[$func])) {
$this->profileData[$func]["start"]=array();
}
list ($usec,$sec) = explode(" ", microtime());
$this->profileData[$func]["start"][] = floatval($usec)+floatval($sec);
$this->profileData[$func]["count"]++;
return $func;
}
else {
if (!array_key_exists($func,$this->profileData)){
exit("JFProfile start not found for function $func");
}
list ($usec,$sec) = explode(" ", microtime());
$laststart = array_pop($this->profileData[$func]["start"]);
$this->profileData[$func]["total"] += (floatval($usec)+floatval($sec)) - $laststart;
}
}
/**
* Public function to test if table has translated content available
*
* @param string $table : tablename to test
*/
function translatedContentAvailable($table){
return in_array( $table, $this->_mlTableList) || $table=="content";
}
/** Internal function to return reference table names from an sql query
*
* @return string table name
*/
function getRefTables(){
return $this->_refTables;
}
/**
* This global function loads the first row of a query into an object
*/
function loadObject( $class = 'stdClass', $translate=true, $language=null ) {
$objects = $this->loadObjectList("",$class,$translate,$language);
if (!is_null($objects) && count($objects)>0){
return $objects[0];
}
return null;
}
/**
* Overwritten Fetch a result row as an associative array
*
* @access public
* @return array
*/
function loadAssoc( $translate=true, $language=null) {
if (!$translate){
return parent::loadResult();
}
$result=null;
$result = $this->_loadObject( $translate, $language );
$pfunc = $this->_profile();
if( $result != null ) {
$fields = get_object_vars( $result );
$pfunc = $this->_profile($pfunc);
return $fields;
}
return $result;
}
/**
* Overwritten Load a assoc list of database rows
*
* @access public
* @param string The field name of a primary key
* @return array If key is empty as sequential list of returned records.
*/
function loadAssocList( $key = null, $column = null, $translate=true, $language=null )
{
if (!$translate){
return parent::loadAssocList($key, $column = null);
}
$result=null;
$rows = $this->loadObjectList($key,'stdClass', $translate, $language );
$pfunc = $this->_profile();
$return = array();
if( $rows != null ) {
foreach ($rows as $row) {
$vars = get_object_vars( $row );
$value = ($column) ? (isset($vars[$column]) ? $vars[$column] : $vars) : $vars;
if ($key) {
$return[$vars[$key]] = $value;
}
else {
$return[] = $value;
}
}
$pfunc = $this->_profile($pfunc);
}
return $return;
}
/**
* Overwritten insert function to enable storage of material created in non-default language.
* Note that this creates a translation which is identical to the original - when we update
* the original in the default language we then keep the translation (although it will appread out of date!).
*
* @param string table name
* @param object instance with information to store
* @param string primary key name of table
* @param boolean debug info printed or not
* @param boolean passthru without storing information in a translation table
*/
function updateObject( $table, &$object, $keyName, $updateNulls=true, $passthru=false ) {
$params = JComponentHelper::getParams('com_falang');
$pfunc = $this->_profile();
$falangManager = FalangManager::getInstance();
$current_lang = JFactory::getLanguage()->getTag();
//default site language
$default_lang = JComponentHelper::getParams('com_languages')->get('site');
//we update if content language is set to all language or if content language is current_langauge
// check if marked langage of content is the detaul language:
if ($table=='#__content' && isset($object->id) &&$object->id>0 ){
$test = JTable::getInstance("Content");
$test->load($object->id);
if ( $test->language == '*'){
if ($current_lang == $default_lang) {
return parent::updateObject( $table, $object, $keyName, $updateNulls );
}
}
if ( $test->language == $current_lang) {
return parent::updateObject( $table, $object, $keyName, $updateNulls );
}
}
if (isset($falangManager) && ($table != "#__falang_content")){
$tableName = preg_replace( '/^#__/', '', $table);
$contentElement = $falangManager->getContentElement( $tableName );
if( isset( $contentElement ) ) {
include_once(JPATH_ADMINISTRATOR."/components/com_falang/models/ContentObject.php");
$actContentObject = new ContentObject( $falangManager->getLanguageID($current_lang), $contentElement );
//hikashop woraround //
$lkeyName = method_exists($object,'getKeyName')?$object->getKeyName():null;
if( !empty( $lkeyName) ) {
$actContentObject->loadFromContentID( $object->id );
$actContentObject->updateMLContent( $object );
if( isset( $object->state ) ) {
$actContentObject->published = ($object->state == 1) ? true : false;
} else if ( isset( $object->published ) ) {
$actContentObject->published = ($object->published == 1) ? true : false;
}
//if ( $falangManager->getCfg("frontEndPublish")){
if ($params->get('frontEndEdition',0) == 1){
$user = JFactory::getUser();
$access = new stdClass();
//$access->canPublish = $user->authorize('com_content', 'publish', 'content', 'all');
//if ($access->canPublish) $actContentObject->setPublished($actContentObject->published);
$actContentObject->setPublished($actContentObject->published);
}
//if allow front-end translation
if ($params->get('frontEndEdition',0) == 1){
$actContentObject->store();
} else {
$application = JFactory::getApplication();
$application->enqueueMessage(JText::_('PLG_SYSTEM_FALANGDRIVER_FRONT_UPDATE_NOT_AUTHORIZED'), 'notice');
return false;
}
} else {
//hikashop workaround this update hit.
return parent::updateObject( $table, $object, $keyName, $updateNulls );
}
} //content element not exist
$pfunc = $this->_profile($pfunc);
//return parent::updateObject( $table, $object, $keyName, $updateNulls );
return true;
} else {
return parent::updateObject( $table, $object, $keyName, $updateNulls );
}
}
}