So I had to make a function that I pass a bundle and field name too. Both are in the form of strings. The function then returns a uri with the tokens replaced.
function getFileDirectory($media_type, $field_name) {
// Fetch all field definitions for the media bundle.
$fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('media', $media_type);
foreach ($fields as $field => $field_definition) {
$bundle = $field_definition->getTargetBundle();
// Look for the field we need
if ($bundle == $media_type && $field == $field_name) {
// Get the settings for the field, in order to start building the directory path
$settings = $field_definition->getSettings();
$file_directory_path_tokens = $settings['file_directory'];
$uri_scheme = $settings['uri_scheme'];
// Convert tokens in files directory string
$token = \Drupal::token();
$directory_path = $token->replace($file_directory_path_tokens);
// If there is a value for the file directory setting on the file field, ensure the directory exists,
// if not create it.
if ($directory_path) {
$directory = $uri_scheme . '://' . $directory_path;
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
$file_system->prepareDirectory($directory, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
return $directory;
}
// Otherwise just return the uri_scheme ie public:// or private://
else {
return $uri_scheme . '://';
}
}
}
}
This is specific for media entities. It wouldn't be too much bother to extend it to be more generic to cover all entities.
I hope this saves someone some pain.