blacksmith-8.x-1.x-dev/src/Blacksmith/EntityImporter/FieldFormatter/FileFieldFormatter.php
src/Blacksmith/EntityImporter/FieldFormatter/FileFieldFormatter.php
<?php namespace Drupal\blacksmith\Blacksmith\EntityImporter\FieldFormatter; use Drupal\Component\Utility\Random; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Utility\Token; use Drupal\blacksmith\Exception\BlacksmithImportSkipField; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Component\Plugin\Exception\PluginNotFoundException; /** * Class ImageFieldFormatter. * * @package Drupal\blacksmith\Blacksmith\EntityImporter\FieldFormatter */ class FileFieldFormatter extends FieldFormatterBase implements ContainerInjectionInterface { /** * Drupal token service. * * @var \Drupal\Core\Utility\Token */ protected $token; /** * Drupal file system service. * * @var \Drupal\Core\File\FileSystem */ protected $fileSystem; /** * Default file scheme. * * @var string */ protected $fileScheme; /** * File storage. * * @var \Drupal\file\FileStorage */ protected $fileStorage; /** * @var \Drupal\Component\Utility\Random */ protected $random; /** * {@inheritdoc} */ public function __construct($fieldDefinition, Token $token, FileSystemInterface $fileSystem, EntityTypeManagerInterface $entityTypeManager, ConfigFactoryInterface $configFactory) { parent::__construct($fieldDefinition); $this->token = $token; $this->fileSystem = $fileSystem; $this->fileScheme = $configFactory->get('system.file')->get('default_scheme'); $this->random = new Random(); try { $this->fileStorage = $entityTypeManager->getStorage('file'); } catch (PluginNotFoundException | InvalidPluginDefinitionException $exception) { $this->logger->error($exception->getMessage()); } } /** * {@inheritDoc} */ public static function create(ContainerInterface $container, FieldDefinitionInterface $fieldDefinition = NULL) { return new static( $fieldDefinition, $container->get('token'), $container->get('file_system'), $container->get('entity_type.manager'), $container->get('config.factory') ); } /** * {@inheritdoc} * * @throws \Drupal\blacksmith\Exception\BlacksmithImportSkipField * @throws \Drupal\Core\Entity\EntityStorageException */ protected function formatUniqueValue($value) : array { // Assume that a file ID is given if the value is a number. if (is_int($value)) { return parent::formatUniqueValue($value); } // Make sure that the value is always provided as an array. if (is_string($value)) { return $this->formatUniqueValue(['src' => $value]); } // Load the file from the src and save it in the file directory. if (isset($value['src'])) { // Fetch the file from the URL. // @todo Find a way to get a file that is inside the repository. $data = file_get_contents($value['src']); if (!$data) { throw new BlacksmithImportSkipField('Unable to get the file "' . $value['src'] . '"', NULL); } // Set the filename. if (isset($value['name'])) { $filename = trim($value['name']); } else { $fileHeaders = self::parseHeaders($http_response_header); $fileType = explode('/', $fileHeaders['Content-Type'])[1]; // @todo Do not set the name here. The saveData method will do it. $filename = $this->random->name(16) . '.' . $fileType; } // Set the file directory and file path. $directory = $value['file_directory'] ?? $this->fieldDefinition->getSetting('file_directory'); $directory = $this->token->replace($directory); $filePath = (empty($directory)) ? "$this->fileScheme://$filename" : "$this->fileScheme://$directory/$filename"; // @todo Find a proper way to name the file. $uri = $this->fileSystem->saveData($data, $filePath, FileSystemInterface::EXISTS_RENAME); $file = $this->fileStorage->create([ 'filename' => $filename, 'uri' => $uri, 'status' => 1, ]); $file->save(); return [ 'title' => $value['title'] ?? '', 'target_id' => $file->id(), ]; } throw new BlacksmithImportSkipField('You need to specify the image "src"'); } /** * Formats the values returned in the header response. * * @param array $headers * Header response from file_get_contents. * * @return array * The formatted header response. * * @see file_get_contents() * @see $http_response_header */ public static function parseHeaders(array $headers) : array { $head = []; foreach ($headers as $key => $value) { $t = explode(':', $value, 2); if (isset($t[1])) { $head[trim($t[0])] = trim($t[1]); } else { $head[] = $value; if (preg_match("#HTTP/[\d.]+\s+([\d]+)#", $value, $out)) { $head['response_code'] = (int) $out[1]; } } } return $head; } }