Problem/Motivation
We need to add support for the @drupal_private_files tag. In D7 the private file system was a variable, in D8 it is a settings.php entry. This doesn't make it impossible to work with, but it requires a module to influence Drupal's runtime.
The private stream wrapper is registered as a service provider if the path exists in the settings definition:
From \Drupal\Core\CoreServiceProvider::register:
// Only register the private file stream wrapper if a file path has been set.
if (Settings::get('file_private_path')) {
$container->register('stream_wrapper.private', 'Drupal\Core\StreamWrapper\PrivateStream')
->addTag('stream_wrapper', ['scheme' => 'private']);
}
The settings object is a singleton that can we reconstructed. We can either dynamically modify the settings.php file, or maybe the panopoly_test module can read a state value entry to turn on and off this value. Then the Behat step just inserts the value into the state key/value storage and remove it.
Old code:
/**
* Configure a private files path if one isn't already configured.
*
* @BeforeScenario @api&&@drupal_private_files
*/
public function configurePrivateFiles($event) {
$file_private_path = variable_get('file_private_path', '');
if (empty($file_private_path)) {
$file_public_path = variable_get('file_public_path', conf_path() . '/files');
if (empty($file_public_path)) {
throw new \Exception('Files must be configured for @drupal_private_files tests to work!');
}
// Set flag for later cleanup.
$this->private_path_overridden = TRUE;
// Create and setup the private path.
$file_private_path = $file_public_path . '/' . 'private';
variable_set('file_private_path', $file_private_path);
}
}
/**
* Clean up our temporary private files path.
*
* @AfterScenario @api&&@drupal_private_files
*/
public function cleanupPrivateFiles($event) {
if ($this->private_path_overridden) {
variable_del('file_private_path');
}
}
Steps to reproduce
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork panopoly-3224020
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mglamanComment #3
mglamanOne thing I realized: we never tested the private file system in 1.x. The old media module simply allowed choosing, so we had a private file system added so we would trigger that step of the upload process.
Every scenario just had
The upload destination is a field storage setting. So
field.storage.media.field_media_imagecontrols theuri_scheme.The upload gets the upload location directly from the field itself:
The upload location is derived from the settings.
I'm uploading an MR which allows setting the private file system directory. This registers it. But the existing steps are not required since you do not pick the upload destination anymore.
Comment #5
mglamanI wonder if we should just delete these items, since they're no longer relevant as part of the upload process.
Comment #6
mglamanComment #7
dsnopekHm, yeah, if that's no longer a thing I guess we should just delete it.
However, I wonder if this means we'll be missing a feature that users may be depending on? I don't think it matters much for file fields, but for WYSIWYG, folks may want to be able to upload files that are private, and I'm not sure how to support that. I guess I could imagine a file upload widget that let you pick between public/private? Or, an additional field on the Media entity for public/private that we'd use in a hook to switch it just before it's saved? It probably makes sense to create a placeholder issue for that just in case.
Comment #9
mglamanThis would be pretty hard. The way URI schemes were changed in Drupal 8 makes it a bit harder.
The URI scheme is on the field storage definition itself:
The upload location is fetched from \Drupal\file\Plugin\Field\FieldType\FileItem::doGetUploadLocation
As far as I can see, there is no way to dynamically choose (hooks or swapping) the URI scheme for a file. You'd need to have a "private" version of each media type.. and that's not fun.
Now, what could be done is altering the source field on the media type.. maybe. So the media types could have a "public" and a "private" URI scheme field. So a "private" boolean to control which field.
\Drupal\media\MediaSourceBase::getSourceFieldValue is what fetches the value. The default configuration is read from
$source_field = $this->configuration['source_field'];. But, it does receive the media entity.So we'd need to swap the File media source plugin class with a customized one. Then, in \Drupal\media\MediaSourceBase::getSourceFieldValue we can check if the media entity is "private" and switch to the proper source field.
The problem is \Drupal\media\MediaSourceBase::getSourceFieldDefinition. This only has the media type. We'd need to also customize the FileUploadForm in media_library (or shoot, in entity_browser?) for \Drupal\media_library\Form\FileUploadForm::createFileItem. This gets the source field definition from the media type's config.
Basically, I think it may be impossible.
If it is, it is unfortunately lost due to Drupal core. And, in WYSIWYG, would embedded private files even be filtered out to unprivledged users? Or would the links persist and that user would see a file name and then a dead link?
Comment #10
dsnopekCurrently, I think the links are left in place, but if you don't have access you'll get an access denied page if you follow the link.
Anyway, it'd be great to get this info on a placeholder issue for now (so, when a user brings this up later, we'll have all your research).
And I think the only thing left to do here is this:
Comment #12
mglamanCreated #3228144: Allow users to select upload destination (public, private) when adding media via entity browser / media library. Opening MR to remove commented out steps
Comment #14
mglamanMR: https://gitlab.com/panopoly/panopoly/-/merge_requests/9
Comment #16
dsnopekThanks!