Now that we have our product image field in place and we can store images, let's revisit our JSON response that contains the product data and assume it looks something like this now:
{ "products" : [ { "id" : 1, "name": "TV", "number": 341, "image": "tv.jpg" }, { "id" : 2, "name": "VCR", "number": 123, "image": "vcr.jpg" } ] }
What's new is the addition of the image key for each product, which simply references a filename for the image that goes with the respective product. The actual location of the images is at some other path we need to include in the code.
Going back to our JsonImporter::persistProduct() method, let's delegate the handling of the image import to a helper method called handleProductImage(). We need to call this method both if we are creating a new Product entity and if we are updating an existing one (right before saving):
$this->handleProductImage($data, $product);
And this is what the actual method looks like:
/** * Imports the image of the product and adds it to the Product entity. * * @param $data * @param \Drupal\products\Entity\ProductInterface $product */ private function handleProductImage($data, ProductInterface $product) { $name = $data->image; // This needs to be hardcoded for the moment. $image_path = ''; $image = file_get_contents($image_path . '/' . $name); if (!$image) { // Perhaps log something. return; } /** @var \Drupal\file\FileInterface $file */ $file = file_save_data($image, 'public://product_images/' . $name, FileSystemInterface::EXISTS_REPLACE); if (!$file) { // Something went wrong, perhaps log it. return; } $product->setImage($file->id()); }
And the new use statement at the top:
use Drupal\products\Entity\ProductInterface; use Drupal\Core\File\FileSystemInterface;
First, we get the name of the image. Then we construct the path to where the product images are stored. In this example, it's left blank, but if the example were to work, we'd have to add a real path there. I leave that up to you for now. If you want to test it out, create a local folder with some images and reference that.
Using the native file_get_contents() function, we load the data of the image from the remote environment into a string. We then pass this string to the file_save_data() function which saves a new managed file to the public filesystem. This function takes three parameters: the data to be saved, the URI of the destination, and a flag indicating what to do if a file with the same name already exists. You'll notice that we used the Drupal public:// stream wrapper to build the URI and we already know which folder this maps to.
As for the third parameter, we chose to replace the file in case one already exists. The alternative would have been to either use the EXISTS_RENAME or EXISTS_ERROR constants of the same interface. The first would have created a new file whose name would have gotten a number appended until the name became unique. The second would have simply not done anything and returned FALSE.
If all goes well, this function returns a File entity (that implements FileInterface) whose ID we can use in the Product image setter method. With that in place, we can synchronize also the individual product images.
Moreover, in our database, a record is created in the file_usage table to indicate that this file is being used on the respective Product entity.