The following protected methods in \Drupal\feeds\Feeds\Target\File have been deprecated in feeds:3.3.0 and will be removed in feeds:4.0.0:
getFileName()getContent()writeData()getFileLegacy()
File resolution logic has been moved to the feeds.file_resolver service. Custom modules that extend the File target and override these methods should migrate to decorating the feeds.file_resolver service instead. The File resolver service also has extra features to deal with files that the File target did not have, such as accepting a server path as input.
Impact
Modules that override getFileName(), getContent(), or writeData() in a File target subclass will receive deprecation warnings. The overrides continue to work during the deprecation period (until feeds:4.0.0) via a legacy code path.
Migration
Use a service decorator that extends FileResolver and overrides the appropriate protected method. Register it with decorates: feeds.file_resolver in your module's services.yml.
getContent() — adding authentication
Before:
class MyFileTarget extends File { protected function getContent($url) { $response = $this->client->request('GET', $url, [ 'headers' => ['Authorization' => 'Bearer ' . $this->getToken()], ]); if ($response->getStatusCode() >= 400) { throw new TargetValidationException('Download failed'); } return (string) $response->getBody(); } }
After: Decorate FileResolver and override downloadFile():
class MyFileResolver extends FileResolver { protected function downloadFile(string $url): string { $options = [ 'headers' => ['Authorization' => 'Bearer ' . $this->getAuthToken($url)], ]; $response = $this->client->request('GET', $url, $options); if ($response->getStatusCode() >= 400) { throw new DownloadException($url, $response->getStatusCode()); } return (string) $response->getBody(); } }
getFileName() — custom filename format
Before:
class MyFileTarget extends File { protected function getFileName($url) { $filename = parent::getFileName($url); return date('Y-m-d') . '-' . $filename; } }
After: Decorate FileResolver and override getFileNameFromUrl():
class MyFileResolver extends FileResolver { protected function getFileNameFromUrl(string $url): string { $filename = parent::getFileNameFromUrl($url); return date('Y-m-d') . '-' . $filename; } }
writeData() — pre-processing content before save
Before:
class MyFileTarget extends File { protected function writeData($data, $destination = NULL, $replace = FileExists::Rename) { $data = $this->processContent($data); return parent::writeData($data, $destination, $replace); } }
After: Decorate FileResolver and override saveFileAndCreateEntity():
class MyFileResolver extends FileResolver { protected function saveFileAndCreateEntity(string $content, string $destination, FileExists|int|string $replace, array $options = []): ?FileInterface { $content = $this->processContent($content); return parent::saveFileAndCreateEntity($content, $destination, $replace, $options); } }
Service definition
Register the decorator in mymodule.services.yml:
services: mymodule.file_resolver: class: Drupal\mymodule\Utility\MyFileResolver decorates: feeds.file_resolver factory: Drupal\mymodule\Utility\MyFileResolver::create arguments: ['@service_container']
The decorator extends FileResolver and implements a create() factory (see docs/EXTENDING_FILERESOLVER.md). The original service is available as @mymodule.file_resolver.inner if you need to delegate to it.
See docs/EXTENDING_FILERESOLVER.md for detailed examples.