<?php

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

/**
 * This class is collection of static utility functions for module installation.
 * These functions are useful for Legacy modules' system-fixed-installer and
 * modules' custom-installer. All functions for the custom-installer are added
 * notes as "FOR THE CUSTOM-ISNTALLER".
 * 
 * For more attentions, see base classes for the custom-installer.
 * 
 * @see Legacy_PhasedUpgrader
 */
class Legacy_ModuleInstallUtils
{
	/**
	 * Executes SQL file which xoops_version of $module specifies. This
	 * function is usefull for installers, but it's impossible to control
	 * for detail.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @note FOR THE CUSTOM-INSTALLER
	 */
	function installSQLAutomatically(&$module, &$log)
	{
		$sqlfileInfo =& $module->getInfo('sqlfile');
		$dirname = $module->getVar('dirname');

		if (!isset($sqlfileInfo[XOOPS_DB_TYPE])) {
			return;
		}
		
		require_once XOOPS_MODULE_PATH . "/legacy/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_LEGACY_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_LEGACY_MESSAGE_DATABASE_SETUP_FINISHED);
	}
	
	/**
	 * Installs all of module templates $module specify. This function is
	 * usefull for installer and updater. In the case of updater, you should
	 * uninstall all of module templates before this function.
	 * 
	 * This function gets informations about templates from xoops_version.
	 * 
	 * @section Attention
	 * 
	 * This function depends the specific spec of Legacy_RenderSystem, but this
	 * static function is needed by the 2nd installer of Legacy System.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @note FOR THE CUSTOM-INSTALLER
	 * @see Legacy_ModuleInstallUtils::uninstallAllOfModuleTemplates()
	 */	
	function installAllOfModuleTemplates(&$module, &$log)
	{
        $templates = $module->getInfo('templates');
        if ($templates != false) {
            foreach ($templates as $template) {
                Legacy_ModuleInstallUtils::installModuleTemplate($module, $template, $log);
            }
        }
	}
	
