From f37eee71ffb025867319cc291d473a94b875c543 Mon Sep 17 00:00:00 2001 From: Jean Francois Van Ass Date: Thu, 30 Sep 2021 11:32:15 +0200 Subject: [PATCH] Manage files parameters --- lib/admin_presets_base.class.php | 1 - lib/admin_presets_export.class.php | 4 +- lib/admin_presets_load.class.php | 4 +- lib/admin_presets_settings_types.php | 264 +++++++++++++++++++++++++++ version.php | 2 +- 5 files changed, 270 insertions(+), 5 deletions(-) diff --git a/lib/admin_presets_base.class.php b/lib/admin_presets_base.class.php index 697a899..177941c 100755 --- a/lib/admin_presets_base.class.php +++ b/lib/admin_presets_base.class.php @@ -430,7 +430,6 @@ protected function _get_settings($dbsettings, $sitedbvalues = false, $settings, } } } - return $settings; } diff --git a/lib/admin_presets_export.class.php b/lib/admin_presets_export.class.php index 2ad00da..de95848 100755 --- a/lib/admin_presets_export.class.php +++ b/lib/admin_presets_export.class.php @@ -184,7 +184,7 @@ public function download_xml() { $tagname = strtoupper($plugin); - // To aviod xml slash problems. + // To avoid xml slash problems. if (strstr($tagname, '/') != false) { $tagname = str_replace('/', '__', $tagname); } @@ -209,7 +209,7 @@ public function download_xml() { } } - $xmlwriter->full_tag(strtoupper($setting->name), $setting->value, $attributes); + $xmlwriter->full_tag(strtoupper(trim($setting->name)), trim($setting->value), $attributes); } $xmlwriter->end_tag('SETTINGS'); diff --git a/lib/admin_presets_load.class.php b/lib/admin_presets_load.class.php index 18369d5..1572324 100755 --- a/lib/admin_presets_load.class.php +++ b/lib/admin_presets_load.class.php @@ -59,7 +59,7 @@ public function execute() { // Only for selected items. $appliedchanges = array(); $unnecessarychanges = array(); - foreach (filter_input_array(INPUT_POST) as $varname => $value) { + foreach ($_POST as $varname => $value) { unset($updatesetting); @@ -148,6 +148,8 @@ public function execute() { $appliedchanges[$varname]->oldvisiblevalue = $sitesetting->get_visiblevalue(); $appliedchanges[$varname]->visiblevalue = $presetsetting->get_visiblevalue(); + purge_caches(); + // Unnecessary changes (actual setting value). } else { $unnecessarychanges[$varname] = $presetsetting; diff --git a/lib/admin_presets_settings_types.php b/lib/admin_presets_settings_types.php index cc0dc66..6e64cb8 100755 --- a/lib/admin_presets_settings_types.php +++ b/lib/admin_presets_settings_types.php @@ -838,6 +838,270 @@ protected function set_visiblevalue() { } } +class admin_preset_admin_setting_configstoredfile extends admin_preset_setting { + + private $base64; + private $extensions = []; + private $filenames = []; + private $separator = '_separator_'; + private $multiseparator = '_multis_'; + + public function __construct(admin_setting $settingdata, $dbsettingvalue) { + + // Check if preview context (multiseparator present or pathinfo extension not set) + $pathinfo = pathinfo($dbsettingvalue); + if (!isset($pathinfo['extension']) || strpos($dbsettingvalue, $this->multiseparator) !== false) { + // Manage multiple files + $multisplits = explode($this->multiseparator, $dbsettingvalue); + foreach ($multisplits as $multisplit) { + $split = explode($this->separator, $multisplit); + if (!empty($split[2])) { + $this->filenames[$split[2]] = $split[2]; + $this->extensions[$split[2]] = $split[1]; + if (base64_encode(base64_decode($split[0], true)) === $split[0]) { + $this->base64 .= $split[0] . $this->separator . $split[1] . $this->separator . $split[2] . $this->multiseparator; // We store the base64 with his extension and filename. + } + } + } + } else { + $this->base64 = $this->get_current_files($settingdata->plugin, $settingdata->name); + } + + parent::__construct($settingdata, $dbsettingvalue); + + } + + /** + * Defines the value as equal to the base64 of the image followed by its extension + * (to be able to retrieve the extension more easily) + * + * @param string $value + * @return boolean Cleaned or not, but always true + */ + protected function set_value($value) { + if ($this->base64) { + $this->value = $this->base64; + } else { + $this->value = $value; + } + return true; + } + + /** + * Defines the visible value as an html image built from the base64 of the image + * (Because it is stored as a base64 in the xml and in the database) + */ + protected function set_visiblevalue() { + $this->visiblevalue = ''; + + if ($this->base64) { + $multisplits = explode($this->multiseparator, $this->base64); + foreach ($multisplits as $multisplit) { + if (!empty($multisplit)) { + $split = explode($this->separator, $multisplit); + if ($this->checkImageExtension($this->extensions[$split[2]])) { + // Remove the extension. + $base64 = str_replace($this->separator . $this->extensions[$split[2]], '', $split[0]); + $base64 = str_replace($this->separator . $this->filenames[$split[2]], '', $base64); + // Render a preview of the image instead of the base64 value. + $this->visiblevalue .= ''; + } else { + $this->visiblevalue .= '' . + $this->filenames[$split[2]] . ' ' . substr(base64_decode($split[0]), 0, 250) . '...'; + } + } + } + } + } + + /** + * Stores the setting into database, logs the change and returns the config_log inserted id + * + * @param bool $name + * @param mixed $value + * @return integer config_log inserted id + * @throws dml_exception + * @throws moodle_exception + */ + public function save_value($name = false, $value = null) { + + // Object values if no arguments. + if ($value === null) { + $value = $this->value; + } + if (!$name) { + $name = $this->settingdata->name; + } + + // Plugin name or null. + $plugin = $this->settingdata->plugin; + if ($plugin == 'none' || $plugin == '') { + $plugin = null; + } + + // Manage multiple files + $i = 0; + $filename = ''; + $configlogid = ''; + $fs = get_file_storage(); + $multisplits = explode($this->multiseparator, $value); + foreach ($multisplits as $multisplit) { + $split = explode($this->separator, $multisplit); + // Manage filename for config + if ($i == 0) { + $filename = $split[2]; + } + $i++; + if (!empty($split[2])) { + $currentfile = $this->get_file_from_fs($plugin, $name, $split[2]); + if ($currentfile) { + $oldvalue = base64_encode($currentfile->get_content()); + // skip same value + if ($oldvalue == $split[0]) { + continue; + } + // Delete the old file. + $currentfile->delete(); + } + // Prepare new file record object. + $fileinfo = [ + 'contextid' => 1, + 'component' => $plugin, + 'filearea' => $this->fileareaMapping($plugin, $name), + 'itemid' => 0, + 'filepath' => '/', + 'filename' => $split[2] + ]; + $fs->create_file_from_string($fileinfo, base64_decode($split[0])); + } + } + // update config & log + if ($filename) { + unset_config($name, $plugin); + set_config($name, '/' . $filename, $plugin); + $configlogid = $this->to_log($plugin, $name, $filename, get_config($plugin, $name) ?? ''); + } + + return $configlogid; + } + + /** + * Get the file actually stored in the configuration + * + * @param $plugin + * @param $name + * @return mixed + * @throws dml_exception + */ + private function get_current_files($plugin, $name) { + global $DB; + + $content = ''; + $datas = [ + 'component' => $plugin, + 'filearea' => $this->fileareaMapping($plugin, $name), + 'itemid' => 0, + 'contextid' => 1, + ]; + // Retrieve the file. So we can convert it to base64 (to add it in the xml or compare with new value in "load" context). + $dbfiles = $DB->get_records_sql( + 'SELECT * FROM {files} + WHERE component = :component + AND filearea = :filearea + AND itemid = :itemid + AND contextid = :contextid + ', + $datas + ); + + if ($dbfiles) { + $fs = get_file_storage(); + foreach ($dbfiles as $dbfile) { + $pathinfo = pathinfo($dbfile->filename); + if (!empty($pathinfo['extension']) && !empty($pathinfo['basename'])) { + $this->filenames[$pathinfo['basename']] = $pathinfo['basename']; + $this->extensions[$pathinfo['basename']] = $pathinfo['extension']; + $content .= base64_encode($fs->get_file_by_hash($dbfile->pathnamehash)->get_content()) . $this->separator . $pathinfo['extension'] . $this->separator . $pathinfo['basename'] . $this->multiseparator; + } + } + } + return $content; + } + + /** + * @param $plugin + * @param $name + * @param $filename + * @return bool|stored_file|null + * @throws dml_exception + */ + private function get_file_from_fs($plugin, $name, $filename) { + global $DB; + + $datas = [ + 'component' => $plugin, + 'filearea' => $this->fileareaMapping($plugin, $name), + 'itemid' => 0, + 'contextid' => 1, + ]; + if ($filename) { + $wherefilename = 'filename = "' . $filename . '"'; + } else { + // Must be set. + $wherefilename = 'filename NOT IN ("", ".")'; + } + // Retrieve the file. So we can convert it to base64 (to add it in the xml or compare with new value in "load" context). + $dbfile = $DB->get_record_sql( + 'SELECT * FROM {files} + WHERE component = :component + AND filearea = :filearea + AND itemid = :itemid + AND contextid = :contextid + AND ' . $wherefilename, + $datas + ); + if ($dbfile) { + $fs = get_file_storage(); + return $fs->get_file_by_hash($dbfile->pathnamehash); + } + return null; + } + + /** + * @param $extension + * @return bool + */ + private function checkImageExtension($extension) + { + $img = ['gif' , 'jpeg' , 'jpg' , 'jif' , 'jfif' , 'png' , 'bmp', 'svg', 'tiff']; + + if (in_array($extension, $img)) { + return true; + } + return false; + } + + /** + * Because some plugins (like Theme fordson use another filearea name than param name for associated files + * + * @param $plugin + * @param $name + * @return string + */ + private function fileareaMapping($plugin, $name) + { + $filearea = $name; + if ($plugin == 'theme_fordson') { + if ($name == 'presetfiles') { + $filearea = 'preset'; + } + } + return $filearea; + } + +} + class admin_preset_admin_setting_configcheckbox_with_advanced extends admin_preset_admin_setting_configcheckbox { public function __construct(admin_setting $settingdata, $dbsettingvalue) { diff --git a/version.php b/version.php index 54cc6df..59b34df 100755 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021052700; +$plugin->version = 2021052701; $plugin->requires = 2016052300; // Requires this Moodle version $plugin->component = 'block_admin_presets'; $plugin->release = '3.4';