maniaControl = $maniaControl; $this->initTables(); $this->pluginMenu = new PluginMenu($maniaControl); $this->maniaControl->configurator->addMenu($this->pluginMenu); } /** * Initialize necessary database tables * * @return bool */ private function initTables() { $mysqli = $this->maniaControl->database->mysqli; $pluginsTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLUGINS . "` ( `index` int(11) NOT NULL AUTO_INCREMENT, `className` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `active` tinyint(1) NOT NULL DEFAULT '0', `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`index`), UNIQUE KEY `className` (`className`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='ManiaControl plugin status' AUTO_INCREMENT=1;"; $tableStatement = $mysqli->prepare($pluginsTableQuery); if ($mysqli->error) { trigger_error($mysqli->error, E_USER_ERROR); return false; } $tableStatement->execute(); if ($tableStatement->error) { trigger_error($tableStatement->error, E_USER_ERROR); return false; } $tableStatement->close(); return true; } /** * Check if the plugin is running * * @param string $pluginClass * @return bool */ public function isPluginActive($pluginClass) { if (is_object($pluginClass)) { $pluginClass = get_class($pluginClass); } return isset($this->activePlugins[$pluginClass]); } /** * Check if the given class implements the plugin interface * * @param string $pluginClass * @return bool */ public function isPluginClass($pluginClass) { if (is_object($pluginClass)) { $pluginClass = get_class($pluginClass); } if (!in_array(Plugin::PLUGIN_INTERFACE, class_implements($pluginClass))) { return false; } return true; } /** * Add the class to array of loaded plugin classes * * @param string $pluginClass * @return bool */ public function addPluginClass($pluginClass) { if (is_object($pluginClass)) { $pluginClass = get_class($pluginClass); } if (in_array($pluginClass, $this->pluginClasses)) { return false; } if (!$this->isPluginClass($pluginClass)) { return false; } array_push($this->pluginClasses, $pluginClass); return true; } /** * Activate and start the plugin with the given name * * @param string $pluginClass * @return bool */ public function activatePlugin($pluginClass) { if (!is_string($pluginClass)) { return false; } if (!$this->isPluginClass($pluginClass)) { return false; } if ($this->isPluginActive($pluginClass)) { return false; } $plugin = new $pluginClass(); $plugin->load($this->maniaControl); $this->activePlugins[$pluginClass] = $plugin; $this->savePluginStatus($pluginClass, true); return true; } /** * Deactivate the plugin with the given class * * @param string $pluginClass * @return bool */ public function deactivatePlugin($pluginClass) { if (is_object($pluginClass)) { $pluginClass = get_class($pluginClass); } if (!$this->isPluginActive($pluginClass)) { return false; } $plugin = $this->activePlugins[$pluginClass]; unset($this->activePlugins[$pluginClass]); $plugin->unload(); $interfaces = class_implements($pluginClass); if (in_array(CallbackListener::CALLBACKLISTENER_INTERFACE, $interfaces)) { $this->maniaControl->callbackManager->unregisterCallbackListener($plugin); $this->maniaControl->callbackManager->unregisterScriptCallbackListener($plugin); } if (in_array(ManialinkPageAnswerListener::MANIALINKPAGEANSWERLISTENER_INTERFACE, $interfaces)) { $this->maniaControl->manialinkManager->unregisterManialinkPageAnswerListener($plugin); } $this->savePluginStatus($pluginClass, false); return true; } /** * Load complete plugins directory and start all configured plugins */ public function loadPlugins() { $pluginsDirectory = ManiaControlDir . '/plugins/'; $pluginFiles = scandir($pluginsDirectory, 0); foreach ($pluginFiles as $pluginFile) { if (stripos($pluginFile, '.') === 0) { continue; } $classesBefore = get_declared_classes(); $success = include_once $pluginsDirectory . $pluginFile; if (!$success) { continue; } $classesAfter = get_declared_classes(); $newClasses = array_diff($classesAfter, $classesBefore); foreach ($newClasses as $className) { if (!$this->isPluginClass($className)) { continue; } $this->addPluginClass($className); if ($this->isPluginActive($className)) { continue; } if (!$this->getSavedPluginStatus($className)) { continue; } $this->activatePlugin($className); } } } /** * Returns an Plugin if it is aktivated * @param $pluginClass * @return null */ public function getPlugin($pluginClass) { if($this->isPluginActive($pluginClass)){ return $this->activePlugins[$pluginClass]; } return null; } /** * Get all declared plugin class names * * @return array */ public function getPluginClasses() { return $this->pluginClasses; } /** * Get all active plugins * * @return array */ public function getActivePlugins() { return $this->activePlugins; } /** * Save plugin status in database * * @param string $className * @param bool $active * @return bool */ private function savePluginStatus($className, $active) { $mysqli = $this->maniaControl->database->mysqli; $pluginStatusQuery = "INSERT INTO `" . self::TABLE_PLUGINS . "` ( `className`, `active` ) VALUES ( ?, ? ) ON DUPLICATE KEY UPDATE `active` = VALUES(`active`);"; $pluginStatement = $mysqli->prepare($pluginStatusQuery); if ($mysqli->error) { trigger_error($mysqli->error); return false; } $activeInt = ($active ? 1 : 0); $pluginStatement->bind_param('si', $className, $activeInt); $pluginStatement->execute(); if ($pluginStatement->error) { trigger_error($pluginStatement->error); $pluginStatement->close(); return false; } $pluginStatement->close(); return true; } /** * Get plugin status from database * * @param string $className * @return bool */ private function getSavedPluginStatus($className) { $mysqli = $this->maniaControl->database->mysqli; $pluginStatusQuery = "SELECT `active` FROM `" . self::TABLE_PLUGINS . "` WHERE `className` = ?;"; $pluginStatement = $mysqli->prepare($pluginStatusQuery); if ($mysqli->error) { trigger_error($mysqli->error); return false; } $pluginStatement->bind_param('s', $className); $pluginStatement->execute(); if ($pluginStatement->error) { trigger_error($pluginStatement->error); $pluginStatement->close(); return false; } $pluginStatement->store_result(); if ($pluginStatement->num_rows <= 0) { $pluginStatement->free_result(); $pluginStatement->close(); $this->savePluginStatus($className, false); return false; } $pluginStatement->bind_result($activeInt); $pluginStatement->fetch(); $active = ($activeInt === 1); $pluginStatement->free_result(); $pluginStatement->close(); return $active; } }