/** * Upgrade a module. * * @param array $args All parameters passed to this function. * numeric $args['id'] The module ID. * boolean $args['interactive_upgrade'] Whether or not to upgrade in interactive mode. * * @return boolean True on success, false on failure. */ public function upgrade($args) { // Argument check if (!isset($args['id']) || !is_numeric($args['id'])) { return LogUtil::registerArgsError(); } // Get module information $modinfo = ModUtil::getInfo($args['id']); if (empty($modinfo)) { return LogUtil::registerError($this->__('Error! No such module ID exists.')); } switch ($modinfo['state']) { case ModUtil::STATE_NOTALLOWED: return LogUtil::registerError($this->__f('Error! No permission to upgrade %s.', $modinfo['name'])); break; default: if ($modinfo['state'] > 10) { return LogUtil::registerError($this->__f('Error! %s is not compatible with this version of Zikula.', $modinfo['name'])); } } $osdir = DataUtil::formatForOS($modinfo['directory']); ModUtil::dbInfoLoad($modinfo['name'], $osdir); $modpath = $modinfo['type'] == ModUtil::TYPE_SYSTEM ? 'system' : 'modules'; // load module maintainence functions $oomod = ModUtil::isOO($modinfo['name']); if ($oomod) { ZLoader::addAutoloader($osdir, "{$modpath}/{$osdir}/lib"); } $bootstrap = "{$modpath}/{$osdir}/bootstrap.php"; if (file_exists($bootstrap)) { include_once $bootstrap; } if ($modinfo['type'] == ModUtil::TYPE_MODULE) { if (is_dir("modules/{$osdir}/locale")) { ZLanguage::bindModuleDomain($modinfo['name']); } } if (!$oomod && file_exists($file = "{$modpath}/{$osdir}/pninit.php")) { if (!(include_once $file)) { LogUtil::registerError($this->__f("Error! Could not load a required file: '%s'.", $file)); } } if ($oomod) { $className = ucwords($modinfo['name']) . '_Installer'; $reflectionInstaller = new ReflectionClass($className); if (!$reflectionInstaller->isSubclassOf('Zikula_AbstractInstaller')) { LogUtil::registerError($this->__f("%s must be an instance of Zikula_AbstractInstaller", $className)); } $installer = $reflectionInstaller->newInstanceArgs(array($this->serviceManager)); $interactiveClass = ucwords($modinfo['name']) . '_Controller_Interactiveinstaller'; $interactiveController = null; if (class_exists($interactiveClass)) { $reflectionInteractive = new ReflectionClass($interactiveClass); if (!$reflectionInteractive->isSubclassOf('Zikula_Controller_AbstractInteractiveInstaller')) { LogUtil::registerError($this->__f("%s must be an instance of Zikula_Controller_AbstractInteractiveInstaller", $className)); } $interactiveController = $reflectionInteractive->newInstance($this->serviceManager); } } // perform the actual upgrade of the module $func = $oomod ? array($installer, 'upgrade') : $modinfo['name'] . '_upgrade'; $interactive_func = $oomod ? array($interactiveController, 'upgrade') : $modinfo['name'] . '_init_interactiveupgrade'; // allow bypass of interactive upgrade during a new installation only. if (System::isInstalling() && is_callable($interactive_func) && !is_callable($func)) { return; // return void here } if (isset($args['interactive_upgrade']) && $args['interactive_upgrade'] == false && is_callable($interactive_func)) { if (is_array($interactive_func)) { // This must be an OO controller since callable is an array. // Because interactive installers extend the Zikula_AbstractController, is_callable will always return true because of the __call() // so we must check if the method actually exists by reflection - drak if ($reflectionInteractive->hasMethod('upgrade')) { SessionUtil::setVar('interactive_upgrade', true); return call_user_func($interactive_func, array('oldversion' => $modinfo['version'])); } } else { // this is enclosed in the else so that if both conditions fail, execution will pass onto the non-interactive execution below. SessionUtil::setVar('interactive_upgrade', true); return call_user_func($interactive_func, array('oldversion' => $modinfo['version'])); } } // non-interactive if (is_callable($func)) { $result = call_user_func($func, $modinfo['version']); if (is_string($result)) { if ($result != $modinfo['version']) { // update the last successful updated version $modinfo['version'] = $result; $obj = DBUtil::updateObject($modinfo, 'modules', '', 'id', true); } return false; } elseif ($result != true) { return false; } } $modversion['version'] = '0'; $modversion = Extensions_Util::getVersionMeta($osdir, $modpath); $version = $modversion['version']; // Update state of module $result = $this->setState(array('id' => $args['id'], 'state' => ModUtil::STATE_ACTIVE)); if ($result) { LogUtil::registerStatus($this->__("Done! Module has been upgraded. Its status is now 'Active'.")); } else { return false; } // Note the changes in the database... // Get module database info ModUtil::dbInfoLoad('Extensions'); $obj = array('id' => $args['id'], 'version' => $version); DBUtil::updateObject($obj, 'modules'); // legacy to be removed from 1.4 - remove hooks during upgrade since we cannot rely on // module authors to do this - drak if ($oomod) { $tables = DBUtil::getTables(); $hooksCol = $tables['hooks_column']; $where = "{$hooksCol['smodule']} = '{$modinfo['name']}' OR {$hooksCol['tmodule']} = '{$modinfo['name']}'"; $hooks = DBUtil::selectObjectArray('hooks', $where); if ($hooks) { foreach ($hooks as $hook) { DBUtil::deleteObject($hook, 'hooks'); } LogUtil::registerStatus($this->__f("NOTICE! Legacy hook configurations for %s have been removed.", $modinfo['name'])); } } // Upgrade succeeded, issue event. $event = new Zikula_Event('installer.module.upgraded', null, $modinfo); $this->eventManager->notify($event); // Success return true; }
/** * Initialise a module. * * @param int 'id' module id * @return bool true */ public function initialise() { $csrftoken = FormUtil::getPassedValue('csrftoken'); $this->checkCsrfToken($csrftoken); // Get parameters from whatever input we need $id = (int) FormUtil::getPassedValue('id', 0); $objectid = (int) FormUtil::getPassedValue('objectid', 0); $confirmation = (bool) FormUtil::getPassedValue('confirmation', false); $startnum = (int) FormUtil::getPassedValue('startnum'); $letter = FormUtil::getPassedValue('letter'); $state = (int)FormUtil::getPassedValue('state'); if ($objectid) { $id = $objectid; } // assign any dependencies - filtering out non-active module dependents // when getting here without a valid id we are in interactive init mode and then // the dependencies checks have been done before already $fataldependency = false; if ($id != 0) { $dependencies = ModUtil::apiFunc('Extensions', 'admin', 'getdependencies', array('modid' => $id)); $modulenotfound = false; if (!$confirmation && $dependencies) { foreach ($dependencies as $key => $dependency) { $dependencies[$key]['insystem'] = true; $modinfo = ModUtil::getInfoFromName($dependency['modname']); $base = ($modinfo['type'] == ModUtil::TYPE_MODULE) ? 'modules' : 'system'; if (is_dir("$base/$dependency[modname]")) { $minok = 0; $maxok = 0; $modversion = Extensions_Util::getVersionMeta($dependency['modname'], $base); if (!empty($dependency['minversion'])) { $minok = version_compare($modversion['version'], $dependency['minversion']); } if (!empty($dependency['maxversion'])) { $maxok = version_compare($dependency['maxversion'], $modversion['version']); } if ($minok == -1 || $maxok == -1) { if ($dependency['status'] == ModUtil::DEPENDENCY_REQUIRED) { $fataldependency = true; } else { unset($dependencies[$key]); } } else { $dependencies[$key] = array_merge($dependencies[$key], $modinfo); // if this module is already installed, don't display it in the list of dependencies. if (isset($dependencies[$key]['state']) && ($dependencies[$key]['state'] > ModUtil::STATE_UNINITIALISED && $dependencies[$key]['state'] < ModUtil::STATE_NOTALLOWED)) { unset($dependencies[$key]); } } } elseif (!empty($modinfo)) { $dependencies[$key] = array_merge($dependencies[$key], $modinfo); } else { $dependencies[$key]['insystem'] = false; $modulenotfound = true; if ($dependency['status'] == ModUtil::DEPENDENCY_REQUIRED) { $fataldependency = true; } } } $this->view->assign('fataldependency', $fataldependency); // we have some dependencies so let's warn the user about these if (!empty($dependencies)) { return $this->view->assign('id', $id) ->assign('dependencies', $dependencies) ->assign('modulenotfound', $modulenotfound) ->fetch('extensions_admin_initialise.tpl'); } } else { $dependencies = (array)$this->request->request->get('dependencies', array()); } } $interactive_init = SessionUtil::getVar('interactive_init'); $interactive_init = (empty($interactive_init)) ? false : true; if ($interactive_init == false) { SessionUtil::setVar('modules_id', $id); SessionUtil::setVar('modules_startnum', $startnum); SessionUtil::setVar('modules_letter', $letter); SessionUtil::setVar('modules_state', $state); $activate = false; } else { $id = SessionUtil::getVar('modules_id'); $startnum = SessionUtil::getVar('modules_startnum'); $letter = SessionUtil::getVar('modules_letter'); $state = SessionUtil::getVar('modules_state'); $activate = (bool) FormUtil::getPassedValue('activate'); } if (empty($id) || !is_numeric($id)) { return LogUtil::registerError($this->__('Error! No module ID provided.'), 404, ModUtil::url('Extensions', 'admin', 'view')); } // initialise and activate any dependencies if (isset($dependencies) && is_array($dependencies)) { foreach ($dependencies as $dependency) { if (!ModUtil::apiFunc('Extensions', 'admin', 'initialise', array('id' => $dependency))) { $this->redirect(ModUtil::url('Extensions', 'admin', 'view', array( 'startnum' => $startnum, 'letter' => $letter, 'state' => $state))); } if (!ModUtil::apiFunc('Extensions', 'admin', 'setstate', array('id' => $dependency, 'state' => ModUtil::STATE_ACTIVE))) { $this->redirect(ModUtil::url('Extensions', 'admin', 'view', array( 'startnum' => $startnum, 'letter' => $letter, 'state' => $state))); } } } // Now we've initialised the dependencies initialise the main module $res = ModUtil::apiFunc('Extensions', 'admin', 'initialise', array('id' => $id, 'interactive_init' => $interactive_init)); if (is_bool($res) && $res == true) { // Success SessionUtil::delVar('modules_id'); SessionUtil::delVar('modules_startnum'); SessionUtil::delVar('modules_letter'); SessionUtil::delVar('modules_state'); SessionUtil::delVar('interactive_init'); LogUtil::registerStatus($this->__('Done! Installed module.')); if ($activate == true) { if (ModUtil::apiFunc('Extensions', 'admin', 'setstate', array('id' => $id, 'state' => ModUtil::STATE_ACTIVE))) { // Success LogUtil::registerStatus($this->__('Done! Activated module.')); } } $this->redirect(ModUtil::url('Extensions', 'admin', 'view', array('startnum' => $startnum, 'letter' => $letter, 'state' => $state))); } elseif (is_bool($res)) { $this->redirect(ModUtil::url('Extensions', 'admin', 'view', array('startnum' => $startnum, 'letter' => $letter, 'state' => $state))); } else { return $res; } }