moodle_rest-1.0.1/modules/moodle_rest_migrate/src/Plugin/migrate/process/MoodleFile.php

modules/moodle_rest_migrate/src/Plugin/migrate/process/MoodleFile.php
<?php

namespace Drupal\moodle_rest_migrate\Plugin\migrate\process;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StreamWrapper\LocalStream;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateSkipProcessException;
use Drupal\migrate\Row;
use Drupal\file\FileInterface;
use Drupal\file\Entity\File;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\migrate\Plugin\migrate\process\FileProcessBase;
use Drupal\moodle_rest\Services\MoodleRest;

/**
 * Imports a file from Moodle.
 *
 * Required configuration keys:
 * - source: The source path or URI, e.g. '/path/to/foo.txt' or
 *   'public://bar.txt'.
 *
 * Optional configuration keys:
 * - destination_dir: The destination path or URI to import the file to.
 *   If no destination is set, it will default to "public://".
 * - destination_name: Destination filename. Default will be source filename.
 * - uid: The uid to attribute the file entity to. Defaults to 0
 * - rename: 0, 1, 2 as defined by FileSystemInterface::EXISTS_RENAME (0),
 *   FileSystemInterface::EXISTS_REPLACE (1), FileSystemInterface::EXISTS_ERROR
 *   (2). Default FileSystemInterface::EXISTS_REPLACE.
 * - reuse: Boolean, if TRUE, reuse the current file in its existing
 *   location rather than move/copy/rename the file. Defaults to FALSE.
 * - id_only: Boolean, if TRUE, the process will return just the id instead of
 *   an entity reference array. Useful if you want to manage other sub-fields
 *   in your migration (see example below).
 * - skip_on_error: Send a migrate skip processing on error if file fails to be
 *   downloaded or saved.
 *
 * Example:
 *
 * @code
 * process:
 *   field_course_image:
 *     plugin: moodle_file
 *     source: overviewfiles/0/fileurl
 *     destination_dir: 'public://moodle_files'
 *     uid: @uid
 * @endcode
 *
 * @see \Drupal\migrate\Plugin\MigrateProcessInterface
 *
 * @MigrateProcessPlugin(
 *   id = "moodle_file"
 * )
 */
class MoodleFile extends FileProcessBase implements ContainerFactoryPluginInterface {

  /**
   * The stream wrapper manager service.
   *
   * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
   */
  protected $streamWrapperManager;

  /**
   * Entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The file system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * The Moodle rest connection.
   *
   * @var \Drupal\moodle_rest\Services\MoodleRest
   */
  protected $moodle;

