getEditableTemplates(); $missingTemplates = array_diff($this->getCoreTemplates(), $this->getPluginTemplates()); $extraTemplates = array_diff($this->getPluginTemplates(), $this->getCoreTemplates()); $modifiedStatus = $this->getModifiedStatus(); $this->response->html($this->helper->layout->config("OMITemplateModder:config/index", [ "title" => t("OMI - Notification Template Modder"), "templates" => $templates, "missing_templates" => $missingTemplates, "extra_templates" => $extraTemplates, "modified_status" => $modifiedStatus, ])); } /** * Get a list of editable templates from the plugin's directory. * * @return array */ private function getEditableTemplates() { $templates = []; $templateDir = ETM_PLUGIN_ROOT_DIR . "/Template/notification"; foreach (glob($templateDir . "/*.php") as $filename) { $templateName = basename($filename, ".php"); $templates[] = "notification/" . $templateName; } return $templates; } /** * Get a list of core notification templates. * * @return array */ private function getCoreTemplates() { $templates = []; // Use the new custom constant defined in Plugin.php $templateDir = KB_APP_DIR . "/Template/notification"; foreach (glob($templateDir . "/*.php") as $filename) { $templates[] = basename($filename, ".php"); } return $templates; } /** * Get a list of plugin notification templates. * * @return array */ private function getPluginTemplates() { $templates = []; $templateDir = ETM_PLUGIN_ROOT_DIR . "/Template/notification"; foreach (glob($templateDir . "/*.php") as $filename) { $templates[] = basename($filename, ".php"); } return $templates; } /** * Compares core and plugin templates by file content to check for modifications. * * @return array */ private function getModifiedStatus() { $modified = []; $pluginTemplateDir = ETM_PLUGIN_ROOT_DIR . '/Template/notification'; $coreTemplateDir = KB_APP_DIR . '/Template/notification'; foreach (glob($pluginTemplateDir . '/*.php') as $filename) { $templateName = basename($filename); $pluginFile = $pluginTemplateDir . '/' . $templateName; $coreFile = $coreTemplateDir . '/' . $templateName; // Only compare if the core file exists if (file_exists($coreFile)) { $pluginContent = file_get_contents($pluginFile); $coreContent = file_get_contents($coreFile); // Compare the file contents if ($pluginContent !== $coreContent) { $modified[$templateName] = true; } } } return $modified; } /** * Show the form to edit a template */ public function edit() { $templateIndex = $this->request->getIntegerParam("template_index"); $templates = $this->getEditableTemplates(); if (!isset($templates[$templateIndex])) { $this->flash->failure(t("Template not found!")); return $this->response->redirect($this->helper->url->to("TemplateController", "show", ["plugin" => "OMITemplateModder"])); } $templateName = $templates[$templateIndex]; $templatePath = $this->getTemplatePath($templateName); if (!file_exists($templatePath)) { $this->flash->failure(t("Template file not found!")); return $this->response->redirect($this->helper->url->to("TemplateController", "show", ["plugin" => "OMITemplateModder"])); } $templateContent = file_get_contents($templatePath); // Use the layout helper to render the page with the full Kanboard layout. $this->response->html($this->helper->layout->config("OMITemplateModder:config/edit", [ "title" => t("OMI - Notification Template Modder"), "subtitle" => t("Edit Template: %s", $templateName), "templateName" => $templateName, "templateContent" => htmlspecialchars($templateContent), "templateIndex" => $templateIndex // Pass the index for the form action ])); } /** * Save the edited template */ public function save() { $templateIndex = $this->request->getIntegerParam("template_index"); $templates = $this->getEditableTemplates(); if (!isset($templates[$templateIndex])) { $this->flash->failure(t("Template not found! Check your Kanboard version is compatible with this plugin.")); return $this->response->redirect($this->helper->url->to("TemplateController", "show", ["plugin" => "OMITemplateModder"])); } $templateName = $templates[$templateIndex]; $templateContent = $this->request->getValue("content"); $templatePath = $this->getTemplatePath($templateName); //check if the realpath of the file to be saved begins with the realpath of the allowed directory. $allowedDir = realpath(\ETM_PLUGIN_ROOT_DIR . "/Template/notification"); $realTemplatePath = realpath($templatePath); if ($realTemplatePath === false || strpos($realTemplatePath, $allowedDir) !== 0) { $this->flash->failure(t("Invalid template path.")); return $this->response->redirect($this->helper->url->to("TemplateController", "show", ["plugin" => "OMITemplateModder"])); } // Try to save the file if (file_put_contents($templatePath, $templateContent) !== false) { $this->flash->success(t("Template saved successfully.")); } else { $this->flash->failure(t("Unable to save template. Please check file permissions and directory '_DIR_' set up.")); } return $this->response->redirect($this->helper->url->to("TemplateController", "edit", ["plugin" => "OMITemplateModder", "template_index" => $templateIndex])); } /** * Get the full path to a template file * * @param string $templateName * @return string */ private function getTemplatePath($templateName) { return \ETM_PLUGIN_ROOT_DIR . "/Template/" . $templateName . ".php"; } } #- #plugins/OMITemplateModder/Controller/TemplateController.php