/** * {@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; // Modify the destination filename if necessary. $replace = !empty($this->configuration['rename']) ? FILE_EXISTS_RENAME : FILE_EXISTS_REPLACE; $final_destination = file_destination($destination, $replace); // Try opening the file first, to avoid calling file_prepare_directory() // unnecessarily. We're suppressing fopen() errors because we want to try // to prepare the directory before we give up and fail. $destination_stream = @fopen($final_destination, 'w'); if (!$destination_stream) { // If fopen didn't work, make sure there's a writable directory in place. $dir = $this->fileSystem->dirname($final_destination); if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { throw new MigrateException("Could not create or write to directory '{$dir}'"); } // Let's try that fopen again. $destination_stream = @fopen($final_destination, 'w'); if (!$destination_stream) { throw new MigrateException("Could not write to file '{$final_destination}'"); } } // Stream the request body directly to the final destination stream. $this->configuration['guzzle_options']['sink'] = $destination_stream; // Make the request. Guzzle throws an exception for anything other than 200. $this->httpClient->get($source, $this->configuration['guzzle_options']); return $final_destination; }
/** * 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; }
/** * {@inheritdoc} */ public function denormalize($data, $class, $format = NULL, array $context = array()) { // File content can be passed base64 encoded in a special "data" property. // That property is not a field, so we remove it before denormalizing the // rest of the file entity. $file_data = $data['data'][0]['value']; unset($data['data']); $entity = parent::denormalize($data, $class, $format, $context); // Decode and save to file if it's a new file. if (!isset($context['request_method']) || $context['request_method'] != 'patch') { $file_contents = base64_decode($file_data); $dirname = $this->fileSystem->dirname($entity->getFileUri()); file_prepare_directory($dirname, FILE_CREATE_DIRECTORY); if ($uri = file_unmanaged_save_data($file_contents, file_build_uri(drupal_basename($entity->getFilename())))) { $entity->setFileUri($uri); } else { throw new RuntimeException('failed to write ' . $entity->getFilename()); } } return $entity; }
/** * Locate all images in a piece of text that need replacing. * * An array of settings that will be used to identify which images need * updating. Includes the following: * * - image_locations: An array of acceptable image locations. * of the following values: "remote". Remote image will be downloaded and * saved locally. This procedure is intensive as the images need to * be retrieved to have their dimensions checked. * * @param string $text * The text to be updated with the new img src tags. * * @return array $images * An list of images. */ private function getImages($text) { $dom = Html::load($text); $xpath = new \DOMXPath($dom); /** @var \DOMNode $node */ foreach ($xpath->query('//img') as $node) { $file = $this->entityRepository->loadEntityByUuid('file', $node->getAttribute('data-entity-uuid')); // If the image hasn't an uuid then don't try to resize it. if (is_null($file)) { continue; } $image = $this->imageFactory->get($node->getAttribute('src')); // Checking if the image needs to be resized. if ($image->getWidth() == $node->getAttribute('width') && $image->getHeight() == $node->getAttribute('height')) { continue; } $target = file_uri_target($file->getFileUri()); $dirname = dirname($target) != '.' ? dirname($target) . '/' : ''; $info = pathinfo($file->getFileUri()); $resize_file_path = 'public://resize/' . $dirname . $info['filename'] . '-' . $node->getAttribute('width') . 'x' . $node->getAttribute('height') . '.' . $info['extension']; // Checking if the image was already resized: if (file_exists($resize_file_path)) { $node->setAttribute('src', file_url_transform_relative(file_create_url($resize_file_path))); continue; } // Delete this when https://www.drupal.org/node/2211657#comment-11510213 // be fixed. $dirname = $this->fileSystem->dirname($resize_file_path); if (!file_exists($dirname)) { file_prepare_directory($dirname, FILE_CREATE_DIRECTORY); } // Checks if the resize filter exists if is not then create it. $copy = file_unmanaged_copy($file->getFileUri(), $resize_file_path, FILE_EXISTS_REPLACE); $copy_image = $this->imageFactory->get($copy); $copy_image->resize($node->getAttribute('width'), $node->getAttribute('height')); $copy_image->save(); $node->setAttribute('src', file_url_transform_relative(file_create_url($copy))); } return Html::serialize($dom); }