	/**
	 * Inserts the specified template to DB.
	 * 
	 * @section Attention
	 * 
	 * This function depends the specific spec of Legacy_RenderSystem, but this
	 * static function is needed by the 2nd installer of Legacy System.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param string[][] $template
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @return bool
	 * 
	 * @note This is not usefull a litte for custom-installers.
	 * @todo We'll need the way to specify the template by identity or others.
	 */
	function installModuleTemplate($module, $template, &$log)
	{
		$tplHandler =& xoops_gethandler('tplfile');

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

		$tpldata = Legacy_ModuleInstallUtils::readTemplateFile($module->get('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_LEGACY_MESSAGE_TEMPLATE_INSTALLED, $fileName));
		}
		else {
			$log->addError(XCube_Utils::formatMessage(_AD_LEGACY_ERROR_COULD_NOT_INSTALL_TEMPLATE, $fileName));
			return false;
		}
	}

	/**
	 * Uninstalls all of module templates $module specify. This function is
	 * usefull for uninstaller and updater. In the case of update, you should
	 * call this function before installAllOfModuleTemplates(). In the case of
	 * uninstall, you must set 'false' to $defaultOnly.
	 * 
	 * This function gets informations about templates from the database.
	 * 
	 * @section Attention
	 * 
	 * This function depends the specific spec of Legacy_RenderSystem, but this
	 * static function is needed by the 2nd installer of Legacy System.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @param bool $defaultOnly Indicates whether this function deletes templates from all of tplsets.
	 * @note FOR THE CUSTOM-INSTALLER
	 * @see Legacy_ModuleInstallUtils::installAllOfModuleTemplates()
	 */	
	function uninstallAllOfModuleTemplates(&$module, &$log, $defaultOnly = true)
	{
		$tplHandler =& xoops_gethandler('tplfile');

		//
		// The following processing depends on the structure of Legacy_RenderSystem.
		//
		$tplHandler =& xoops_gethandler('tplfile');
		$delTemplates = null;
		
		if ($defaultOnly) {
			$delTemplates =& $tplHandler->find('default', 'module', $module->get('mid'));
		}
		else {
			$delTemplates =& $tplHandler->find(null, 'module', $module->get('mid'));
		}
		
		if (is_array($delTemplates) && count($delTemplates) > 0) {
			//
			// clear cache
			//
			$xoopsTpl =& new XoopsTpl();
			$xoopsTpl->clear_cache(null, "mod_" . $module->get('dirname'));
			
			foreach ($delTemplates as $tpl) {
				if (!$tplHandler->delete($tpl)) {
					$log->addError(XCube_Utils::formatMessage(_AD_LEGACY_ERROR_TEMPLATE_UNINSTALLED, $tpl->get('tpl_file')));
				}
			}
		}
	}
	
	/**
	 * Installs all of blocks $module specify.
	 * 
	 * This function gets informations about blocks from xoops_version.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @note FOR THE CUSTOM-INSTALLER
	 * @see Legacy_ModuleInstallUtils::uninstallAllOfBlocks()
	 */	
	function installAllOfBlocks(&$module, &$log)
	{
		$definedBlocks = $module->getInfo('blocks');
		if($definedBlocks == false) {
			return true;
		}
		
		$handler =& xoops_gethandler('block');

		$func_num = 0;
		foreach ($definedBlocks as $block) {
			$func_num++;
			$newBlock =& Legacy_ModuleInstallUtils::createBlockByInfo($module, $block, $func_num);
			Legacy_ModuleInstallUtils::installBlock($module, $newBlock, $block, $this->mLog);
        }
	}

	/**
	 * Uninstalls all of blocks which $module specifies, and its permissions.
	 * 
	 * This function gets informations about templates from the database.
	 * 
	 * @static
	 * @param XoopsModule $module
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @return bool
	 * 
	 * @note FOR THE CUSTOM-INSTALLER
	 * @see Legacy_ModuleInstallUtils::installAllOfBlocks()
	 * @see Legacy_ModuleInstallUtils::uninstallBlock()
	 */	
	function uninstallAllOfBlocks(&$module, &$log)
	{
		$handler =& xoops_gethandler('block');
		$criteria = new Criteria('mid', $module->get('mid'));

		$blockArr =& $handler->getObjectsDirectly($criteria);
		
		$successFlag = true;
		
		foreach (array_keys($blockArr) as $idx) {
			$successFlag &= Legacy_ModuleInstallUtils::uninstallBlock($blockArr[$idx], $log);
		}
		
		return $successFlag;
	}
	
	/**
	 * 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, $func_num)
	{
		$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->set('mid', $module->getVar('mid'));
		$blockObj->set('options', $options);
		$blockObj->set('name', $block['name']);
		$blockObj->set('title', $block['name']);
		$blockObj->set('block_type', 'M');
		$blockObj->set('c_type', 1);
		$blockObj->set('isactive', 1);
		$blockObj->set('dirname', $module->getVar('dirname'));
		$blockObj->set('func_file', $block['file']);
		
		//
		// IMPORTANT CONVENTION
		//
		$show_func = "";
		if (isset($block['class'])) {
			$show_func = "cl::" . $block['class'];
		}
		else {
			$show_func = $block['show_func'];
		}
		
		$blockObj->set('show_func', $show_func);
		$blockObj->set('edit_func', $edit_func);
		$blockObj->set('template', $template);
		$blockObj->set('last_modified', time());
		$blockObj->set('visible', $visible);
		
		$func_num = isset($block['func_num']) ? intval($block['func_num']) : $func_num;
		$blockObj->set('func_num', $func_num);

		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_LEGACY_ERROR_COULD_NOT_INSTALL_BLOCK, $blockObj->getVar('name')));

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

			$tplHandler =& xoops_gethandler('tplfile');

			if (!Legacy_ModuleInstallUtils::installAllOfBlockTemplates($module, $blockObj)) {
				$log->addError(XCube_Utils::formatMessage(_AD_LEGACY_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_LEGACY_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_LEGACY_ERROR_COULD_NOT_SET_BLOCK_PERMISSION, $blockObj->getVar('name')));
        				}
        			}
				} else {
				    $root =& XCube_Root::getSingleton();
                    $groups = $root->mContext->mXoopsUser->getGroups();
                    foreach ($groups as $mygroup) {
        				$bperm->setVar('gperm_groupid', $mygroup);
        				$bperm->setNew();
        				if (!$gpermHandler->insert($bperm)) {
        					$log->addWarn(XCube_Utils::formatMessage(_AD_LEGACY_ERROR_COULD_NOT_SET_BLOCK_PERMISSION, $blockObj->getVar('name')));
    				    }
    				}
				}
			}

			return true;
		}
	}
	
	/**
	 * Uninstalls a block which $block specifies. In the same time, deletes
	 * permissions for the block.
	 * 
	 * @param XoopsBlock $block
	 * @param Legacy_ModuleUtilsSimpleLog $log
	 * @note FOR THE CUSTOM-INSTALLER
	 * 
	 * @todo error handling & delete the block's template.
	 */
	function uninstallBlock(&$block, &$log)
	{
		$blockHandler =& xoops_gethandler('block');
		$blockHandler->delete($block);
		$log->addReport(XCube_Utils::formatMessage(_AD_LEGACY_MESSAGE_UNINSTALLATION_BLOCK_SUCCESSFUL, $block->get('name')));
		
		//
		// Deletes permissions
		//
		$gpermHandler =& xoops_gethandler('groupperm');
		$criteria =& new CriteriaCompo();
		$criteria->add(new Criteria('gperm_name', 'block_read'));
		$criteria->add(new Criteria('gperm_itemid', $block->get('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 installAllOfBlockTemplates(&$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_ModuleInstallUtils::readTemplateFile($module->getVar('dirname'), $block->getVar('template'), true);
		$tplfile->setVar('tpl_source', $tplSource);
		$tplfile->setVar('tpl_lastmodified', time());

		return $tplHandler->insert($tplfile);
	}
	
	/**
	 * Read template file, return it.
	 * 
	 * @note This is must, but it depends on ...
	 */
	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;
	}

	function installAllOfConfigs(&$module, &$log)
	{
		$configInfos = Legacy_ModuleInstallUtils::getConfigInfosFromManifesto($module);

		$count = 0;
		if (is_array($configInfos)) {
			$configHandler =& xoops_gethandler('config');
			
			foreach ($configInfos as $configInfo) {
				$config =& $configHandler->createConfig();
				
				$config->loadFromConfigInfo($module->get('mid'), $configInfo, $count++);
				
				if ($configHandler->insertConfig($config)) {
					$log->addReport(XCube_Utils::formatMessage(_AD_LEGACY_MESSAGE_INSERT_CONFIG, $configInfo['name']));
				}
				else {
					$log->addError(XCube_Utils::formatMessage(_AD_LEGACY_ERROR_COULD_NOT_INSERT_CONFIG, $configInfo['name']));
				}
				
				unset($config);
			}
		}
	}
	
	/**
	 * Get & build config items from Manifesto by specific module object.
	 */	
	function &getConfigInfosFromManifesto(&$module)
	{
		$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 ($module->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('', $module->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
			);
		}
		
		return $configInfos;
	}
	
	/**
	 * Delete all configs of $module.
	 *
	 * @param $module XoopsModule
	 */
	function uninstallAllOfConfigs(&$module, &$log)
	{
		if ($module->get('hasconfig') == 0) {
			return;
		}

		$configHandler =& xoops_gethandler('config');
		$configs =& $configHandler->getConfigs(new Criteria('conf_modid', $module->get('mid')));

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

		foreach ($configs as $config) {
			$configHandler->deleteConfig($config);
		}
	}
	
	/**
	 * Executes SQL query as cube style.
	 */
	function DBquery($query, &$module, $log)
	{
		require_once XOOPS_MODULE_PATH . "/legacy/admin/class/Legacy_SQLScanner.class.php";
		
		$successFlag = true;
		
		$scanner =& new Legacy_CubeStyleSQLScanner();
		$scanner->setDB_PREFIX(XOOPS_DB_PREFIX);
		$scanner->setDirname($module->get('dirname'));
		$scanner->setBuffer($query);
		$scanner->parse();
		$sqlArr = $scanner->getSQL();

		$root =& XCube_Root::getSingleton();
		
		foreach ($sqlArr as $sql) {		
			if ($root->mController->mDB->query($sql)) {
				$log->addReport("Success: ${sql}");
				$successFlag &= true;
			}
			else {
				$log->addError("Failure: ${sql}");
				$successFlag = false;
			}
		}
		
		return $successFlag;
	}
}

?>