<?php

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

require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/BeanFactory.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/Enum.class.php';
require_once XOONIPS_TRUST_PATH . '/admin/class/installer/XoonipsInstallUtils.class.php';
require_once XOONIPS_TRUST_PATH . '/class/DelegateFunctions.class.php';
require_once XOONIPS_TRUST_PATH . '/include/common.inc.php';

/**
 * Xoonips_Installer
**/
class Xoonips_Installer {
    /**
     * @brief   Legacy_ModuleInstallLog
    **/
    public $mLog = null;

    /**
     * @brief   bool
    **/
    private $_mForceMode = false;

    /**
     * @brief   XoopsModule
    **/
    private $_mXoopsModule = null;

    /**
     * __construct
     *
     * @param   void
     *
     * @return  void
    **/
    public function __construct() {
        $this->mLog = new Legacy_ModuleInstallLog();
    }

    /**
     * setCurrentXoopsModule
     *
     * @param   XoopsModule  &$xoopsModule
     *
     * @return  void
    **/
    public function setCurrentXoopsModule(/*** XoopsModule ***/ &$xoopsModule) {
        $this->_mXoopsModule =& $xoopsModule;
    }

    /**
     * setForceMode
     *
     * @param   bool  $isForceMode
     *
     * @return  void
    **/
    public function setForceMode(/*** bool ***/ $isForceMode) {
        $this->_mForceMode = $isForceMode;
    }

    /**
     * _installTables
     *
     * @param   void
     *
     * @return  bool
    **/
    private function _installTables() {
        if (!Xoonips_InstallUtils::installSQLAutomatically($this->_mXoopsModule, $this->mLog)) {
			return false;
		}
        if (!Xoonips_InstallUtils::installDataAutomatically($this->_mXoopsModule, $this->mLog)) {
			return false;
		}
		return true;
    }

    /**
     * _installModule
     *
     * @param   void
     *
     * @return  bool
    **/
    private function _installModule() {
        $moduleHandler = &xoops_gethandler('module');
        if (!$moduleHandler->insert($this->_mXoopsModule)) {
            $this->mLog->addError(_MI_XOONIPS_INSTALL_ERROR_MODULE_INSTALLED);
            return false;
        }

        $gpermHandler = &xoops_gethandler('groupperm');

        if ($this->_mXoopsModule->getInfo('hasAdmin')) {
            $adminPerm =& $this->_createPermission(XOOPS_GROUP_ADMIN);
            $adminPerm->setVar('gperm_name', 'module_admin');
            if (!$gpermHandler->insert($adminPerm)) {
                $this->mLog->addError(_MI_XOONIPS_INSTALL_ERROR_PERM_ADMIN_SET);
            }
        }

        if ($this->_mXoopsModule->getInfo('hasMain')) {
            if ($this->_mXoopsModule->getInfo('read_any')) {
                $memberHandler = &xoops_gethandler('member');
                $groupObjects =& $memberHandler->getGroups();
                foreach ($groupObjects as $group) {
                    $readPerm =& $this->_createPermission($group->getVar('groupid'));
                    $readPerm->setVar('gperm_name','module_read');
                    if(!$gpermHandler->insert($readPerm)) {
                        $this->mLog->addError(_MI_XOONIPS_INSTALL_ERROR_PERM_READ_SET);
                    }
                }
            } else {
                $root =& XCube_Root::getSingleton();
                $groups = $root->mContext->mXoopsUser->getGroups(new Criteria('group_type', Xoonips_Enum::GROUP_TYPE, '<>'));
                foreach ($groups as $group) {
                    $readPerm =& $this->_createPermission($group);
                    $readPerm->setVar('gperm_name', 'module_read');
                    if (!$gpermHandler->insert($readPerm)) {
                        $this->mLog->addError(_MI_XOONIPS_INSTALL_ERROR_PERM_READ_SET);
                    }
                }
            }
        }
        return true;
    }

