MDL-62003 privacy: Consistently export files into _files folder

There were two major issues with the previous implementation:

* The exported folder name was localised so it was "Files" or "Soubory"
  etc depending on the current language. Yet URLs referring to the files
  in that folder were always rewritten with hard-coded English "files".
* Files from all fileareas and itemids were all exported to a single
  target directory. So if there were two files with the same name being
  exported from multiple areas (such as submission_content and
  submission_attachment in the workshop module), one would overwrite
  another.

The patch addresses these issues as follows:

* To unify the folder name and also to minimise the risk of conflict
  with a subcontext folder, we now always export stored files under
  "_files" folder.
* Under that folder, there is a subdirectory with the area name and then
  eventually another subdirectory with non-zero itemid. And there
  finally the stored_file is exported to under its own file path.
This commit is contained in:
David Mudrák 2018-04-18 13:12:47 +02:00
parent 20bf0c45ff
commit 3ecbf154db
3 changed files with 102 additions and 16 deletions

View file

@ -159,7 +159,7 @@ class moodle_content_writer implements content_writer {
* @return string The processed string
*/
public function rewrite_pluginfile_urls(array $subcontext, $component, $filearea, $itemid, $text) : string {
return str_replace('@@PLUGINFILE@@/', 'files/', $text);
return str_replace('@@PLUGINFILE@@/', $this->get_files_target_path($component, $filearea, $itemid).'/', $text);
}
/**
@ -188,11 +188,12 @@ class moodle_content_writer implements content_writer {
*/
public function export_file(array $subcontext, \stored_file $file) : content_writer {
if (!$file->is_directory()) {
$subcontextextra = [
get_string('files'),
$file->get_filepath(),
];
$path = $this->get_path(array_merge($subcontext, $subcontextextra), $file->get_filename());
$pathitems = array_merge(
$subcontext,
[$this->get_files_target_path($file->get_component(), $file->get_filearea(), $file->get_itemid())],
[$file->get_filepath()]
);
$path = $this->get_path($pathitems, $file->get_filename());
check_dir_exists(dirname($path), true, true);
$this->files[$path] = $file;
}
@ -285,6 +286,26 @@ class moodle_content_writer implements content_writer {
return preg_replace('@' . DIRECTORY_SEPARATOR . '+@', DIRECTORY_SEPARATOR, $filepath);
}
/**
* Get a path within a subcontext where exported files should be written to.
*
* @param string $component The name of the component that the files belong to.
* @param string $filearea The filearea within that component.
* @param string $itemid Which item those files belong to.
* @return string The path
*/
protected function get_files_target_path($component, $filearea, $itemid) : string {
// We do not need to include the component because we organise things by context.
$parts = ['_files', $filearea];
if (!empty($itemid)) {
$parts[] = $itemid;
}
return implode(DIRECTORY_SEPARATOR, $parts);
}
/**
* Write the data to the specified path.
*

View file

@ -385,6 +385,10 @@ class content_writer implements \core_privacy\local\request\content_writer {
/**
* Prepare a text area by processing pluginfile URLs within it.
*
* Note that this method does not implement the pluginfile URL rewriting. Such a job tightly depends on how the
* actual writer exports files so it can be reliably tested only in real writers such as
* {@link core_privacy\local\request\moodle_content_writer}.
*
* @param array $subcontext The location within the current context that this data belongs.
* @param string $component The name of the component that the files belong to.
* @param string $filearea The filearea within that component.
@ -393,7 +397,7 @@ class content_writer implements \core_privacy\local\request\content_writer {
* @return string The processed string
*/
public function rewrite_pluginfile_urls(array $subcontext, $component, $filearea, $itemid, $text) : string {
return str_replace('@@PLUGINFILE@@/', 'files/', $text);
return $text;
}
/**