X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Fmigrate_plus%2Fsrc%2FPlugin%2Fmigrate%2Fprocess%2FFileCopy.php;fp=web%2Fmodules%2Fcontrib%2Fmigrate_plus%2Fsrc%2FPlugin%2Fmigrate%2Fprocess%2FFileCopy.php;h=321afcadac4bd76031ff72ac5d93acc99c2e27e1;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hp=0000000000000000000000000000000000000000;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad;p=yaffs-website diff --git a/web/modules/contrib/migrate_plus/src/Plugin/migrate/process/FileCopy.php b/web/modules/contrib/migrate_plus/src/Plugin/migrate/process/FileCopy.php new file mode 100644 index 000000000..321afcada --- /dev/null +++ b/web/modules/contrib/migrate_plus/src/Plugin/migrate/process/FileCopy.php @@ -0,0 +1,215 @@ + FALSE, + 'rename' => FALSE, + ); + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->streamWrapperManager = $stream_wrappers; + $this->fileSystem = $file_system; + } + + /** + * {@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('file_system') + ); + } + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + // If we're stubbing a file entity, return a URI of NULL so it will get + // stubbed by the general process. + if ($row->isStub()) { + return NULL; + } + list($source, $destination) = $value; + + // Ensure the source file exists, if it's a local URI or path. + if ($this->isLocalUri($source) && !file_exists($source)) { + throw new MigrateException("File '$source' does not exist"); + } + + // If the start and end file is exactly the same, there is nothing to do. + if ($this->isLocationUnchanged($source, $destination)) { + return $destination; + } + + $replace = $this->getOverwriteMode(); + // We attempt the copy/move first to avoid calling file_prepare_directory() + // any more than absolutely necessary. + $final_destination = $this->writeFile($source, $destination, $replace); + if ($final_destination) { + return $final_destination; + } + // If writeFile didn't work, make sure there's a writable directory in + // place. + $dir = $this->getDirectory($destination); + if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { + throw new MigrateException("Could not create or write to directory '$dir'"); + } + $final_destination = $this->writeFile($source, $destination, $replace); + if ($final_destination) { + return $final_destination; + } + throw new MigrateException("File $source could not be copied to $destination"); + } + + /** + * Tries to move or copy a file. + * + * @param string $source + * The source path or URI. + * @param string $destination + * The destination path or URI. + * @param int $replace + * (optional) FILE_EXISTS_REPLACE (default) or FILE_EXISTS_RENAME. + * + * @return string|bool + * File destination on success, FALSE on failure. + */ + protected function writeFile($source, $destination, $replace = FILE_EXISTS_REPLACE) { + if ($this->configuration['move']) { + return file_unmanaged_move($source, $destination, $replace); + } + // We can't use file_unmanaged_copy because it will break with remote Urls. + $final_destination = file_destination($destination, $replace); + if (@copy($source, $final_destination)) { + return $final_destination; + } + return FALSE; + } + + /** + * Determines how to handle file conflicts. + * + * @return int + * Either FILE_EXISTS_REPLACE (default) or FILE_EXISTS_RENAME, depending + * on the current configuration. + */ + protected function getOverwriteMode() { + if (!empty($this->configuration['rename'])) { + return FILE_EXISTS_RENAME; + } + return FILE_EXISTS_REPLACE; + } + + /** + * Returns the directory component of a URI or path. + * + * For URIs like public://foo.txt, the full physical path of public:// + * will be returned, since a scheme by itself will trip up certain file + * API functions (such as file_prepare_directory()). + * + * @param string $uri + * The URI or path. + * + * @return string|false + * The directory component of the path or URI, or FALSE if it could not + * be determined. + */ + protected function getDirectory($uri) { + $dir = $this->fileSystem->dirname($uri); + if (substr($dir, -3) == '://') { + return $this->fileSystem->realpath($dir); + } + return $dir; + } + + /** + * Determines if the source and destination URIs represent identical paths. + * + * If either URI is a remote stream, will return FALSE. + * + * @param string $source + * The source URI. + * @param string $destination + * The destination URI. + * + * @return bool + * TRUE if the source and destination URIs refer to the same physical path, + * otherwise FALSE. + */ + protected function isLocationUnchanged($source, $destination) { + if ($this->isLocalUri($source) && $this->isLocalUri($destination)) { + return $this->fileSystem->realpath($source) === $this->fileSystem->realpath($destination); + } + return FALSE; + } + + /** + * 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 + */ + protected function isLocalUri($uri) { + $scheme = $this->fileSystem->uriScheme($uri); + return $scheme === FALSE || $this->streamWrapperManager->getViaScheme($scheme) instanceof LocalStream; + } + +}