Next, we are going to look at how we can work with managed files using a custom form element. And to demonstrate this, we are finally going to create another Product importer plugin. This time, instead of a remote JSON resource, we will allow users to upload a CSV file that contains product data and imports that into Product entities. This is what the example CSV data looks like:
id,name,number 1,Car,45345 2,Motorbike,54534
It basically has the same kind of data as the JSON resource we've been looking at so far, but without the image reference. So let's get going with our new plugin class.
Here is our starting point:
namespace Drupal\products\Plugin\Importer;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\products\Entity\ImporterInterface;
use Drupal\products\Entity\ProductInterface;
use Drupal\products\Plugin\ImporterBase;
use GuzzleHttp\Client;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Product importer from a JSON format.
*
* @Importer(
* id = "csv",
* label = @Translation("CSV Importer")
* )
*/
class CsvImporter extends ImporterBase {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public function import() {
$products = $this->getData();
if (!$products) {
return FALSE;
}
foreach ($products as $product) {
$this->persistProduct($product);
}
return TRUE;
}
}
The used files at the top also include the ones we will use as we flesh out the class, so one by one they will start making sense. In terms of our starting point, we extend from the ImporterBase class and implement the obligatory import() method. Like before, we delegate to getData() to retrieve the product information, but in this case we simply loop over the resulting records and use the persistProduct() method to save the Product entities. So no batch operations. Apart from no longer saving images, this latter method looks exactly like the one from the JsonImporter, so I won't be copying it over again. But, it makes for a good homework assignment to try to move it to the base class and abstract away the dynamic portions.