<?php

if (!defined('XOOPS_ROOT_PATH')) exit();

require_once XOOPS_BASE_PATH."/admin/class/AbstractModuleInstaller.class.php";

class Legacy_ModuleUpdater extends Legacy_AbstractModuleInstaller
{
	var $mPreVersion = 0;

	function Legacy_ModuleUpdater($dirname)
	{
		parent::Legacy_AbstractModuleInstaller($dirname);
		
		$this->mProcessScript->register('Legacy_ModuleUpdater.ProcessScript');
		$this->mProcessScript->add(array(&$this, '_processScript'));
		
		$this->mInstallTable->register('Legacy_ModuleUpdater.InstallTable');

		$this->mInstallTemplate->register('Legacy_ModuleUpdater.InstallTemplate');
		$this->mInstallTemplate->add('Legacy_ModuleUpdater::_uninstallTemplate');
	}

	/**
	 * @return bool
	 */
	function execute()
	{
		$this->mLog->addReport(_AD_BASE_MESSAGE_UPDATE_STARTED);
		
		parent::execute();
	}
	
	/**
	 * Load xoops module object installed and return it.
	 * @static
	 * @access public
	 * @param $dirname string
	 * @return XoopsModule
	 */
	function &loadModuleObject($dirname)
	{
		$ret = null;

		$moduleHandler =& xoops_gethandler('module');
		$module =& $moduleHandler->getByDirname($dirname);

		if (!is_object($module))
			return $ret;

		$this->mPreVersion = $module->getVar('version');
        $name = $module->getVar('name','n');
		$module->loadInfoAsVar($dirname);
		$module->setVar('name', $name, true);
		return $module;
	}