  /**
   * Constructs a file_copy process plugin.
   *
   * @param array $configuration
   *   The plugin configuration.
   * @param string $plugin_id
   *   The plugin ID.
   * @param array $plugin_definition
   *   The plugin definition.
   * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrappers
   *   The stream wrapper manager service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity type manager.
   * @param \Drupal\Core\File\FileSystemInterface $file_system
   *   The file system service.
   * @param \Drupal\moodle_rest\Services\MoodleRest $moodle
   *   The moodle rest connection.
   */
  public function __construct(array $configuration, $plugin_id, array $plugin_definition, StreamWrapperManagerInterface $stream_wrappers, EntityTypeManagerInterface $entity_type_manager, FileSystemInterface $file_system, MoodleRest $moodle) {
    $configuration += [
      'destination_dir' => 'public://',
      'destination_name' => NULL,
      'uid' => 0,
      'rename' => FileSystemInterface::EXISTS_RENAME,
      'reuse' => TRUE,
      'id_only' => FALSE,
      'skip_on_error' => FALSE,
    ];
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->streamWrapperManager = $stream_wrappers;
    $this->entityTypeManager = $entity_type_manager;
    $this->fileSystem = $file_system;
    $this->moodle = $moodle;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('stream_wrapper_manager'),
      $container->get('entity_type.manager'),
      $container->get('file_system'),
      $container->get('moodle_rest.rest_ws')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {

    if (!$value) {
      return NULL;
    }

    // Get our file entity values.
    $source = $value;
    $destination_dir = $this->getPropertyValue($this->configuration['destination_dir'], $row);
    $uid = $this->getPropertyValue($this->configuration['uid'], $row);
    $id_only = $this->configuration['id_only'];
    $destination_file = $this->getPropertyValue($this->configuration['destination_name'], $row) ?: $this->getDestinationFilename($value, $destination_dir);
    $rename = $this->getPropertyValue($this->configuration['rename'], $row);

    // If we're in re-use mode, reuse the file if it exists.
    if ($this->getPropertyValue($this->configuration['reuse'], $row)&& $this->isLocalUri($destination_file) && is_file($destination_file)) {
      // Look for a file entity with the destination uri.
      if ($files = $this->entityTypeManager->getStorage('file')->loadByProperties(['uri' => $destination_file])) {
        // Grab the first file entity with a matching uri.
        // @todo: Any logic for preference when there are multiple?
        $file = reset($files);
        // Set to permanent if the file in the database is set to temporary.
        if ($file->isTemporary()) {
          $file->setPermanent();
          $file->save();
        }

        return $id_only ? $file->id() : ['target_id' => $file->id()];
      }
      else {
        $final_destination = $destination_file;
      }
    }
    else {
      try {
        // Check dir. But FileBlob and another? try and move file first to
        // avoid doing this everytime?
        $this->fileSystem->prepareDirectory($destination_dir, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
        // Write file.
        $source_stream = $this->moodle->requestFile($source);
        $final_destination = $this->fileSystem->saveData($source_stream->getBody(), $destination_file, $rename);
      }
      catch (\Exception $e) {
        // Check if we're skipping on error
        if ($this->configuration['skip_on_error']) {
          $migrate_executable->saveMessage("File $source could not be imported to $destination_file. Operation failed with message: " . $e->getMessage());
          throw new MigrateSkipProcessException($e->getMessage());
        }
        else {
          // Pass the error back on again.
          throw new MigrateException($e->getMessage());
        }
      }
    }

    if ($final_destination) {
      // Create a file entity.
      $file = File::create([
        'uri' => $final_destination,
        'uid' => $uid,
        'status' => FileInterface::STATUS_PERMANENT,
      ]);
      $file->save();
      return $id_only ? $file->id() : ['target_id' => $file->id()];
    }

    throw new MigrateException("File $source could not be imported to $destination_file");
  }

  /**
   * Build destination filename.
   */
  private function getDestinationFilename($source, $destination_dir) {
    $source_parts = parse_url($source);
    $filename = $this->fileSystem->basename($source_parts['path']);
    return $destination_dir . '/' . $filename;
  }

  /**
   * Gets a value from a source or destination property.
   *
   * Code is adapted from Drupal\migrate\Plugin\migrate\process\Get::transform()
   */
  protected function getPropertyValue($property, $row) {
    if (is_string($property)) {
      $is_source = TRUE;
      if (substr($property, 0, 1) == '@') {
        $property = preg_replace_callback('/^(@?)((?:@@)*)([^@]|$)/', function ($matches) use (&$is_source) {
          // If there are an odd number of @ in the beginning, it's a
          // destination.
          $is_source = empty($matches[1]);
          // Remove the possible escaping and do not lose the terminating
          // non-@ either.
          return str_replace('@@', '@', $matches[2]) . $matches[3];
        }, $property);
        if ($is_source) {
          return $row->getSourceProperty($property);
        }
        else {
          return $row->getDestinationProperty($property);
        }
      }
    }
    return $property;
  }

  /**
   * Determines if the given URI or path is considered local.
   *
   * A URI or path is considered local if it either has no scheme component,
   * or the scheme is implemented by a stream wrapper which extends
   * \Drupal\Core\StreamWrapper\LocalStream.
   *
   * @param string $uri
   *   The URI or path to test.
   *
   * @return bool
   *   True if local.
   */
  protected function isLocalUri($uri) {
    $scheme = StreamWrapperManager::getScheme($uri);

    // The vfs scheme is vfsStream, which is used in testing. vfsStream is a
    // simulated file system that exists only in memory, but should be treated
    // as a local resource.
    if ($scheme == 'vfs') {
      $scheme = FALSE;
    }
    return $scheme === FALSE || $this->streamWrapperManager->getViaScheme($scheme) instanceof LocalStream;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc