MDL-35434 new stored file config setting

This commit is contained in:
Petr Škoda
2013-04-15 10:57:47 +08:00
committed by Damyon Wiese
parent 986adc066c
commit 6ddc9278ff
+200 -6
View File
@@ -1688,6 +1688,24 @@ abstract class admin_setting {
$this->updatedcallback = $functionname;
}
/**
* Execute postupdatecallback if necessary.
* @param mixed $original original value before write_setting()
* @return bool true if changed, false if not.
*/
public function post_write_settings($original) {
// Comparison must work for arrays too.
if (serialize($original) === serialize($this->get_setting())) {
return false;
}
$callbackfunction = $this->updatedcallback;
if (!empty($callbackfunction) and function_exists($callbackfunction)) {
$callbackfunction($this->get_full_name());
}
return true;
}
/**
* Is setting related to query text - used when searching
* @param string $query
@@ -6422,7 +6440,8 @@ function admin_write_settings($formdata) {
$count = 0;
foreach ($settings as $fullname=>$setting) {
$original = serialize($setting->get_setting()); // comparison must work for arrays too
/** @var $setting admin_setting */
$original = $setting->get_setting();
$error = $setting->write_setting($data[$fullname]);
if ($error !== '') {
$adminroot->errors[$fullname] = new stdClass();
@@ -6430,12 +6449,8 @@ function admin_write_settings($formdata) {
$adminroot->errors[$fullname]->id = $setting->get_id();
$adminroot->errors[$fullname]->error = $error;
}
if ($original !== serialize($setting->get_setting())) {
if ($setting->post_write_settings($original)) {
$count++;
$callbackfunction = $setting->updatedcallback;
if (function_exists($callbackfunction)) {
$callbackfunction($fullname);
}
}
}
@@ -8118,6 +8133,185 @@ class admin_setting_configcolourpicker extends admin_setting {
}
}
/**
* Class used for uploading of one file into file storage,
* the file name is stored in config table.
*
* Please note you need to implement your own '_pluginfile' callback function,
* this setting only stores the file, it does not deal with file serving.
*
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_configstoredfile extends admin_setting {
/** @var array file area options - should be one file only */
protected $options;
/** @var string name of the file area */
protected $filearea;
/** @var int intemid */
protected $itemid;
/** @var string used for detection of changes */
protected $oldhashes;
/**
* Create new stored file setting.
*
* @param string $name low level setting name
* @param string $visiblename human readable setting name
* @param string $description description of setting
* @param mixed $filearea file area for file storage
* @param int $itemid itemid for file storage
* @param array $options file area options
*/
public function __construct($name, $visiblename, $description, $filearea, $itemid = 0, array $options = null) {
parent::__construct($name, $visiblename, $description, '');
$this->filearea = $filearea;
$this->itemid = $itemid;
$this->options = (array)$options;
}
/**
* Applies defaults and returns all options.
* @return array
*/
protected function get_options() {
global $CFG;
require_once("$CFG->libdir/filelib.php");
require_once("$CFG->dirroot/repository/lib.php");
$defaults = array(
'mainfile' => '', 'subdirs' => 0, 'maxbytes' => -1, 'maxfiles' => 1,
'accepted_types' => '*', 'return_types' => FILE_INTERNAL, 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED,
'context' => context_system::instance());
foreach($this->options as $k => $v) {
$defaults[$k] = $v;
}
return $defaults;
}
public function get_setting() {
return $this->config_read($this->name);
}
public function write_setting($data) {
global $USER;
// Let's not deal with validation here, this is for admins only.
$current = $this->get_setting();
if (empty($data)) {
// Most probably applying default settings.
if ($current === null) {
return ($this->config_write($this->name, '') ? '' : get_string('errorsetting', 'admin'));
}
return '';
} else if (!is_number($data)) {
// Draft item id is expected here!
return get_string('errorsetting', 'admin');
}
$options = $this->get_options();
$fs = get_file_storage();
$component = is_null($this->plugin) ? 'core' : $this->plugin;
$this->oldhashes = null;
if ($current) {
$hash = sha1('/'.$options['context']->id.'/'.$component.'/'.$this->filearea.'/'.$this->itemid.$current);
if ($file = $fs->get_file_by_hash($hash)) {
$this->oldhashes = $file->get_contenthash().$file->get_pathnamehash();
}
unset($file);
}
if ($fs->file_exists($options['context']->id, $component, $this->filearea, $this->itemid, '/', '.')) {
// Make sure the settings form was not open for more than 4 days and draft areas deleted in the meantime.
$usercontext = context_user::instance($USER->id);
if (!$fs->file_exists($usercontext->id, 'user', 'draft', $data, '/', '.')) {
return get_string('errorsetting', 'admin');
}
}
file_save_draft_area_files($data, $options['context']->id, $component, $this->filearea, $this->itemid, $options);
$files = $fs->get_area_files($options['context']->id, $component, $this->filearea, $this->itemid, 'sortorder,filepath,filename', false);
$filepath = '';
if ($files) {
/** @var stored_file $file */
$file = reset($files);
$filepath = $file->get_filepath().$file->get_filename();
}
return ($this->config_write($this->name, $filepath) ? '' : get_string('errorsetting', 'admin'));
}
public function post_write_settings($original) {
$options = $this->get_options();
$fs = get_file_storage();
$component = is_null($this->plugin) ? 'core' : $this->plugin;
$current = $this->get_setting();
$newhashes = null;
if ($current) {
$hash = sha1('/'.$options['context']->id.'/'.$component.'/'.$this->filearea.'/'.$this->itemid.$current);
if ($file = $fs->get_file_by_hash($hash)) {
$newhashes = $file->get_contenthash().$file->get_pathnamehash();
}
unset($file);
}
if ($this->oldhashes === $newhashes) {
$this->oldhashes = null;
return false;
}
$this->oldhashes = null;
$callbackfunction = $this->updatedcallback;
if (!empty($callbackfunction) and function_exists($callbackfunction)) {
$callbackfunction($this->get_full_name());
}
return true;
}
public function output_html($data, $query = '') {
global $PAGE, $CFG;
$options = $this->get_options();
$id = $this->get_id();
$elname = $this->get_full_name();
$draftitemid = file_get_submitted_draft_itemid($elname);
$component = is_null($this->plugin) ? 'core' : $this->plugin;
file_prepare_draft_area($draftitemid, $options['context']->id, $component, $this->filearea, $this->itemid, $options);
// Filemanager form element implementation is far from optimal, we need to rework this if we ever fix it...
require_once("$CFG->dirroot/lib/form/filemanager.php");
$fmoptions = new stdClass();
$fmoptions->mainfile = $options['mainfile'];
$fmoptions->maxbytes = $options['maxbytes'];
$fmoptions->maxfiles = $options['maxfiles'];
$fmoptions->client_id = uniqid();
$fmoptions->itemid = $draftitemid;
$fmoptions->subdirs = $options['subdirs'];
$fmoptions->target = $id;
$fmoptions->accepted_types = $options['accepted_types'];
$fmoptions->return_types = $options['return_types'];
$fmoptions->context = $options['context'];
$fmoptions->areamaxbytes = $options['areamaxbytes'];
$fm = new form_filemanager($fmoptions);
$output = $PAGE->get_renderer('core', 'files');
$html = $output->render($fm);
$html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
$html .= '<input value="" id="'.$id.'" type="hidden" />';
return format_admin_setting($this, $this->visiblename,
'<div class="form-filemanager">'.$html.'</div>', $this->description, true, '', '', $query);
}
}
/**
* Administration interface for user specified regular expressions for device detection.
*