	/**
	 * @static
	 */
	function _uninstallTemplate(&$module, &$log)
	{
		$tplHandler =& xoops_gethandler('tplfile');

		//
		// The following processing depends on the structure of Legacy_RenderSystem.
		//
		$tplHandler =& xoops_gethandler('tplfile');
		$delTemplates =& $tplHandler->find('default', 'module', $module->getVar('mid'));
		if(is_array($delTemplates) && count($delTemplates) > 0) {
			//
			// clear cache
			//
			$xoopsTpl=new XoopsTpl();
			$xoopsTpl->clear_cache(null, "mod_" . $module->getVar('dirname'));
			
			foreach ($delTemplates as $tpl) {
				if (!$tplHandler->delete($tpl)) {
					$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_TEMPLATE_UNINSTALLED, $tpl->getVar('tpl_file')));
				}
			}
		}

		//
		// install Template All
		//
		$templates = $module->getInfo('templates');
		if ($templates != false) {
			foreach ($templates as $template) {
				Legacy_ModuleUtils::installTemplate($module, $template, $log);
			}
		}
	}

	/**
	 * @return bool
	 */
	function _installBlock()
	{
		// XoopsBlock[]
		$installBlocks = array();

		// XoopsBlock[]
		$unInstallBlocks = array();

		$definedBlocks = $this->mModule->getInfo('blocks');
		if($definedBlocks == false)
			return false;

		$blockHandler =& xoops_gethandler('block');

		$func_num=0;
		$showfuncs = array();
        $funcfiles = array();
		for ($i=1; $i<= count($definedBlocks); $i++) {
		    $block =&  $definedBlocks[$i];
			$func_num = $i;
		    $showfuncs[]=$block['show_func'];
		    $funcfiles[]=$block['file'];
			$newBlock =& Legacy_ModuleUtils::createBlockByInfo($this->mModule, $block);
			//
			// Get a installed block by mid and name.
			//
			$criteria = new CriteriaCompo();
			$criteria->add(new Criteria('mid', $this->mModule->getVar('mid')));
			$criteria->add(new Criteria('func_num', $func_num));
			$criteria->add(new Criteria('show_func', $block['show_func']));
			$criteria->add(new Criteria('func_file', $block['file']));
			$installedBlocks =& $blockHandler->getObjectsDirectly($criteria);
			//
			// If a installed block is not found, push it to new install block list.
			//
			if (count($installedBlocks) == 0) {
				$newBlock->setVar('func_num', $func_num);
				$installBlocks[] = array($newBlock, $block);
				unset($newBlock);

				continue;
			}

			$changedFlag = false;

			$oldBlock =& $installedBlocks[0];
            $newBlock =& Legacy_ModuleUtils::mergeBlockObject($oldBlock, $newBlock, $changedFlag);

			if ($changedFlag) {
				$installBlocks[] = array($newBlock, $block);
			}
			else {
				if (!Legacy_ModuleUtils::installBlockTemplate($this->mModule, $oldBlock)) {
					$this->mLog->addError("ERROR : Could not update block template ".$oldBlock->getVar('name'));
				}
			}

			unset($newBlock);
			unset($oldBlock);
		}
		$criteria = new CriteriaCompo();
		$criteria->add(new Criteria('mid', $this->mModule->getVar('mid')));
		$installedBlocks =& $blockHandler->getObjectsDirectly($criteria);
		foreach ($installedBlocks as $blockObj) {
            if (!in_array($blockObj->getVar('show_func'), $showfuncs) || !in_array($blockObj->getVar('func_file'), $funcfiles)) {
				$unInstallBlocks[] =& $blockObj;
				unset($blockObj);
            }
        }

		foreach ($installBlocks as $block) {
			Legacy_ModuleUtils::installBlock($this->mModule, $block[0], $block[1], $this->mLog);
		}
        
		foreach ($unInstallBlocks as $block) {
			Legacy_ModuleUtils::unInstallBlock($block, $this->mLog);
		}

	}
	
	function _installPreference()
	{
		$configHandler =& xoops_gethandler('config');
		
		//
		// At the start, load config items of this time.
		//
		$criteria =& new CriteriaCompo();
		$criteria->add(new Criteria('conf_modid', $this->mModule->get('mid')));
		$criteria->add(new Criteria('conf_catid', 0));
		
		$activeConfigArr =& $configHandler->getConfigs($criteria);
		
		//
		// Next, load config item from xoops_version.php.
		//
		$newConfigArr = array();
		$t_configInfoArr = Legacy_ModuleUtils::getConfigInfosFromManifesto($this->mModule);
		
		$count = 0;
		if (is_array($t_configInfoArr)) {
			foreach ($t_configInfoArr as $t_configInfo) {
				$config =& $configHandler->createConfig();
				$config->loadFromConfigInfo($this->mModule->get('mid'), $t_configInfo, $count++);
				$newConfigArr[] =& $config;
				unset($config);
			}
		}
		
		//
		// If some active configs were deleted, remove them form database.
		//
		foreach (array_keys($activeConfigArr) as $t_actkey) {
			$findFlag = false;
			foreach (array_keys($newConfigArr) as $t_newkey) {
				
				if ($activeConfigArr[$t_actkey]->get('conf_name') == $newConfigArr[$t_newkey]->get('conf_name')) {
					$findFlag = true;
					if (!$activeConfigArr[$t_actkey]->isEqual($newConfigArr[$t_newkey])) {
						//
						// Update object
						//
						$activeConfigArr[$t_actkey]->set('conf_title', $newConfigArr[$t_newkey]->get('conf_title'));
						$activeConfigArr[$t_actkey]->set('conf_value', $newConfigArr[$t_newkey]->get('conf_value'));
						$activeConfigArr[$t_actkey]->set('conf_desc', $newConfigArr[$t_newkey]->get('conf_desc'));
						$activeConfigArr[$t_actkey]->set('conf_formtype', $newConfigArr[$t_newkey]->get('conf_formtype'));
						$activeConfigArr[$t_actkey]->set('conf_valuetype', $newConfigArr[$t_newkey]->get('conf_valuetype'));
						
						//
						// Delete config options.
						//
						$t_optionArr =& $activeConfigArr[$t_actkey]->getOptionItems();
						foreach (array_keys($t_optionArr) as $t_optionKey) {
							$configHandler->_oHandler->delete($t_optionArr[$t_optionKey]);	//< Exception!!
						}
						
						$activeConfigArr[$t_actkey]->setConfOptions($newConfigArr[$t_newkey]->getConfOptions());
						
						$configHandler->insertConfig($activeConfigArr[$t_actkey]);	//< FIXME need log.
					}
				}
			}
			
			if (!$findFlag) {
				$configHandler->deleteConfig($activeConfigArr[$t_actkey]);
				unset($activeConfigArr[$t_actkey]);
			}
		}
		
		//
		// If some new configs were registered, insert them into database.
		//
		$maxOrder = 0;
		foreach (array_keys($activeConfigArr) as $t_actkey) {
			if ($activeConfigArr[$t_actkey]->get('conf_order') > $maxOrder) {
				$maxOrder = $activeConfigArr[$t_actkey]->get('conf_order');
			}
		}
		
		$order = $maxOrder + 1;
		
		foreach (array_keys($newConfigArr) as $t_newkey) {
			$newFlag = true;
			foreach (array_keys($activeConfigArr) as $t_actkey) {
				if ($newConfigArr[$t_newkey]->isEqual($activeConfigArr[$t_actkey])) {
					$newFlag = false;
					break;
				}
			}
			
			if ($newFlag) {
				$newConfigArr[$t_newkey]->set('conf_order', $order);
				if ($configHandler->insertConfig($newConfigArr[$t_newkey])) {
					$this->mLog->addReport(XCube_Utils::formatMessage(_AD_BASE_MESSAGE_INSERT_CONFIG, $newConfigArr[$t_newkey]->get('conf_name')));
				}
				else {
					$this->mLog->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_INSERT_CONFIG, $newConfigArr[$t_newkey]->get('conf_name')));
				}
			}
		}
	}

	function _processScript(&$module, &$log)
	{
		$installScript = trim($module->getInfo('onUpdate'));
		if ($installScript != false) {
			require_once XOOPS_MODULE_PATH . "/" . $module->getVar('dirname') . "/" . $installScript;
			$funcName = 'xoops_module_update_' . $module->getVar('dirname');
			if (function_exists($funcName)) {
				if (!call_user_func($funcName, $module, $this->mPreVersion)) {
					$log->addError("Failed to execute " . $funcName);
				}
			}
		}
	}
	
	function _processReport()
	{
		if (!$this->mLog->hasError()) {
			$this->mLog->add(XCube_Utils::formatMessage(_AD_BASE_MESSAGE_UPDATING_MODULE_SUCCESSFUL, $this->mModule->get('name')));
		}
		else {
			if (is_object($this->mModule)) {
				$this->mLog->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_UPDATING_MODULE_FAILURE, $this->mModule->get('name')));
			}
			else {
				$this->mLog->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_UPDATING_MODULE_FAILURE, $this->mDirname));
			}
		}
	}
}

?>