/** * 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; }
/** * Load a block. * * @param string $modname Module name. * @param string $block Name of the block. * * @throws LogicException Uf OO-Block is not a Zikula_Controller_AbstractBlock object. * @return bool True on successful load, false otherwise. */ public static function load($modname, $block) { $sm = ServiceUtil::getManager(); $modinfo = ModUtil::getInfoFromName($modname); $serviceId = strtolower('block.' . $modinfo['name'] . '_' . 'Block_' . $block); if ($sm->hasService($serviceId)) { return $sm->getService($serviceId); } if ($modinfo['type'] == ModUtil::TYPE_MODULE) { ZLanguage::bindModuleDomain($modinfo['name']); } $basedir = ($modinfo['type'] == ModUtil::TYPE_SYSTEM) ? 'system' : 'modules'; $moddir = DataUtil::formatForOS($modinfo['directory']); $blockdir = "$basedir/$moddir/lib/$moddir/Block"; $ooblock = "$blockdir/" . ucwords($block) . '.php'; ModUtil::load($modname); $isOO = ModUtil::isOO($modname); if (!$isOO) { $blockdirOld = $moddir . '/pnblocks'; $incfile = DataUtil::formatForOS($block . '.php'); if (file_exists("$basedir/$blockdirOld/$incfile")) { include_once "$basedir/$blockdirOld/$incfile"; } else { return false; } } // get the block info if ($isOO) { $className = ucwords($modinfo['name']) . '_' . 'Block_' . ucwords($block); $r = new ReflectionClass($className); $blockInstance = $r->newInstanceArgs(array($sm)); try { if (!$blockInstance instanceof Zikula_Controller_AbstractBlock) { throw new LogicException(sprintf('Block %s must inherit from Zikula_Controller_AbstractBlock', $className)); } } catch (LogicException $e) { if (System::isDevelopmentMode()) { throw $e; } else { LogUtil::registerError('A fatal error has occured which can be viewed only in development mode.', 500); return false; } } $sm->attachService($serviceId, $blockInstance); } $result = ($isOO ? $blockInstance : true); if ($isOO) { $blocks_modules[$block] = call_user_func(array($blockInstance, 'info')); } else { $infofunc = "{$modname}_{$block}block_info"; $blocks_modules[$block] = $infofunc(); } // set the module and keys for the new block $blocks_modules[$block]['bkey'] = $block; $blocks_modules[$block]['module'] = $modname; $blocks_modules[$block]['mid'] = ModUtil::getIdFromName($modname); // merge the blockinfo in the global list of blocks if (!isset($GLOBALS['blocks_modules'])) { $GLOBALS['blocks_modules'] = array(); } $GLOBALS['blocks_modules'][$blocks_modules[$block]['mid']][$block] = $blocks_modules[$block]; // Initialise block if required (new-style) if ($isOO) { call_user_func(array($blockInstance, 'init')); } else { $initfunc = "{$modname}_{$block}block_init"; $initfunc(); } // add stylesheet to the page vars, this makes manual loading obsolete PageUtil::addVar('stylesheet', ThemeUtil::getModuleStylesheet($modname)); return $result; }
/** * Extensions_admin_view - list modules and current settings * @return string HTML output string */ public function view() { // Security check if (!SecurityUtil::checkPermission('Extensions::', '::', ACCESS_ADMIN)) { return LogUtil::registerPermissionError(); } // Get parameters from whatever input we need. $modinfo = $this->getModInfo(); $startnum = (int) FormUtil::getPassedValue('startnum', null, 'GET'); $letter = FormUtil::getPassedValue('letter', null, 'GET'); $state = FormUtil::getPassedValue('state', (!strstr(System::serverGetVar('HTTP_REFERER'), 'module='.$modinfo['url'])) ? null : SessionUtil::getVar('state', null), 'GETPOST'); $sort = FormUtil::getPassedValue('sort', (!strstr(System::serverGetVar('HTTP_REFERER'), 'module='.$modinfo['url'])) ? null : SessionUtil::getVar('sort', null), 'GET'); $sortdir = FormUtil::getPassedValue('sortdir', (!strstr(System::serverGetVar('HTTP_REFERER'), 'module='.$modinfo['url'])) ? null : SessionUtil::getVar('sortdir', null), 'GET'); // parameter for used sort order if ($sort != 'name' && $sort != 'displayname') $sort = 'name'; if ($sortdir != 'ASC' && $sortdir != 'DESC') $sortdir = 'ASC'; // save the current values SessionUtil::setVar('state', $state); SessionUtil::setVar('sort', $sort); SessionUtil::setVar('sortdir', $sortdir); // do some clean up SessionUtil::delVar('interactive_init'); SessionUtil::delVar('interactive_remove'); SessionUtil::delVar('interactive_upgrade'); if ($this->serviceManager['multisites.enabled'] != 1 || ($this->serviceManager['multisites.mainsiteurl'] == FormUtil::getPassedValue('sitedns', null, 'GET') && $this->serviceManager['multisites.based_on_domains'] == 0) || ($this->serviceManager['multisites.mainsiteurl'] == $_SERVER['HTTP_HOST'] && $this->serviceManager['multisites.based_on_domains'] == 1)) { // always regenerate modules list $filemodules = ModUtil::apiFunc('Extensions', 'admin', 'getfilemodules'); $inconsistencies = ModUtil::apiFunc('Extensions', 'admin', 'checkconsistency', array('filemodules' => $filemodules)); if (!(empty($inconsistencies['errors_modulenames']) && empty($inconsistencies['errors_displaynames']))) { $this->view->assign('errors_modulenames', $inconsistencies['errors_modulenames']) ->assign('errors_displaynames', $inconsistencies['errors_displaynames']); return $this->view->fetch('extensions_admin_regenerate_errors.tpl'); } // No inconsistencies, so we can regenerate modules $defaults = (int) FormUtil::getPassedValue('defaults', false, 'GET'); if (!ModUtil::apiFunc('Extensions', 'admin', 'regenerate', array('filemodules' => $filemodules, 'defaults' => $defaults))) { LogUtil::registerError($this->__('Errors were detected regenerating the modules list from file system.')); } } // assign the state filter $this->view->assign('state', $state); // Get list of modules $mods = ModUtil::apiFunc('Extensions', 'admin', 'listmodules', array('startnum' => $startnum, 'letter' => $letter, 'state' => $state, 'numitems' => $this->getVar('itemsperpage'), 'sortdir' => $sortdir, 'sort' => $sort)); // generate an auth key to use in urls $csrftoken = SecurityUtil::generateCsrfToken($this->serviceManager, true); $moduleinfo = array(); if (!empty($mods)) { foreach ($mods as $mod) { // Add applicable actions $actions = array(); if (SecurityUtil::checkPermission('Extensions::', "$mod[name]::$mod[id]", ACCESS_ADMIN)) { switch ($mod['state']) { case ModUtil::STATE_ACTIVE: if (!ModUtil::apiFunc('Extensions', 'admin', 'iscoremodule', array('modulename' => $mod['name']))) { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'deactivate', array( 'id' => $mod['id'], 'startnum' => $startnum, 'csrftoken' => $csrftoken, 'letter' => $letter, 'state' => $state)), 'image' => 'folder_red.png', 'title' => $this->__f('Deactivate \'%s\' module', $mod['name'])); } if (System::isLegacyMode() && !ModUtil::isOO($mod['name'])) { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'legacyhooks', array( 'id' => $mod['id'])), 'image' => 'attach.png', 'title' => $this->__f('Legacy hook settings for \'%s\'', $mod['name'])); } if (PluginUtil::hasModulePlugins($mod['name'])) { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'viewPlugins', array( 'bymodule' => $mod['name'])), 'image' => 'blockdevice.png', 'title' => $this->__f('Plugins for \'%s\'', $mod['name'])); } break; case ModUtil::STATE_INACTIVE: $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'activate', array( 'id' => $mod['id'], 'startnum' => $startnum, 'csrftoken' => $csrftoken, 'letter' => $letter, 'state' => $state)), 'image' => 'folder_green.png', 'title' => $this->__f('Activate \'%s\'', $mod['name'])); $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'remove', array( 'id' => $mod['id'], 'startnum' => $startnum, 'letter' => $letter, 'state' => $state)), 'image' => '14_layer_deletelayer.png', 'title' => $this->__f('Uninstall \'%s\' module', $mod['name'])); break; case ModUtil::STATE_MISSING: $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'remove', array( 'id' => $mod['id'], 'startnum' => $startnum, 'letter' => $letter, 'state' => $state)), 'image' => '14_layer_deletelayer.png', 'title' => $this->__f('Remove \'%s\' module', $mod['name'])); break; case ModUtil::STATE_UPGRADED: $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'upgrade', array( 'id' => $mod['id'], 'startnum' => $startnum, 'csrftoken' => $csrftoken, 'letter' => $letter, 'state' => $state)), 'image' => 'folder_favorites.png', 'title' => $this->__f('Upgrade \'%s\'', $mod['name'])); break; case ModUtil::STATE_INVALID: // nothing to do, remove manually // future wish list, allow removal if FS is writable /* $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'remove', array( 'id' => $mod['id'], 'startnum' => $startnum, 'authid' => $authid, 'letter' => $letter, 'state' => $state)), 'image' => '14_layer_deletelayer.png', 'title' => $this->__('Remove module')); */ break; case ModUtil::STATE_NOTALLOWED: $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'remove', array( 'id' => $mod['id'], 'startnum' => $startnum, 'csrftoken' => $csrftoken, 'letter' => $letter, 'state' => $state)), 'image' => '14_layer_deletelayer.png', 'title' => $this->__f('Remove \'%s\' module', $mod['name'])); break; case ModUtil::STATE_UNINITIALISED: default: if ($mod['state'] < 10) { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'initialise', array( 'id' => $mod['id'], 'startnum' => $startnum, 'csrftoken' => $csrftoken, 'letter' => $letter, 'state' => $state)), 'image' => 'folder_new.png', 'title' => $this->__f('Install \'%s\'', $mod['name'])); // if ($this->serviceManager['multisites.enabled'] != 1 || ($this->serviceManager['multisites.mainsiteurl'] == FormUtil::getPassedValue('sitedns', null, 'GET') && $this->serviceManager['multisites.based_on_domains'] == 0) || ($this->serviceManager['multisites.mainsiteurl'] == $_SERVER['HTTP_HOST'] && $this->serviceManager['multisites.based_on_domains'] == 1)) { // $actions[] = array( // 'url' => ModUtil::url('Extensions', 'admin', 'remove', array( // 'id' => $mod['id'], // 'startnum' => $startnum, // 'authid' => $authid, // 'letter' => $letter, // 'state' => $state)), // 'image' => '14_layer_deletelayer.png', // 'title' => $this->__('Remove module')); // } } else { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'compinfo', array( 'id' => $mod['id'], 'startnum' => $startnum, 'letter' => $letter, 'state' => $state)), 'image' => 'documentinfo.png', 'title' => $this->__f('Incompatible version: \'%s\'', $mod['name'])); } break; } // RNG: can't edit an invalid module if ($mod['state'] != ModUtil::STATE_INVALID) { $actions[] = array( 'url' => ModUtil::url('Extensions', 'admin', 'modify', array( 'id' => $mod['id'])), 'image' => 'xedit.png', 'title' => $this->__f('Edit \'%s\'', $mod['name'])); } } // Translate state switch ($mod['state']) { case ModUtil::STATE_INACTIVE: $status = $this->__('Inactive'); $statusimage = 'yellowled.png'; break; case ModUtil::STATE_ACTIVE: $status = $this->__('Active'); $statusimage = 'greenled.png'; break; case ModUtil::STATE_MISSING: $status = $this->__('Files missing'); $statusimage = 'redled.png'; break; case ModUtil::STATE_UPGRADED: $status = $this->__('New version'); $statusimage = 'redled.png'; break; case ModUtil::STATE_INVALID: $status = $this->__('Invalid structure'); $statusimage = 'redled.png'; break; case ModUtil::STATE_NOTALLOWED: $status = $this->__('Not allowed'); $statusimage = 'folder_red.png'; break; case ModUtil::STATE_UNINITIALISED: default: if ($mod['state'] > 10) { $status = $this->__('Incompatible'); $statusimage = 'folder_red.png'; } else { $status = $this->__('Not installed'); $statusimage = 'redled.png'; } break; } // get new version number for ModUtil::STATE_UPGRADED if ($mod['state'] == ModUtil::STATE_UPGRADED) { $mod['newversion'] = $filemodules[$mod['directory']]['version']; } $moduleinfo[] = array( 'modinfo' => $mod, 'status' => $status, 'statusimage' => $statusimage, 'options' => $actions); } } $this->view->assign('multi', $this->serviceManager['multisites.enabled']) ->assign('sort', $sort) ->assign('sortdir', $sortdir) ->assign('modules', $moduleinfo); // Assign the values for the smarty plugin to produce a pager. $this->view->assign('pager', array('numitems' => ModUtil::apiFunc('Extensions', 'admin', 'countitems', array('letter' => $letter, 'state' => $state)), 'itemsperpage' => $this->getVar('itemsperpage'))); // Return the output that has been generated by this function return $this->view->fetch('extensions_admin_view.tpl'); }