    /**
     * &_createPermission
     *
     * @param   int  $group
     *
     * @return  XoopsGroupPerm
    **/
    private function &_createPermission(/*** int ***/ $group) {
        $gpermHandler = &xoops_gethandler('groupperm');
        $perm =& $gpermHandler->create();
        $perm->setVar('gperm_groupid', $group);
        $perm->setVar('gperm_itemid', $this->_mXoopsModule->getVar('mid'));
        $perm->setVar('gperm_modid', 1);
        return $perm;
    }

    /**
     * _installTemplates
     *
     * @param   void
     *
     * @return  void
    **/
    private function _installTemplates() {
        Xoonips_InstallUtils::installAllOfModuleTemplates(
            $this->_mXoopsModule,
            $this->mLog
        );
        Xoonips_InstallUtils::installCommonTemplates(
            $this->_mXoopsModule,
            $this->mLog
        );
    }

    /**
     * _installBlocks
     *
     * @param   void
     *
     * @return  void
    **/
    private function _installBlocks() {
        Xoonips_InstallUtils::installAllOfBlocks(
            $this->_mXoopsModule,
            $this->mLog
        );
    }

    /**
     * _installPreferences
     *
     * @param   void
     *
     * @return  void
    **/
    private function _installPreferences() {
        Xoonips_InstallUtils::installAllOfConfigs(
            $this->_mXoopsModule,
            $this->mLog
        );
    }

    /**
     * _processReport
     *
     * @param   void
     *
     * @return  void
    **/
    private function _processReport() {
        if (!$this->mLog->hasError()) {
            $this->mLog->add(
                XCube_Utils::formatString(
                    _MI_XOONIPS_INSTALL_MSG_MODULE_INSTALLED,
                    $this->_mXoopsModule->getInfo('name')
                )
            );
        } else if (is_object($this->_mXoopsModule)) {
            $this->mLog->addError(
                XCube_Utils::formatString(
                    _MI_XOONIPS_INSTALL_ERROR_MODULE_INSTALLED,
                    $this->_mXoopsModule->getInfo('name')
                )
            );
        } else {
            $this->mLog->addError(
                XCube_Utils::formatString(
                    _MI_XOONIPS_INSTALL_ERROR_MODULE_INSTALLED,
                    'something'
                )
            );
        }
    }

	function _processScript() {
		$result = $this->moduleInstall($this->_mXoopsModule);
		if (!$result) {
            $this->mLog->addError(
                XCube_Utils::formatString(
                    _MI_XOONIPS_INSTALL_ERROR_MODULE_INSTALLED,
                    $this->_mXoopsModule->getInfo('name')
                )
            );
		}
    }

    /**
     * executeInstall
     *
     * @param   void
     *
     * @return  bool
    **/
    public function executeInstall() {
    	set_time_limit(240);
        $this->_installTables();
        if (!$this->_mForceMode && $this->mLog->hasError()) {
            $this->_processReport();
            return false;
        }

        $this->_installModule();
        if (!$this->_mForceMode && $this->mLog->hasError()) {
            $this->_processReport();
            return false;
        }

        $this->_installTemplates();
        if (!$this->_mForceMode && $this->mLog->hasError()) {
            $this->_processReport();
            return false;
        }

        $this->_installBlocks();
        if (!$this->_mForceMode && $this->mLog->hasError()) {
            $this->_processReport();
            return false;
        }

        $this->_installPreferences();
        if (!$this->_mForceMode && $this->mLog->hasError()) {
            $this->_processReport();
            return false;
        }

    	$this->_processScript();
		if (!$this->_mForceMode && $this->mLog->hasError()) {
			$this->_processReport();
			return false;
		}

        $this->_processReport();
        return true;
    }

