<?php

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

require_once XOOPS_ROOT_PATH."/class/template.php";

define("MODINSTALL_LOGTYPE_REPORT", "report");
define("MODINSTALL_LOGTYPE_WARNING", "warning");
define("MODINSTALL_LOGTYPE_ERROR", "error");

/**
 * A temporary log class.
 */
class Legacy_ModuleUtilsSimpleLog
{
	var $mFetalErrorFlag = false;
	var $mMessages = array();

	function add($msg)
	{
		$this->mMessages[] = array('type' => MODINSTALL_LOGTYPE_REPORT, 'message' => $msg);
	}

	function addReport($msg)
	{
		$this->add($msg);
	}
	
	function addWarning($msg)
	{
		$this->mMessages[] = array('type' => MODINSTALL_LOGTYPE_WARNING, 'message' => $msg);
	}

	function addError($msg)
	{
		$this->mMessages[] = array('type' => MODINSTALL_LOGTYPE_ERROR, 'message' => $msg);
		$this->mFetalErrorFlag = true;
	}
	
	function hasError()
	{
		return $this->mFetalErrorFlag;
	}
}

/**
 * This provides static methods for the module installation. Methods of this
 * class may move to base class of installers. 
 */
class Legacy_ModuleUtils
{
	/**
	 */
	function installTable(&$module, &$log)
	{
		$sqlfileInfo =& $module->getInfo('sqlfile');
		$dirname = $module->getVar('dirname');

		if (!isset($sqlfileInfo[XOOPS_DB_TYPE])) {
			return;
		}
		
		require_once XOOPS_MODULE_PATH . "/base/admin/class/Legacy_SQLScanner.class.php";
		$scanner =& new Legacy_SQLScanner();
		$scanner->setDB_PREFIX(XOOPS_DB_PREFIX);
		
		$sqlfile = $sqlfileInfo[XOOPS_DB_TYPE];
		if (!$scanner->loadFile(XOOPS_MODULE_PATH . "/${dirname}/" . $sqlfile)) {
			$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_SQL_FILE_NOT_FOUND, $sqlfile));
			return false;
		}

		$scanner->parse();
		$sqls = $scanner->getSQL();
		
		$root =& XCube_Root::getSingleton();
		$db =& $root->mController->getDB();
		
		//
		// TODO The following variable exists for rollback, but it is not implemented.
		//
		foreach ($sqls as $sql) {
			if (!$db->query($sql)) {
				$log->addError($db->error());
				return;
			}
		}
		
		$log->addReport(_AD_BASE_MESSAGE_DATABASE_SETUP_FINISHED);
	}

	/**
	 *  Insert template to DB.
	 *  This function depends on the structure of Legacy_RenderSystem. We should
	 * move this to another mechanism.
	 *
	 * @param $dirname string
	 * @param $$template string[][]
	 * @param $log Legacy_ModuleUtilsSimpleLog *
	 * @param bool
	 */
	function installTemplate($module, $template, &$log)
	{
		$tplHandler =& xoops_gethandler('tplfile');

		$fileName = trim($template['file']);

		$tpldata = Legacy_ModuleUtils::readTemplateFile($module->getVar('dirname'), $fileName);
		if ($tpldata == false)
			return false;

		//
		// Create template file object, then store it.
		//
		$tplfile =& $tplHandler->create();
		$tplfile->setVar('tpl_refid', $module->getVar('mid'));
		$tplfile->setVar('tpl_lastimpoerted', 0);
		$tplfile->setVar('tpl_lastmodified', time());

		if (preg_match("/\.css$/i", $fileName)) {
			$tplfile->setVar('tpl_type', 'css');
		}
		else {
			$tplfile->setVar('tpl_type', 'module');
		}

		$tplfile->setVar('tpl_source', $tpldata, true);
		$tplfile->setVar('tpl_module', $module->getVar('dirname'));
		$tplfile->setVar('tpl_tplset', 'default');
		$tplfile->setVar('tpl_file', $fileName, true);

		$description = isset($tpl['description']) ? $tpl['description'] : '';
		$tplfile->setVar('tpl_desc', $description, true);
		
		if ($tplHandler->insert($tplfile)) {
			$log->addReport(XCube_Utils::formatMessage(_AD_BASE_MESSAGE_TEMPLATE_INSTALLED, $fileName));
		}
		else {
			$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_INSTALL_TEMPLATE, $fileName));
			return false;
		}

		return true;
	}
	
	/**
	 * Read template file, return it.
	 *
	 * @return string or false
	 */
	function readTemplateFile($dirname, $fileName, $isblock = false)
	{
		//
		// Load template data
		//
		if ($isblock) {
			$filePath = XOOPS_MODULE_PATH . "/" . $dirname . "/templates/blocks/" . $fileName;
		}
		else {
			$filePath = XOOPS_MODULE_PATH . "/" . $dirname . "/templates/" . $fileName;
		}

		if (!file_exists($filePath)) {
			return false;
		}

		$lines = file($filePath);
		if ($lines == false) {
			return false;
		}

		$tpldata = "";
		foreach ($lines as $line) {
			//
			// Unify linefeed to "\r\n" 
			//
			$tpldata .= str_replace("\n", "\r\n", str_replace("\r\n", "\n", $line));
		}
		
		return $tpldata;
	}
	
	/**
	 * Create XoopsBlock object by array that is defined in xoops_version, return it.
	 * @param $module XoopsModule
	 * @param $block array
	 * @return XoopsBlock
	 */
	function &createBlockByInfo(&$module, $block)
	{
		$options = isset($block['options']) ? $block['options'] : null;
		$edit_func = isset($block['edit_func']) ? $block['edit_func'] : null;
		$template = isset($block['template']) ? $block['template'] : null;
		$visible = isset($block['visible']) ? $block['visible'] : (isset($block['visible_any']) ? $block['visible_any']: 0);
		$blockHandler =& xoops_gethandler('block');
		$blockObj =& $blockHandler->create();

		$blockObj->setVar('mid', $module->getVar('mid'));
		$blockObj->setVar('options', $options);
		$blockObj->setVar('name', $block['name']);
		$blockObj->setVar('title', $block['name']);
		$blockObj->setVar('block_type', 'M');
		$blockObj->setVar('c_type', 1);
		$blockObj->setVar('isactive', 1);
		$blockObj->setVar('dirname', $module->getVar('dirname'));
		$blockObj->setVar('func_file', $block['file']);
		$blockObj->setVar('show_func', $block['show_func']);
		$blockObj->setVar('edit_func', $edit_func);
		$blockObj->setVar('template', $template);
		$blockObj->setVar('last_modified', time());
		$blockObj->setVar('visible', $visible);

		return $blockObj;
	}

    /**
     * Merge existing block XoopsBlock object and new XoopsBlock object from xoops_verion
     * @param $oldBlock XoopsBlock
     * @param $newBlock XoopsBlock
     * @param $changedFlag bool
     * @return XoopsBlock
     */
	function &mergeBlockObject(&$oldBlock, &$newBlock, &$changedFlag)
    {
        $blockObj =& $oldBlock->xoopsClone();
        $blockObj->unsetNew();
        
		$changedFlag = false;
		$checkValues = array('name', 'func_file', 'show_func', 'edit_func', 'template');
		foreach($checkValues as $checkValue) {
		    if ($newBlock->getVar($checkValue) != $oldBlock->getVar($checkValue)) {
		        $blockObj->setVar($checkValue, $newBlock->getVar($checkValue));
		        $changedFlag |= true;
		    }
		}

		$old_options=explode("|",$oldBlock->getVar('options'));
		$new_options=explode("|",$newBlock->getVar('options'));
		if (count($new_options) > count($old_options)) {
	        $changedFlag |= true;
		    for ($i=count($old_options); $i<count($new_options); $i++) {
		        $old_options[$i] = $old_options[$i];
		    }
		    $blockObj->setVar('options', implode("|", $old_options));
		} else if (count($new_options) < count($old_options)) {
	        $changedFlag |= true;
		    $blockObj->setVar('options', $newBlock->getVar('options'));
		}
		
		return $blockObj;
    }

	/**
	 * This function can receive both new and update.
	 * @param $module XoopsModule
	 * @param $blockObj XoopsBlock
	 * @param $block array
	 * @return bool
	 */
	function installBlock(&$module, &$blockObj, &$block, &$log)
	{
		$isNew = $blockObj->isNew();
		$blockHandler =& xoops_gethandler('block');

        if (!empty($block['show_all_module'])) {
            $autolink = false;
        } else {
            $autolink = true;
        }
		if (!$blockHandler->insert($blockObj, $autolink)) {
			$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_INSTALL_BLOCK, $blockObj->getVar('name')));

			return false;
		}
		else {
			$log->addReport(XCube_Utils::formatMessage(_AD_BASE_MESSAGE_BLOCK_INSTALLED, $blockObj->getVar('name')));

			$tplHandler =& xoops_gethandler('tplfile');

			if (!Legacy_ModuleUtils::installBlockTemplate($module, $blockObj)) {
				$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_BLOCK_TEMPLATE_INSTALL, $blockObj->getVar('name')));
			}
			
			//
			// Process of a permission.
			//
			if ($isNew) {
                if (!empty($block['show_all_module'])) {
        			$link_sql = "INSERT INTO " . $blockHandler->db->prefix('block_module_link') . " (block_id, module_id) VALUES (".$blockObj->getVar('bid').", 0)";
		        	if (!$blockHandler->db->query($link_sql)) {
       					$log->addWarn(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_SET_LINK, $blockObj->getVar('name')));
		        	}
    			}
   				$gpermHandler =& xoops_gethandler('groupperm');
   				$bperm =& $gpermHandler->create();
				$bperm->setVar('gperm_itemid', $blockObj->getVar('bid'));
				$bperm->setVar('gperm_name', 'block_read');
				$bperm->setVar('gperm_modid', 1);
				
				if (!empty($block['visible_any'])) {
    				$memberHandler =& xoops_gethandler('member');
    				$groupObjects =& $memberHandler->getGroups();
    				foreach($groupObjects as $group) {
        				$bperm->setVar('gperm_groupid', $group->getVar('groupid'));
        				$bperm->setNew();
        				if (!$gpermHandler->insert($bperm)) {
        					$log->addWarn(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_SET_BLOCK_PERMISSION, $blockObj->getVar('name')));
        				}
        			}
				} else {
				    $root =& XCube_Root::getSingleton();
                    $groups = $root->mController->mXoopsUser->getGroups();
                    foreach ($groups as $mygroup) {
        				$bperm->setVar('gperm_groupid', $mygroup);
        				$bperm->setNew();
        				if (!$gpermHandler->insert($bperm)) {
        					$log->addWarn(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_SET_BLOCK_PERMISSION, $blockObj->getVar('name')));
    				    }
    				}
				}
			}

			return true;
		}
	}
	
	function unInstallBlock(&$block, &$log) {
		$blockHandler =& xoops_gethandler('block');
		$blockHandler->delete($block);
		$log->addReport("Uninstall block '".$block->getVar('name'));
		//
		// delete permission
		//
		$gpermHandler =& xoops_gethandler('groupperm');
		$criteria =& new CriteriaCompo();
		$criteria->add(new Criteria('gperm_name', 'block_read'));
		$criteria->add(new Criteria('gperm_itemid', $block->getVar('bid')));
		$criteria->add(new Criteria('gperm_modid', 1));
		$gpermHandler->deleteAll($criteria);
    }
    
	/**
	 * Save the information of block's template specified and the source code of it
	 * to database.
	 * @return bool
	 */
	function installBlockTemplate(&$module, &$block)
	{
		if ($block->get('template') == null) {
			return true;
		}
		
		$tplHandler =& xoops_gethandler('tplfile');

		$criteria =& new CriteriaCompo();
		$criteria->add(new Criteria('tpl_type', 'block'));
		$criteria->add(new Criteria('tpl_tplset', 'default'));
		$criteria->add(new Criteria('tpl_module', $module->getVar('dirname')));
		$criteria->add(new Criteria('tpl_file', $block->getVar('template')));
		$tplfiles =& $tplHandler->getObjects($criteria);

		if (count($tplfiles) > 0) {
			$tplfile =& $tplfiles[0];
		}
		else {
			$tplfile =& $tplHandler->create();
			$tplfile->setVar('tpl_refid', $block->getVar('bid'));
			$tplfile->setVar('tpl_tplset', 'default');
			$tplfile->setVar('tpl_file', $block->getVar('template'));
			$tplfile->setVar('tpl_module', $module->getVar('dirname'));
			$tplfile->setVar('tpl_type', 'block');
			// $tplfile->setVar('tpl_desc', $tpl_desc);
			$tplfile->setVar('tpl_lastimported', 0);
		}
		
		$tplSource = Legacy_ModuleUtils::readTemplateFile($module->getVar('dirname'), $block->getVar('template'), true);
		$tplfile->setVar('tpl_source', $tplSource);
		$tplfile->setVar('tpl_lastmodified', time());

		return $tplHandler->insert($tplfile);
	}

	function insertAllConfigs(&$module, &$log)
	{
		$configInfos = $module->getInfo('config');

		//
		// Insert comment config by old style.
		//
		if ($module->getVar('hascomments') !=0 ) {
			require_once XOOPS_ROOT_PATH . "/include/comment_constants.php";

			$configInfos[] = array('name' => 'com_rule',
			                         'title' => '_CM_COMRULES',
			                         'description' => '',
			                         'formtype' => 'select',
			                         'valuetype' => 'int',
			                         'default' => 1,
			                         'options' => array('_CM_COMNOCOM' => XOOPS_COMMENT_APPROVENONE, '_CM_COMAPPROVEALL' => XOOPS_COMMENT_APPROVEALL, '_CM_COMAPPROVEUSER' => XOOPS_COMMENT_APPROVEUSER, '_CM_COMAPPROVEADMIN' => XOOPS_COMMENT_APPROVEADMIN)
			                   );

			$configInfos[] = array('name' => 'com_anonpost',
			                         'title' => '_CM_COMANONPOST',
			                         'description' => '',
			                         'formtype' => 'yesno',
			                         'valuetype' => 'int',
			                         'default' => 0
			                   );
		}

		//
		// Insert comment config by old style.
		//
		if ($this->mModule->get('hasnotification') != 0) {
			require_once XOOPS_ROOT_PATH . '/include/notification_constants.php';
			require_once XOOPS_ROOT_PATH . '/include/notification_functions.php';
			
			$t_options = array();
			$t_options['_NOT_CONFIG_DISABLE'] = XOOPS_NOTIFICATION_DISABLE;
			$t_options['_NOT_CONFIG_ENABLEBLOCK'] = XOOPS_NOTIFICATION_ENABLEBLOCK;
			$t_options['_NOT_CONFIG_ENABLEINLINE'] = XOOPS_NOTIFICATION_ENABLEINLINE;
			$t_options['_NOT_CONFIG_ENABLEBOTH'] = XOOPS_NOTIFICATION_ENABLEBOTH;
			
			$configInfos[] = array(
				'name' => 'notification_enabled',
				'title' => '_NOT_CONFIG_ENABLE',
				'description' => '_NOT_CONFIG_ENABLEDSC',
				'formtype' => 'select',
				'valuetype' => 'int',
				'default' => XOOPS_NOTIFICATION_ENABLEBOTH,
				'options' => $t_options
			);
			
			//
			// FIXME: doesn't work when update module... can't read back the
			//        array of options properly...  " changing to &quot;
			//
			
			unset ($t_options);
			
			$t_options = array();
			$t_categoryArr =& notificationCategoryInfo('', $this->mModule->get('mid'));
			foreach ($t_categoryArr as $t_category) {
				$t_eventArr =& notificationEvents($t_category['name'], false, $module->get('mid'));
				foreach ($t_eventArr as $t_event) {
					if (!empty($event['invisible'])) {
						continue;
					}
					$t_optionName = $t_category['title'] . ' : ' . $t_event['title'];
					$t_options[$t_optionName] = $t_category['name'] . '-' . $t_event['name'];
				}
				
				$configInfos[] = array(
					'name' => 'notification_events',
					'title' => '_NOT_CONFIG_EVENTS',
					'description' => '_NOT_CONFIG_EVENTSDSC',
					'formtype' => 'select_multi',
					'valuetype' => 'array',
					'default' => array_values($t_options),
					'options' => $t_options
				);
			}
		}

		$configHandler =& xoops_gethandler('config');

		$count = 0;
		if (is_array($configInfos)) {
			foreach ($configInfos as $configInfo) {
				$config =& $configHandler->createConfig();
	
				$config->setVar('conf_modid', $module->getVar('mid'));
				$config->setVar('conf_catid', 0);
				$config->setVar('conf_name', $configInfo['name']);
				$config->setVar('conf_title', $configInfo['title'], true);
				if (isset($configInfo['description'])) {
					$config->setVar('conf_desc', $configInfo['description'], true);
				}
				$config->setVar('conf_formtype', $configInfo['formtype'], true);
				$config->setVar('conf_valuetype', $configInfo['valuetype'], true);
				$config->setConfValueForInput($configInfo['default'], true);
				$config->setVar('conf_order', $count++);
	
				if (isset($configInfo['options']) && is_array($configInfo['options'])) {
					foreach ($configInfo['options'] as $key => $value) {
						$configOption =& $configHandler->createConfigOption();
						$configOption->setVar('confop_name', $key, true);
						$configOption->setVar('confop_value', $value, true);
						$config->setConfOptions($configOption);
						unset($configOption);
					}
				}
				
				if ($configHandler->insertConfig($config)) {
					$log->addReport(XCube_Utils::formatMessage(_AD_BASE_MESSAGE_INSERT_CONFIG, $configInfo['name']));
				}
				else {
					$log->addError(XCube_Utils::formatMessage(_AD_BASE_ERROR_COULD_NOT_INSERT_CONFIG, $configInfo['name']));
				}
				
				unset($config);
			}
		}
	}

	/**
	 * Delete all configs of $module.
	 *
	 * @param $module XoopsModule
	 */
	function deleteAllConfigs(&$module, &$log)
	{
		if ($this->mModule->getVar('hasconfig') == 0) {
			return;
		}

		$configHandler =& xoops_gethandler('config');
		$configs =& $configHandler->getConfigs(new Criteria('conf_modid', $this->mModule->getVar('mid')));

		if (count($configs) == 0) {
			return;
		}

		foreach ($configs as $config) {
			$configHandler->deleteConfig($config);
		}
	}
}

?>