I ended up doing it with the risky inserts directly into the tables.
the tables involved are (in this order)
- catalog_product_entity_media_gallery
- catalog_product_entity_media_gallery_value
- catalog_product_entity_media_gallery_value_to_entity
- catalog_product_entity_media_gallery_value_video
Pre-explanations:
This should happen inside one class.
This class has these members that are added via constructor (di will take care of instantiating them)
// \Magento\Framework\App\ResourceConnection
private $resourceConnection;
// \Magento\Catalog\Api\ProductAttributeRepositoryInterface
private $attributeRepository;
Let's take the tables 1 by 1:
catalog_product_entity_media_gallery
$mediaAttributeId = $this->attributeRepository->get('media_gallery')->getAttributeId();
$image = 'someImage.jpg'; //This is the preview image of the video. the image needs to exist in `/media/catalog/product/`. I'm not going to cover how you add it there
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery');
$data = [
'attribute_id' => $mediaAttributeId,
'value' => $image,
'media_type' => \Magento\ProductVideo\Model\Product\Attribute\Media\ExternalVideoEntryConverter::MEDIA_TYPE_CODE,
'disabled' => 0
];
$this->resourceConnection->getConnection()->insert($table, $data);
Now remember the last added increment id because it is needed in the later inserts.
$valueId = $this->resourceConnection->getConnection()->lastInsertId();
catalog_product_entity_media_gallery_value
$storeId = the store id for witch the video is available. Use 0 for global;
$productId = the id of the product for which you add the video
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value');
$data = [
'value_id' => $valueId, //the increment id from above
'store_id' => $storeId,
'entity_id' => $productId,
'position' => 1, //any number goes here
'disabled' => 0
];
$this->resourceConnection->getConnection()->insert($table, $data);
catalog_product_entity_media_gallery_value_to_entity
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value_to_entity');
$data = [
'value_id' => $valueId, // increment id from above
'entity_id' => $productId, // product id from the step above
];
$this->resourceConnection->getConnection()->insert($table, $data);
catalog_product_entity_media_gallery_value_video
$videoUrl = 'url of the video from youtube or vimeo';
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value_video');
$data = [
'value_id' => $valueId, //saved increment id from above
'store_id' => $storeId, // Store id from the steps above
'provider' => '',
'url' => $videoUrl,
'title' => "Video title", //this is mandatory
'description' => 'Video description', //this can be empty
'metadata' => '' //I have no idea what this does
];
$this->resourceConnection->getConnection()->insert($table, $data);
That's it. Some reindexing may be needed.