	private function moduleInstall($xoopsMod) {
		$mydirname = $xoopsMod->getVar('dirname');
		$uid = $GLOBALS['xoopsUser']->getVar('uid', 'n');
		$mid = $xoopsMod->getVar('mid', 'n');

		// fix invalid group permissions
		if (!Xoonips_InstallUtils::fixGroupPermissions()) {
			return false;
		}

		// define groups
		$member_handler =& xoops_gethandler('member');
		$groups = $member_handler->getGroupList();
		$gids = array_keys($groups);

		// get moderator of xleprogress
		$mgid_arr = array();
		if (Xoonips_InstallUtils::chkXleprogress()) {
			foreach ($groups as $id => $val) {
				if ($val == 'moderator') {
					$mgid_arr[] = $id;
					Xoonips_InstallUtils::setAdminRight($mid, $id);
				}
			}
		}
		
		$ogids = array_diff($gids, array(XOOPS_GROUP_ADMIN, XOOPS_GROUP_USERS, XOOPS_GROUP_ANONYMOUS), $mgid_arr);
		
		// set module access permission to all known groups
		foreach ($gids as $gid) {
			$right = in_array($gid, $ogids) ? false : true;
			Xoonips_InstallUtils::setModuleReadRight($mid, $gid, $right);
		}

		// set block parameters (read permissions and positions)
		// php-indent: disable
		$block_params = array(
			'b_xoonips_quick_search_show' => array(
				'rights' => array(true, true, true, false),
				'positions' => array(true, 0, 10, true)
			),
			'b_xoonips_tree_show' => array(
				'rights' => array(true, true, true, false),
				'positions' => array(true, 0, 20, true)
			),
			'b_xoonips_login_show' => array(
				'rights' => array(true, true, true, false),
				'positions' => array(true, 0, 0, true)
			),
			'b_xoonips_user_show' => array(
				'rights' => array(true, false, true, false),
				'positions' => array(true, 1, 0, true)
			),
			'b_xoonips_itemtypes_show' => array(
				'rights' => array(true, true, true, false),
				'positions' => array(true, 5, 20, false)
			)
		);
		// php-indent: enable
		foreach ($block_params as $show_func => $block_param) {
			$bids = Xoonips_InstallUtils::getBlockIds($mid, $show_func);
			foreach ($bids as $bid) {
				// - rights
				$rights = $block_param['rights'];
				list($uright, $gright, $mright, $oright) = $block_param['rights'];
				Xoonips_InstallUtils::setBlockReadRight($bid, XOOPS_GROUP_USERS, $uright);
				Xoonips_InstallUtils::setBlockReadRight($bid, XOOPS_GROUP_ANONYMOUS, $gright);
				if (Xoonips_InstallUtils::chkXleprogress() && count($mgid_arr) > 0) {
					foreach ($mgid_arr as $mgid) {
						Xoonips_InstallUtils::setBlockReadRight($bid, $mgid, $mright);
					}
				}
				foreach ($ogids as $gid) {
					Xoonips_InstallUtils::setBlockReadRight($bid, $gid, $oright);
				}
				// - positions
				list($visible, $side, $weight, $allpage) = $block_param['positions'];
				Xoonips_InstallUtils::setBlockPosition($bid, $visible, $side, $weight);
				Xoonips_InstallUtils::setBlockShowPage($bid, 0, $allpage);
				if ($allpage) {
					// unset top page
					Xoonips_InstallUtils::setBlockShowPage($bid, - 1, false);
				} else {
					Xoonips_InstallUtils::setBlockShowPage($bid, - 1, true);
				}
			}
		}

		// hide 'user' and 'login' blocks
		if (Xoonips_BeanFactory::chkUserBean()) {
			$sys_blocks = array();
			// php-indent: disable
			$sys_blocks[] = array('system', 'b_system_user_show');
			$sys_blocks[] = array('system', 'b_system_login_show');
			// php-indent: enable
			if (defined('XOOPS_CUBE_LEGACY')) {
				// for XOOPS Cube Legacy 2.2
				// php-indent: disable
				$sys_blocks[] = array('legacy', 'b_legacy_usermenu_show');
				$sys_blocks[] = array('user', 'b_user_login_show');
				// php-indent: enable
			}
			foreach ($sys_blocks as $sys_block) {
				list($dirname, $show_func) = $sys_block;
				$sysmid = Xoonips_InstallUtils::getModuleId($dirname);
				if ($sysmid === false) {
					// this case will occur when system module does not installed on
					// XOOPS Cube Legacy 2.1
					continue;
				}
				$bids = Xoonips_InstallUtils::getBlockIds($sysmid, $show_func);
				foreach ($bids as $bid) {
					Xoonips_InstallUtils::setBlockPosition($bid, false, 0, 0);
				}
			}
		}
		
		// omit guest from mainmenu of legacy
		if (defined('XOOPS_CUBE_LEGACY')) {
			$sysmid = Xoonips_InstallUtils::getModuleId('legacy');
			if ($sysmid === false) continue;
			$bids = Xoonips_InstallUtils::getBlockIds($sysmid, 'b_legacy_mainmenu_show');
			foreach ($bids as $bid) {
				Xoonips_InstallUtils::setBlockReadRight($bid, XOOPS_GROUP_ANONYMOUS, false);
			}
		}

		// register my xoonips user information
		if (!Xoonips_InstallUtils::pickupXoopsUser($uid, Xoonips_Enum::USER_CERTIFIED, $mydirname, true)) {
			return false;
		}
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);

