From cdd89da287ef1994057b1c95d73f0686739ae344 Mon Sep 17 00:00:00 2001 From: beu Date: Sun, 10 Apr 2022 22:11:28 +0200 Subject: [PATCH] Add the possibility to unlink settings on multiple servers --- core/Configurator/ManiaControlSettings.php | 211 +++++++++++++++++++-- core/Plugins/PluginMenu.php | 184 ++++++++++++++++-- core/Settings/Setting.php | 6 + core/Settings/SettingManager.php | 199 ++++++++++++++++--- 4 files changed, 540 insertions(+), 60 deletions(-) diff --git a/core/Configurator/ManiaControlSettings.php b/core/Configurator/ManiaControlSettings.php index b017462a..db8ff62a 100644 --- a/core/Configurator/ManiaControlSettings.php +++ b/core/Configurator/ManiaControlSettings.php @@ -18,6 +18,7 @@ use ManiaControl\Callbacks\CallbackManager; use ManiaControl\ManiaControl; use ManiaControl\Players\Player; use ManiaControl\Settings\Setting; +use ManiaControl\Settings\SettingManager; /** * Class offering a Configurator for ManiaControl Settings @@ -32,7 +33,9 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { */ const TITLE = 'ManiaControl Settings'; const ACTION_PREFIX_SETTING = 'MCSetting.'; + const ACTION_PREFIX_SETTING_LINK = 'MCSettingLink.'; const ACTION_PREFIX_SETTINGCLASS = 'MCSettingClass.'; + const ACTION_PREFIX_SETTINGLINKS = 'MCSettingLinks.'; const ACTION_SETTINGCLASS_BACK = 'MCSettingClassBack'; const SETTING_PERMISSION_CHANGE_MC_SETTINGS = 'Change ManiaControl Settings'; const CACHE_CLASS_OPENED = 'ClassOpened'; @@ -69,9 +72,16 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { * @see \ManiaControl\Configurator\ConfiguratorMenu::getMenu() */ public function getMenu($width, $height, Script $script, Player $player) { - $openedClass = $player->getCache($this, self::CACHE_CLASS_OPENED); - if ($openedClass) { - return $this->getMenuSettingsForClass($openedClass, $width, $height, $script, $player); + $SubMenu = $player->getCache($this, self::CACHE_CLASS_OPENED); + if ($SubMenu) { + // Show Settings Menu + if (strpos($SubMenu, self::ACTION_PREFIX_SETTINGCLASS) === 0) { + $settingClass = substr($SubMenu, strlen(self::ACTION_PREFIX_SETTINGCLASS)); + return $this->getMenuSettingsForClass($settingClass, $width, $height, $script); + } else if (strpos($SubMenu, self::ACTION_PREFIX_SETTINGLINKS) === 0) { + $settingClass = substr($SubMenu, strlen(self::ACTION_PREFIX_SETTINGLINKS)); + return $this->getManageSettingsLink($settingClass, $width, $height, $script); + } } return $this->getMenuSettingClasses($width, $height, $script, $player); } @@ -86,8 +96,9 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { * @param Player $player * @return \FML\Controls\Frame */ - private function getMenuSettingsForClass($settingClass, $width, $height, Script $script, Player $player) { + private function getMenuSettingsForClass($settingClass, $width, $height, Script $script) { $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); + $isunlinkable = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getSettingManager(), SettingManager::SETTING_ALLOW_UNLINK_SERVER); $paging = new Paging(); $script->addFeature($paging); @@ -179,6 +190,18 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); $settingName = self::ACTION_PREFIX_SETTING . $setting->index; + + if ($isunlinkable && $setting->setting != SettingManager::SETTING_ALLOW_UNLINK_SERVER) { + $quadlink = new Quad(); + $settingFrame->addChild($quadlink); + $quadlink->setPosition(-0.48 * $width, 0.2, -0.01); + $quadlink->setSize(4, 4); + $quadlink->setColorize("ccccccaa"); + $quadlink->setStyle("UICommon64_1"); + $quadlink->setSubStyle("Padlock_light"); + $quadlink->setStyleSelected($setting->linked); + } + if ($setting->type === Setting::TYPE_BOOL) { // Boolean checkbox $quad = new Quad(); @@ -211,6 +234,136 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { $index++; } + if ($isunlinkable) { + $mapNameButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton( + 'Manage settings link', + 30, + 5, + self::ACTION_PREFIX_SETTINGLINKS . $settingClass + ); + $frame->addChild($mapNameButton); + $mapNameButton->setPosition(-$width / 2 + 60, -35); + } + + return $frame; + } + + /** + * getManageSettingsLink + * + * @param mixed $settingClass + * @param float $width + * @param float $height + * @param Script $script + * @param Player $player + * @return void + */ + public function getManageSettingsLink($settingClass, $width, $height, Script $script) { + $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); + + $paging = new Paging(); + $script->addFeature($paging); + $frame = new Frame(); + + // Config + $pagerSize = 9.; + $settingHeight = 5.; + $labelTextSize = 2; + $pageMaxCount = 10; + + // Pagers + $pagerPrev = new Quad_Icons64x64_1(); + $frame->addChild($pagerPrev); + $pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); + $pagerPrev->setSize($pagerSize, $pagerSize); + $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); + + $pagerNext = new Quad_Icons64x64_1(); + $frame->addChild($pagerNext); + $pagerNext->setPosition($width * 0.45, $height * -0.44, 2); + $pagerNext->setSize($pagerSize, $pagerSize); + $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); + + $paging->addButtonControl($pagerNext); + $paging->addButtonControl($pagerPrev); + + $pageCountLabel = new Label_Text(); + $frame->addChild($pageCountLabel); + $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); + $pageCountLabel->setPosition($width * 0.35, $height * -0.44); + $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); + $pageCountLabel->setTextSize(2); + + $paging->setLabel($pageCountLabel); + + $backLabel = new Label_Button(); + $frame->addChild($backLabel); + $backLabel->setStyle($backLabel::STYLE_CardMain_Quit); + $backLabel->setPosition(-$width / 2 + 5, -$height / 2 + 5); + $backLabel->setHorizontalAlign($backLabel::LEFT); + $backLabel->setScale(0.5); + $backLabel->setTextSize(2); + $backLabel->setText('Back'); + $backLabel->setAction(self::ACTION_PREFIX_SETTINGCLASS . $settingClass); + + $headLabel = new Label_Text(); + $frame->addChild($headLabel); + $headLabel->setHorizontalAlign($headLabel::LEFT); + $headLabel->setPosition($width * -0.46, $height * 0.41); + $headLabel->setSize($width * 0.6, $settingHeight); + $headLabel->setStyle($headLabel::STYLE_TextCardSmall); + $headLabel->setTextSize(3); + $headLabel->setText($settingClass); + $headLabel->setTextColor('ff0'); + + $pageFrame = null; + $index = 0; + $posY = 0; + foreach ($settings as $setting) { + if ($index % $pageMaxCount === 0) { + $pageFrame = new Frame(); + $frame->addChild($pageFrame); + $paging->addPageControl($pageFrame); + $posY = $height * 0.41 - $settingHeight * 1.5; + } + + $settingFrame = new Frame(); + $pageFrame->addChild($settingFrame); + $settingFrame->setY($posY); + + $nameLabel = new Label_Text(); + $settingFrame->addChild($nameLabel); + $nameLabel->setHorizontalAlign($nameLabel::LEFT); + $nameLabel->setX($width * -0.46); + $nameLabel->setSize($width * 0.6, $settingHeight); + $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); + $nameLabel->setTextSize($labelTextSize); + $nameLabel->setText($setting->setting); + $nameLabel->setTextColor('fff'); + + $descriptionLabel = new Label_Text(); + $pageFrame->addChild($descriptionLabel); + $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); + $descriptionLabel->setPosition(-0.45 * $width, -0.35 * $height); + $descriptionLabel->setSize(0.9 * $width, $settingHeight); + $descriptionLabel->setTextSize($labelTextSize); + $descriptionLabel->setTranslate(true); + $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); + + if ($setting->setting != SettingManager::SETTING_ALLOW_UNLINK_SERVER) { + $quad = new Quad(); + $quad->setPosition($width * 0.33, 0.2, -0.01); + $quad->setSize(4, 4); + $checkBox = new CheckBox(self::ACTION_PREFIX_SETTING_LINK . $setting->index, $setting->linked, $quad); + $checkBox->setEnabledDesign("UICommon64_1", "Padlock_light"); + $checkBox->setDisabledDesign("UICommon64_1", "Padlock_light"); + $settingFrame->addChild($checkBox); + } + + $posY -= $settingHeight; + $index++; + } + return $frame; } @@ -223,7 +376,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { * @param Player $player * @return \FML\Controls\Frame */ - private function getMenuSettingClasses($width, $height, Script $script, Player $player) { + private function getMenuSettingClasses($width, $height, Script $script) { $settingClasses = $this->maniaControl->getSettingManager()->getSettingClasses(true); $paging = new Paging(); @@ -311,13 +464,13 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { $player->destroyCache($this, self::CACHE_CLASS_OPENED); $menuId = $this->maniaControl->getConfigurator()->getMenuId($this); $this->maniaControl->getConfigurator()->showMenu($player, $menuId); - } else if (strpos($actionId, self::ACTION_PREFIX_SETTINGCLASS) === 0) { - // Setting class selected - $settingClass = substr($actionId, strlen(self::ACTION_PREFIX_SETTINGCLASS)); - + } else if (strpos($actionId, self::ACTION_PREFIX_SETTINGCLASS) === 0 || strpos($actionId, self::ACTION_PREFIX_SETTINGLINKS) === 0) { $login = $callback[1][1]; $player = $this->maniaControl->getPlayerManager()->getPlayer($login); - $player->setCache($this, self::CACHE_CLASS_OPENED, $settingClass); + if (!$player) { + return; + } + $player->setCache($this, self::CACHE_CLASS_OPENED, $actionId); $menuId = $this->maniaControl->getConfigurator()->getMenuId($this); $this->maniaControl->getConfigurator()->showMenu($player, $menuId); @@ -333,25 +486,45 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener { $this->maniaControl->getAuthenticationManager()->sendNotAllowed($player); return; } - if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0) { + + if (!$configData[3] || (strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0 && strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING_LINK) !== 0)) { return; } - $prefixLength = strlen(self::ACTION_PREFIX_SETTING); - foreach ($configData[3] as $settingData) { - $settingIndex = (int)substr($settingData['Name'], $prefixLength); - $settingObject = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($settingIndex); - if (!$settingObject) { + if (!$settingData || !isset($settingData['Value'])) { continue; } - if (!$settingData || $settingData['Value'] == $settingObject->value) { + $data = explode(".", $settingData["Name"]); + $type = $data[0]; + $index = $data[1]; + + $settingObjectByIndex = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($index); + if (!$settingObjectByIndex) { continue; } - $settingObject->value = $settingData['Value']; - $this->maniaControl->getSettingManager()->saveSetting($settingObject); + if ($type . "." == self::ACTION_PREFIX_SETTING_LINK) { + if ($settingData['Value'] && !$settingObjectByIndex->linked) { + $this->maniaControl->getSettingManager()->deleteSettingUnlinked($settingObjectByIndex); + $setting = $this->maniaControl->getSettingManager()->getSettingObject($settingObjectByIndex->class, $settingObjectByIndex->setting); + $setting->linked = True; + } else if (!$settingData['Value'] && $settingObjectByIndex->linked) { + $setting = $settingObjectByIndex; + $setting->linked = false; + $this->maniaControl->getSettingManager()->setSettingUnlinked($setting); + } else { + continue; + } + } else { + $setting = $settingObjectByIndex; + if ($settingData['Value'] == $setting->value) { + continue; + } + $setting->value = $settingData['Value']; + } + $this->maniaControl->getSettingManager()->saveSetting($setting); } $this->maniaControl->getChat()->sendSuccess('Settings saved!', $player); diff --git a/core/Plugins/PluginMenu.php b/core/Plugins/PluginMenu.php index df322271..99538ab3 100644 --- a/core/Plugins/PluginMenu.php +++ b/core/Plugins/PluginMenu.php @@ -24,6 +24,8 @@ use ManiaControl\ManiaControl; use ManiaControl\Manialinks\ManialinkPageAnswerListener; use ManiaControl\Players\Player; use ManiaControl\Settings\Setting; +use ManiaControl\Settings\SettingManager; + /** * Configurator for enabling and disabling Plugins @@ -40,6 +42,8 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns const ACTION_PREFIX_DISABLEPLUGIN = 'PluginMenu.Disable.'; const ACTION_PREFIX_SETTINGS = 'PluginMenu.Settings.'; const ACTION_PREFIX_SETTING = 'PluginMenuSetting.'; + const ACTION_PREFIX_SETTING_LINK = 'PluginMenuSettingLink.'; + const ACTION_PREFIX_MANAGE_SETTING_LINK = 'PluginMenu.ManageSettingsLink.'; const ACTION_BACK_TO_PLUGINS = 'PluginMenu.BackToPlugins'; const ACTION_PREFIX_UPDATEPLUGIN = 'PluginMenu.Update.'; const ACTION_UPDATEPLUGINS = 'PluginMenu.Update.All'; @@ -126,10 +130,16 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $paging->setLabel($pageCountLabel); - $settingClass = $player->getCache($this, self::CACHE_SETTING_CLASS); - if ($settingClass) { + $SubMenu = $player->getCache($this, self::CACHE_SETTING_CLASS); + if ($SubMenu) { // Show Settings Menu - return $this->getPluginSettingsMenu($frame, $width, $height, $paging, $player, $settingClass); + if (strpos($SubMenu, self::ACTION_PREFIX_SETTINGS) === 0) { + $settingClass = substr($SubMenu, strlen(self::ACTION_PREFIX_SETTINGS)); + return $this->getPluginSettingsMenu($frame, $width, $height, $paging, $player, $settingClass); + } else if (strpos($SubMenu, self::ACTION_PREFIX_MANAGE_SETTING_LINK) === 0) { + $settingClass = substr($SubMenu, strlen(self::ACTION_PREFIX_MANAGE_SETTING_LINK)); + return $this->getManageSettingsLink($frame, $width, $height, $paging, $player, $settingClass); + } } // Display normal Plugin List @@ -255,6 +265,7 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns private function getPluginSettingsMenu(Frame $frame, $width, $height, Paging $paging, Player $player, $settingClass) { // TODO: centralize menu code to use by mc settings and plugin settings $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); + $isunlinkable = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getSettingManager(), SettingManager::SETTING_ALLOW_UNLINK_SERVER); $pageSettingsMaxCount = 10; $posY = 0; @@ -273,6 +284,11 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $headLabel->setText($settingClass); $headLabel->setTextColor('ff0'); + if (count($settings) > 64) { + Logger::logWarning("You can't send more than 64 fields in Manialink Action"); + $this->maniaControl->getChat()->sendError("Some settings may not be saved because it has more than 64", $player); + } + foreach ($settings as $setting) { if ($index % $pageSettingsMaxCount === 0) { $pageFrame = new Frame(); @@ -304,6 +320,17 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $descriptionLabel->setTranslate(true); $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); + if ($isunlinkable) { + $quadlink = new Quad(); + $settingFrame->addChild($quadlink); + $quadlink->setPosition(-0.48 * $width, 0.2, -0.01); + $quadlink->setSize(4, 4); + $quadlink->setColorize("ccccccaa"); + $quadlink->setStyle("UICommon64_1"); + $quadlink->setSubStyle("Padlock_light"); + $quadlink->setStyleSelected($setting->linked); + } + if ($setting->type === Setting::TYPE_BOOL) { // Boolean checkbox $quad = new Quad(); @@ -346,6 +373,109 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $backButton->setPosition(-$width / 2 + 5, -$height / 2 + 5); $backButton->setAction(self::ACTION_BACK_TO_PLUGINS); + if ($isunlinkable) { + $mapNameButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton( + 'Manage settings link', + 30, + 5, + self::ACTION_PREFIX_MANAGE_SETTING_LINK . $settingClass + ); + $frame->addChild($mapNameButton); + $mapNameButton->setPosition(-$width / 2 + 60, -35); + } + + return $frame; + } + + /** + * getManageSettingsLink + * + * @param Frame $frame + * @param float $width + * @param float $height + * @param Paging $paging + * @param Player $player + * @param mixed $settingClass + * @return void + */ + public function getManageSettingsLink(Frame $frame, $width, $height, Paging $paging, Player $player, $settingClass) { + $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); + + $pageSettingsMaxCount = 10; + $posY = 0; + $index = 0; + $settingHeight = 5.; + $pageFrame = null; + + if (count($settings) > 64) { + Logger::logWarning("You can't send more than 64 fields in Manialink Action"); + $this->maniaControl->getChat()->sendError("Some settings may not be saved because it has more than 64", $player); + } + + //Headline Label + $headLabel = new Label_Text(); + $frame->addChild($headLabel); + $headLabel->setHorizontalAlign($headLabel::LEFT); + $headLabel->setPosition($width * -0.46, $height * 0.41); + $headLabel->setSize($width * 0.6, $settingHeight); + $headLabel->setStyle($headLabel::STYLE_TextCardSmall); + $headLabel->setTextSize(3); + $headLabel->setText($settingClass); + $headLabel->setTextColor('ff0'); + + foreach ($settings as $setting) { + if ($index % $pageSettingsMaxCount === 0) { + $pageFrame = new Frame(); + $frame->addChild($pageFrame); + $paging->addPageControl($pageFrame); + $posY = $height * 0.41 - $settingHeight * 1.5; + } + + $settingFrame = new Frame(); + $pageFrame->addChild($settingFrame); + $settingFrame->setY($posY); + + $nameLabel = new Label_Text(); + $settingFrame->addChild($nameLabel); + $nameLabel->setHorizontalAlign($nameLabel::LEFT); + $nameLabel->setX($width * -0.46); + $nameLabel->setSize($width * 0.6, $settingHeight); + $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); + $nameLabel->setTextSize(2); + $nameLabel->setText($setting->setting); + $nameLabel->setTextColor('fff'); + + $descriptionLabel = new Label_Text(); + $pageFrame->addChild($descriptionLabel); + $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); + $descriptionLabel->setPosition(-0.45 * $width, -0.35 * $height); + $descriptionLabel->setSize(0.9 * $width, $settingHeight); + $descriptionLabel->setTextSize(2); + $descriptionLabel->setTranslate(true); + $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); + + $quad = new Quad(); + $quad->setPosition($width * 0.33, 0.2, -0.01); + $quad->setSize(4, 4); + $checkBox = new CheckBox(self::ACTION_PREFIX_SETTING_LINK . $setting->index, $setting->linked, $quad); + $checkBox->setEnabledDesign("UICommon64_1", "Padlock_light"); + $checkBox->setDisabledDesign("UICommon64_1", "Padlock_light"); + $settingFrame->addChild($checkBox); + + $posY -= $settingHeight; + + $index++; + } + + $backButton = new Label_Button(); + $frame->addChild($backButton); + $backButton->setStyle($backButton::STYLE_CardMain_Quit); + $backButton->setHorizontalAlign($backButton::LEFT); + $backButton->setScale(0.5); + $backButton->setText('Back'); + $backButton->setPosition(-$width / 2 + 5, -$height / 2 + 5); + $backButton->setAction(self::ACTION_PREFIX_SETTINGS . $settingClass); + return $frame; } @@ -359,7 +489,8 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $enable = (strpos($actionId, self::ACTION_PREFIX_ENABLEPLUGIN) === 0); $disable = (strpos($actionId, self::ACTION_PREFIX_DISABLEPLUGIN) === 0); $settings = (strpos($actionId, self::ACTION_PREFIX_SETTINGS) === 0); - if (!$enable && !$disable && !$settings) { + $managelink = (strpos($actionId, self::ACTION_PREFIX_MANAGE_SETTING_LINK) === 0); + if (!$enable && !$disable && !$settings && !$managelink) { return; } @@ -395,10 +526,9 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns } else { $this->maniaControl->getChat()->sendError('Error deactivating ' . $pluginClass::getName() . '!', $player); } - } else if ($settings) { + } else if ($settings || $managelink) { // Open Settings Menu - $pluginClass = substr($actionId, strlen(self::ACTION_PREFIX_SETTINGS)); - $player->setCache($this, self::CACHE_SETTING_CLASS, $pluginClass); + $player->setCache($this, self::CACHE_SETTING_CLASS, $actionId); } // Reopen the Menu @@ -414,25 +544,45 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns $this->maniaControl->getAuthenticationManager()->sendNotAllowed($player); return; } - if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0) { + + if (!$configData[3] || (strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0 && strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING_LINK) !== 0)) { return; } - $prefixLength = strlen(self::ACTION_PREFIX_SETTING); foreach ($configData[3] as $settingData) { - $settingIndex = (int)substr($settingData['Name'], $prefixLength); - $settingObject = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($settingIndex); - if (!$settingObject) { + if (!$settingData || !isset($settingData['Value'])) { + continue; + } + $data = explode(".", $settingData["Name"]); + $type = $data[0]; + $index = $data[1]; + + $settingObjectByIndex = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($index); + if (!$settingObjectByIndex) { continue; } - if (!$settingData || $settingData['Value'] == $settingObject->value) { - continue; + if ($type . "." == self::ACTION_PREFIX_SETTING_LINK) { + if ($settingData['Value'] && !$settingObjectByIndex->linked) { + $this->maniaControl->getSettingManager()->deleteSettingUnlinked($settingObjectByIndex); + $setting = $this->maniaControl->getSettingManager()->getSettingObject($settingObjectByIndex->class, $settingObjectByIndex->setting); + $setting->linked = True; + } else if (!$settingData['Value'] && $settingObjectByIndex->linked) { + $setting = $settingObjectByIndex; + $setting->linked = false; + $this->maniaControl->getSettingManager()->setSettingUnlinked($setting); + } else { + continue; + } + } else { + $setting = $settingObjectByIndex; + if ($settingData['Value'] == $setting->value) { + continue; + } + $setting->value = $settingData['Value']; } - - $settingObject->value = $settingData['Value']; - $this->maniaControl->getSettingManager()->saveSetting($settingObject); + $this->maniaControl->getSettingManager()->saveSetting($setting); } $this->maniaControl->getChat()->sendSuccess('Plugin Settings saved!', $player); diff --git a/core/Settings/Setting.php b/core/Settings/Setting.php index d10b955c..b03b34b1 100644 --- a/core/Settings/Setting.php +++ b/core/Settings/Setting.php @@ -34,6 +34,8 @@ class Setting implements UsageInformationAble { public $class = null; public $setting = null; public $type = null; + public $linked = null; + public $serverIndex = null; public $value = null; public $default = null; public $set = null; @@ -58,6 +60,8 @@ class Setting implements UsageInformationAble { if ($this->set) { $this->set = $this->castValue($this->set, $this->type); } + $this->linked = $this->castValue($this->linked); + $this->serverIndex = $this->castValue($this->serverIndex); $this->fetchTime = time(); } else { // Created by Values @@ -74,6 +78,8 @@ class Setting implements UsageInformationAble { $this->default = $this->value; $this->description = $description; $this->priority = $priority; + $this->linked = true; + $this->serverIndex = 0; } } diff --git a/core/Settings/SettingManager.php b/core/Settings/SettingManager.php index 07f258fe..2c1db591 100644 --- a/core/Settings/SettingManager.php +++ b/core/Settings/SettingManager.php @@ -23,8 +23,10 @@ class SettingManager implements CallbackListener, UsageInformationAble { /* * Constants */ - const TABLE_SETTINGS = 'mc_settings'; - const CB_SETTING_CHANGED = 'SettingManager.SettingChanged'; + const TABLE_SETTINGS = 'mc_settings'; + const CB_SETTING_CHANGED = 'SettingManager.SettingChanged'; + + const SETTING_ALLOW_UNLINK_SERVER = 'Allow to unlink settings with multiple servers'; /* * Private properties @@ -45,6 +47,8 @@ class SettingManager implements CallbackListener, UsageInformationAble { // Callbacks $this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit'); + + $this->initSetting($this, self::SETTING_ALLOW_UNLINK_SERVER, false); } /** @@ -96,6 +100,18 @@ class SettingManager implements CallbackListener, UsageInformationAble { trigger_error($mysqli->error, E_USER_ERROR); } } + + // Add link status + $mysqli->query("ALTER TABLE `" . self::TABLE_SETTINGS . "` ADD COLUMN `linked` TINYINT(1) DEFAULT 1 AFTER `type`, + ADD COLUMN `serverIndex` INT(11) DEFAULT 0 AFTER `linked`, + DROP INDEX `settingId`, + ADD UNIQUE KEY `settingId` (`class`,`setting`,`serverIndex`);"); + if ($mysqli->error) { + // If not Duplicate + if ($mysqli->errno !== 1060) { + trigger_error($mysqli->error, E_USER_ERROR); + } + } return $result; } @@ -245,14 +261,26 @@ class SettingManager implements CallbackListener, UsageInformationAble { // Fetch setting $mysqli = $this->maniaControl->getDatabase()->getMysqli(); - $settingQuery = "SELECT * FROM `" . self::TABLE_SETTINGS . "` - WHERE `class` = '" . $mysqli->escape_string($settingClass) . "' - AND `setting` = '" . $mysqli->escape_string($settingName) . "';"; - $result = $mysqli->query($settingQuery); + $settingStatement = $mysqli->prepare("SELECT * FROM `" . self::TABLE_SETTINGS . "` + WHERE `class` = ? + AND `setting` = ? + AND (`serverIndex` = ? OR `serverIndex` = 0) ORDER BY `serverIndex` DESC ;"); if ($mysqli->error) { trigger_error($mysqli->error); return null; } + + $serverInfo = $this->maniaControl->getServer(); + if ($serverInfo == null) { + $serverIndex = ""; + } else { + $serverIndex = $serverInfo->index; + } + $settingStatement->bind_param('ssi', $settingClass, $settingName, $serverIndex); + if (!$settingStatement->execute()) { + trigger_error('Error executing MySQL query: ' . $settingStatement->error); + } + $result = $settingStatement->get_result(); if ($result->num_rows <= 0) { $result->free(); if ($default === null) { @@ -314,11 +342,17 @@ class SettingManager implements CallbackListener, UsageInformationAble { public function saveSetting(Setting $setting, $init = false) { $mysqli = $this->maniaControl->getDatabase()->getMysqli(); if ($init) { + $existingsetting = $this->getSettingObject($setting->class, $setting->setting); + if ($existingsetting !== null && !$existingsetting->linked){ + $setting->linked = false; + } + // Init - Keep old value if the default didn't change - $valueUpdateString = '`value` = IF(`default` = VALUES(`default`), `value`, VALUES(`default`))'; + $valueUpdateString = '`value` = IF(`default` = VALUES(`default`), `value`, VALUES(`default`)), + `serverIndex` = IF(`serverIndex` IS NULL, 0, `serverIndex`)'; } else { // Set - Update value in any case - $valueUpdateString = '`value` = VALUES(`value`)'; + $valueUpdateString = '`value` = VALUES(`value`), `serverIndex` = VALUES(`serverIndex`)'; } $settingQuery = "INSERT INTO `" . self::TABLE_SETTINGS . "` ( `class`, @@ -326,15 +360,18 @@ class SettingManager implements CallbackListener, UsageInformationAble { `type`, `description`, `value`, + `serverIndex`, + `linked`, `default`, `set`, `priority` ) VALUES ( - ?, ?, ?, ?, ?, ?, ?, ? + ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ON DUPLICATE KEY UPDATE `index` = LAST_INSERT_ID(`index`), `type` = VALUES(`type`), {$valueUpdateString}, + `linked` = VALUES(`linked`), `default` = VALUES(`default`), `set` = VALUES(`set`), `description` = VALUES(`description`), @@ -348,13 +385,22 @@ class SettingManager implements CallbackListener, UsageInformationAble { $formattedValue = $setting->getFormattedValue(); $formattedDefault = $setting->getFormattedDefault(); $formattedSet = $setting->getFormattedSet(); + $serverInfo = $this->maniaControl->getServer(); + + if ($setting->linked || $serverInfo == null || $serverInfo->index == null) { + $serverIndex = 0; + } else { + $serverIndex = $serverInfo->index; + } $settingStatement->bind_param( - 'sssssssi', + 'sssssiissi', $setting->class, $setting->setting, $setting->type, $setting->description, $formattedValue, + $serverIndex, + $setting->linked, $formattedDefault, $formattedSet, $setting->priority @@ -397,6 +443,44 @@ class SettingManager implements CallbackListener, UsageInformationAble { } return null; } + + /** + * setSettingUnlinked + * + * @param mixed $object + * @param string $settingName + * @return void + */ + public function setSettingUnlinked($object, $settingName = "") { + if ($object instanceof Setting) { + $settingClass = $object->class; + $settingName = $object->setting; + } else { + $settingClass = ClassUtil::getClass($object); + } + + // Fetch setting + $mysqli = $this->maniaControl->getDatabase()->getMysqli(); + $settingStatement = $mysqli->prepare("UPDATE `" . self::TABLE_SETTINGS . "` + SET `linked` = 0, `changed` = NOW() + WHERE `class` = ? + AND `setting` = ?"); + if ($mysqli->error) { + trigger_error($mysqli->error); + return null; + } + + $settingStatement->bind_param('ss', $settingClass, $settingName); + if (!$settingStatement->execute()) { + trigger_error('Error executing MySQL query: ' . $settingStatement->error); + } + $result = $settingStatement->get_result(); + + if (isset($this->storedSettings[$settingClass . $settingName])) { + unset($this->storedSettings[$settingClass . $settingName]); + } + return $result; + } /** * Reset a Setting to its Default Value @@ -407,24 +491,38 @@ class SettingManager implements CallbackListener, UsageInformationAble { */ public function resetSetting($object, $settingName = null) { if ($object instanceof Setting) { - $className = $object->class; + $settingClass = $object->class; $settingName = $object->setting; } else { - $className = ClassUtil::getClass($object); + $settingClass = ClassUtil::getClass($object); } $mysqli = $this->maniaControl->getDatabase()->getMysqli(); - $settingQuery = "UPDATE `" . self::TABLE_SETTINGS . "` + $settingStatement = $mysqli->prepare("UPDATE `" . self::TABLE_SETTINGS . "` SET `value` = `default` - WHERE `class` = '" . $mysqli->escape_string($className) . "' - AND `setting` = '" . $mysqli->escape_string($settingName) . "';"; - $result = $mysqli->query($settingQuery); + WHERE `class` = ? + AND `setting` = ? + AND (`serverIndex` = ? OR `serverIndex` = 0) ORDER BY `serverIndex` DESC LIMIT 1;"); // TODO : by server if linked or not if ($mysqli->error) { trigger_error($mysqli->error); - return false; + return null; } - if (isset($this->storedSettings[$className . $settingName])) { - unset($this->storedSettings[$className . $settingName]); + + $serverInfo = $this->maniaControl->getServer(); + if ($serverInfo == null) { + $serverIndex = 0; + } else { + $serverIndex = $serverInfo->index; } + $settingStatement->bind_param('ssi', $settingClass, $settingName, $serverIndex); + if (!$settingStatement->execute()) { + trigger_error('Error executing MySQL query: ' . $settingStatement->error); + } + $result = $settingStatement->get_result(); + + if (isset($this->storedSettings[$settingClass . $settingName])) { + unset($this->storedSettings[$settingClass . $settingName]); + } + return $result; } @@ -460,6 +558,45 @@ class SettingManager implements CallbackListener, UsageInformationAble { return $result; } + /** + * Delete unlinked settings + * + * @param mixed $object + * @param string $settingName + * @return bool + */ + public function deleteSettingUnlinked($object, $settingName = null) { + if ($object instanceof Setting) { + $settingClass = $object->class; + $settingName = $object->setting; + } else { + $settingClass = ClassUtil::getClass($object); + } + + // Fetch setting + $mysqli = $this->maniaControl->getDatabase()->getMysqli(); + $settingStatement = $mysqli->prepare("DELETE FROM `" . self::TABLE_SETTINGS . "` + WHERE `class` = ? + AND `setting` = ? + AND `serverIndex` != 0"); + if ($mysqli->error) { + trigger_error($mysqli->error); + return null; + } + + $settingStatement->bind_param('ss', $settingClass, $settingName); + if (!$settingStatement->execute()) { + trigger_error('Error executing MySQL query: ' . $settingStatement->error); + } + $result = $settingStatement->get_result(); + + if (isset($this->storedSettings[$settingClass . $settingName])) { + unset($this->storedSettings[$settingClass . $settingName]); + } + + return $result; + } + /** * Get all Settings for the given Class * @@ -469,14 +606,27 @@ class SettingManager implements CallbackListener, UsageInformationAble { public function getSettingsByClass($object) { $className = ClassUtil::getClass($object); $mysqli = $this->maniaControl->getDatabase()->getMysqli(); - $query = "SELECT * FROM `" . self::TABLE_SETTINGS . "` - WHERE `class` = '" . $mysqli->escape_string($className) . "' - ORDER BY `priority` ASC, `setting` ASC;"; - $result = $mysqli->query($query); + // LIMIT is required to keep unlinked setting + $settingStatement = $mysqli->prepare("SELECT * FROM (SELECT * FROM `" . self::TABLE_SETTINGS . "` + WHERE class = ? AND (`serverIndex` = ? OR `serverIndex` = 0) + ORDER BY `priority` ASC, `setting` ASC, `serverIndex` DESC + LIMIT 9999999) + as t GROUP BY `setting`; "); if ($mysqli->error) { trigger_error($mysqli->error); return null; } + $serverInfo = $this->maniaControl->getServer(); + if ($serverInfo == null) { + $serverIndex = 0; + } else { + $serverIndex = $serverInfo->index; + } + $settingStatement->bind_param('si', $className, $serverIndex); + if (!$settingStatement->execute()) { + trigger_error('Error executing MySQL query: ' . $settingStatement->error); + } + $result = $settingStatement->get_result(); $settings = array(); while ($setting = $result->fetch_object(Setting::CLASS_NAME, array(false, null, null))) { $settings[$setting->index] = $setting; @@ -487,10 +637,11 @@ class SettingManager implements CallbackListener, UsageInformationAble { /** * Get all Settings + * CAREFUL: could have multiple time the same setting if in unlinked mode * * @return Setting[] */ - public function getSettings() { + public function getSettings() { $mysqli = $this->maniaControl->getDatabase()->getMysqli(); $query = "SELECT * FROM `" . self::TABLE_SETTINGS . "` ORDER BY `class` ASC, `priority` ASC, `setting` ASC;";