How to create Ibexa DXP Product Categories programmatically

Not all of the Ibexa DXP features are necessarily well documented. Given this scenario: a client wants to use the PIM and hands you a list of product categories that you need to import. Here's one way to create them via PHP.

My first approach was to use TaxonomyEntry and TaxonomyEntryCreateStruct for this. Unfortunately, I ended up with duplicate tags. It seems that the mandatory Content object is sufficient. Surprisingly a published Content object is all that’s needed for a product category tag.

Let’s say you have a similar list like this

name description
Some category Some category description
Another category Another long category description

If you read in your list and loop over the rows, you might have an array like this:

$rows = [
  ['name' => 'Some category', 'description' => 'Some category description'],
  ['name' => 'Another category', 'description' => 'Another long category description'],
];

So looping over $rows, this is what you do with the individual records:

use Ibexa\Contracts\Core\Repository\Repository;
use Ibexa\Core\FieldType\TextLine\Value as TextLineValue;
use Ibexa\Taxonomy\FieldType\TaxonomyEntry\Value as TaxonomyEntryValue;
use Ibexa\Taxonomy\Service\TaxonomyService;

$newIdentifier = 'product_category_tag_' . md5($record['name]); // unique per name to prevent dups
$parent = $this->taxonomyService->loadRootEntry('product_categories');
if ($parent->getContent()) {
  $tagContent = $this->repository->getContentService()->loadContent($parent->content->id);
  $parentLocationId = $tagContent->contentInfo->mainLocationId;
}
$tagType = $this->repository->getContentTypeService()->loadContentTypeByIdentifier('product_category_tag');
$contentCreateStruct = $this->repository->getContentService()->newContentCreateStruct($tagType, 'eng-GB');
$contentCreateStruct->setField('name', $record['name], 'eng-GB');
$contentCreateStruct->setField('identifier', new TextLineValue($newIdentifier), 'eng-GB');
$contentCreateStruct->setField('description', $record['description'], 'eng-GB');
$contentCreateStruct->setField('parent', new TaxonomyEntryValue($parent));
$locationCreateStruct = $this->repository->getLocationService()->newLocationCreateStruct($parentLocationId);
// fails if identifier isnt unique exists
try {
  $contentDraft = $this->repository->getContentService()->createContent($contentCreateStruct, [$locationCreateStruct], []); // the [] prevents validation
  $this->repository->getContentService()->publishVersion($contentDraft->versionInfo);
} catch (ValidationError $e) {
  // we expect this to fail in case it already exists
}
tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo tech logo