		foreach ($userBean->getAllUsers() as $userInfo) {
			if ($userInfo['uid'] != $uid) {
				$activate = $userInfo['level'];
				if ($activate > Xoonips_Enum::USER_CERTIFIED) {
					$activate = Xoonips_Enum::USER_CERTIFIED;
				}
				if (!Xoonips_InstallUtils::pickupXoopsUser($userInfo['uid'], $activate, $mydirname, false)) {
					return false;
				}
			}
		}

		$group_handler =& xoops_gethandler('group');
		$groupbean = Xoonips_BeanFactory::getBean('GroupsBean', XCUBE_CORE_USER_MODULE_NAME);

		$linkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', XCUBE_CORE_USER_MODULE_NAME);
		if (!defined('XOONIPS_TRUST_DIRNAME')) {
			define('XOONIPS_TRUST_DIRNAME', $xoopsMod->modinfo['trust_dirname']);
		}
		foreach ($groupbean->getGroups(Xoonips_Enum::GROUP_TYPE) as $group) {
			$xoopsGroup = $group_handler->get($group['groupid']);
			Xoonips_DelegateFunctions::groupCertify($xoopsGroup);
			foreach ($linkbean->getGroupUserLinkInfoByGroupId($group['groupid']) as $link) {
				if ($link['activate'] == Xoonips_Enum::GRP_US_CERTIFIED) {
					Xoonips_DelegateFunctions::groupMemberJoin(new XoopsUser($link['uid']), $xoopsGroup);
				} elseif ($link['activate'] == Xoonips_Enum::GRP_US_JOIN_REQUIRED) {
					Xoonips_DelegateFunctions::groupMemberJoinRequest(new XoopsUser($link['uid']), $xoopsGroup);
				} elseif ($link['activate'] == Xoonips_Enum::GRP_US_LEAVE_REQUIRED) {
					Xoonips_DelegateFunctions::groupMemberJoin(new XoopsUser($link['uid']), $xoopsGroup);
					Xoonips_DelegateFunctions::groupMemberLeaveRequest(new XoopsUser($link['uid']), $xoopsGroup);
				}
			}
		}

		// set notifications
		$uids = array_keys($member_handler->getUsers(null, true));
		// php-indent: disable
		$info = $xoopsMod->getInfo('notification');
		$notifications = array();
		foreach ($info['category'] as $category) {
			$events = array();
			foreach ($info['event'] as $event) {
				if ($event['category'] == $category['name']) {
					$events[] = $event['name'];
				}
			}
			$notifications[$category['name']] = $events;
		}

		// php-indent: enable
		foreach ($notifications as $category => $events) {
			foreach ($events as $event) {
				// enable event
				Xoonips_InstallUtils::enableNotification($mid, $category, $event);
				// subscribe all notifications to all users
				foreach ($uids as $uid) {
					Xoonips_InstallUtils::subscribeNotification($mid, $uid, $category, $event);
				}
			}
		}
		return true;
	}
}

