You are here

function filefield_paths_filefield_paths_process_file in File (Field) Paths 8

Same name and namespace in other branches
  1. 5 filefield_paths.module \filefield_paths_filefield_paths_process_file()
  2. 6 filefield_paths.module \filefield_paths_filefield_paths_process_file()
  3. 7 modules/filefield_paths.inc \filefield_paths_filefield_paths_process_file()

Implements hook_filefield_paths_process_file().

File

./filefield_paths.inc, line 49
File (Field) Paths module integration.

Code

function filefield_paths_filefield_paths_process_file(ContentEntityInterface $entity, FileFieldItemList $field, array $settings = []) {

  /** @var \Drupal\field\Entity\FieldConfig $field_config */
  $field_config = $field
    ->getFieldDefinition();

  /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */
  $field_storage = $field_config
    ->getFieldStorageDefinition();
  $file_system = \Drupal::service('file_system');

  // Check that the destination is writeable.
  $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
  $wrappers = $stream_wrapper_manager
    ->getWrappers(StreamWrapperInterface::WRITE);
  $destination_scheme_name = $field_storage
    ->getSetting('uri_scheme');

  /** @var \Drupal\Core\StreamWrapper\StreamWrapperInterface $temporary_scheme */
  $temporary_scheme = $stream_wrapper_manager
    ->getViaUri(\Drupal::config('filefield_paths.settings')
    ->get('temp_location'));
  $temporary_scheme_name = key($stream_wrapper_manager
    ->getWrappers($temporary_scheme
    ->getType()));
  $schemas = [
    $temporary_scheme_name,
    $destination_scheme_name,
  ];

  /** @var \Drupal\file\Entity\File $file */
  foreach ($field
    ->referencedEntities() as $file) {

    /** @var \Drupal\Core\StreamWrapper\StreamWrapperInterface $source_scheme */
    $source_scheme = $stream_wrapper_manager
      ->getViaUri($file
      ->getFileUri());
    $source_scheme_name = key($stream_wrapper_manager
      ->getWrappers($source_scheme
      ->getType()));
    if (in_array($source_scheme_name, $schemas) && !empty($wrappers[$destination_scheme_name])) {

      // Process file if this is a new entity, 'Active updating' is set or
      // file wasn't previously attached to the entity.
      if (!$entity
        ->isNew() && isset($entity->original) && empty($settings['active_updating']) && !$entity->original->{$field
        ->getName()}
        ->isEmpty()) {

        /** @var \Drupal\file\Entity\File $original_file */
        foreach ($entity->original->{$field
          ->getName()}
          ->referencedEntities() as $original_file) {
          if ($original_file
            ->id() == $file
            ->id()) {
            continue 2;
          }
        }
      }
      $token_data = [
        'file' => $file,
        $entity
          ->getEntityTypeId() => $entity,
      ];

      // Process filename.
      $settings['file_name']['options']['context'] = 'file_name';
      $name = $file
        ->getFilename();
      if (!empty($settings['file_name']['value'])) {
        $name = filefield_paths_process_string($settings['file_name']['value'], $token_data, $settings['file_name']['options']);
      }

      // Process filepath.
      $settings['file_path']['options']['context'] = 'file_path';
      $path = filefield_paths_process_string($settings['file_path']['value'], $token_data, $settings['file_path']['options']);
      $destination = \Drupal::service('stream_wrapper_manager')
        ->normalizeUri($field_storage
        ->getSetting('uri_scheme') . '://' . $path . DIRECTORY_SEPARATOR . $name);

      // Ensure file uri is no more than 255 characters.
      if (mb_strlen($destination) > 255) {
        \Drupal::logger('filefield_paths')
          ->info(t('File path was truncated'));
        $pathinfo = pathinfo($destination);
        $destination = mb_substr($destination, 0, 254 - mb_strlen($pathinfo['extension'])) . ".{$pathinfo['extension']}";
      }

      // Finalize file if necessary.
      if ($file
        ->getFileUri() !== $destination) {
        $dirname = $file_system
          ->dirname($destination);
        if (\Drupal::service('file_system')
          ->prepareDirectory($dirname, FileSystem::CREATE_DIRECTORY) && ($new_file = file_move($file, $destination))) {

          // Create redirect from old location.
          if (\Drupal::moduleHandler()
            ->moduleExists('redirect') && !empty($settings['redirect']) && $settings['active_updating']) {
            \Drupal::service('filefield_paths.redirect')
              ->createRedirect($file
              ->getFileUri(), $new_file
              ->getFileUri(), $file
              ->language());
          }

          // Remove any old empty directories.
          // @TODO - Add test for this.
          $paths = explode('/', str_replace("{$source_scheme_name}://", '', $file_system
            ->dirname($file
            ->getFileUri())));
          while ($paths) {
            if (@$file_system
              ->rmdir("{$source_scheme_name}://" . implode('/', $paths)) == TRUE) {
              array_pop($paths);
              continue;
            }
            break;
          }
        }
        else {
          \Drupal::logger('filefield_paths')
            ->notice(t('The file %old could not be moved to the destination of %new. Ensure your permissions are set correctly.', [
            '%old' => $file
              ->getFileUri(),
            '%new' => $file
              ->getFileUri(),
          ]));
        }
      }
    }
  }
}