<?php
namespace Jabber\WebthinkingBundle\EventListener;
use Jabber\WebthinkingBundle\Helpers\StringHelper;
use Jabber\WebthinkingBundle\Provider\CategoryProvider;
use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Model\DataObject\Product;
use Pimcore\Model\DataObject\Classificationstore;
class PreUpdateListener {
public function __construct(public array $styleAttributes, public array $classificationGroupMapping, public int $systemUser) {
}
public function onPreUpdate(ElementEventInterface $e) {
if (!$e->hasArgument('isAutoSave')) {
if ($e instanceof DataObjectEvent) {
$object = $e->getObject();
if ($object instanceof Product) {
if ($object->getUserModification() != $this->systemUser) {
if ($object->getProductLevel() == 'STYLE') {
$activeGroups = $this->getActiveGroups($object);
$this->setClassificationValues($object, $activeGroups, true);
$this->setClassificationValues($object, $activeGroups, false);
$this->setCategoryValues($object);
}
$this->sortCategoryOrder($object);
}
}
}
}
}
/**
* Sorts the categories into alphabetic order based on the path
*
* Category order doesn't matter but it is much easier to read if they are in some sort of order
*
* @param Product $object
* @return void
*/
private function sortCategoryOrder(Product $object) {
$items = $object->getCategories();
if ($items) {
// Sorting items alphabetically by their path
usort($items, function ($a, $b) {
return strcmp($a->getFullPath(), $b->getFullPath());
});
$object->setCategories($items);
}
}
private function setCategoryValues(Product $object) {
$existingCategories = $object->getCategories();
// Categories shouldn't be added to products where categories are already visible. This may be subject to change
foreach ($existingCategories as $category) {
if (str_starts_with(strtolower($category->getSource()), 'webthinking')) {
return;
}
}
$provider = new CategoryProvider();
$object->setCategories($provider->getCategories($object));
}
private function getKeyGroupRelations($groupIdList): Classificationstore\KeyGroupRelation\Listing
{
$keyConfigRelations = new Classificationstore\KeyGroupRelation\Listing();
return $keyConfigRelations->setCondition('groupId IN (' . implode(",", $groupIdList) . ')');
}
/**
* Sets classification store values, handling both direct product settings
* and inheritance from parent products.
*
* @param Product $object The product object to process.
*/
public function setClassificationValues(Product $object, array $activeGroups, bool $isParentContext = true) {
$changes = false;
$contextObject = $isParentContext ? $object->getParent() : $object;
$classificationStore = $contextObject->getWebthinkingAttributeData();
$keyConfigRelations = $this->getKeyGroupRelations($activeGroups);
$originalInheritance = $object->getGetInheritedValues();
$object->setGetInheritedValues(true);
foreach ($keyConfigRelations as $relation) {
if ($relation->getKeyId() == 137) {
$foo = "bar";
}
$keyConfig = Classificationstore\KeyConfig::getById($relation->getKeyId());
$keyDefinition = $keyConfig->getDefinition();
$keyDefinitionObject = json_decode($keyDefinition);
$webthinkingAttributeId = $keyDefinitionObject->optionsProviderData;
if ($isParentContext) {
if (in_array($webthinkingAttributeId, $this->styleAttributes)) {
continue;
}
} else {
if (!in_array($webthinkingAttributeId, $this->styleAttributes)) {
continue;
}
}
$groupId = $relation->getGroupId();
$keyId = $relation->getKeyId();
if (!empty($keyDefinitionObject->defaultValueGenerator) || !empty($keyDefinitionObject->defaultValue) || $keyConfig->getType() == 'multiselect') {
$currentValue = $classificationStore->getLocalizedKeyValue($groupId, $keyId);
if (empty($currentValue)) {
$defaultValue = $this->getDefaultValueForKey($keyDefinition, $keyConfig->getType(), $contextObject);
if (!empty($defaultValue)) {
$changes = true;
$classificationStore->setLocalizedKeyValue($groupId, $keyId, $defaultValue);
}
}
}
}
//Return object to its original settings
$object->setGetInheritedValues($originalInheritance);
if ($changes == true) {
if ($isParentContext) {
$contextObject->setWebthinkingAttributeData($classificationStore)->save();
} else {
$object->setWebthinkingAttributeData($classificationStore);
}
}
}
private function getDefaultValueForKey($keyDefinition, $type, $dataObject) {
$fieldDefinitionClass = '\\Pimcore\\Model\\DataObject\\ClassDefinition\\Data\\' . ucfirst($type);
if (!empty($keyDefinition) && ($dataObject->getProductLevel() == 'PARENT' || $dataObject->getProductLevel() == 'STYLE')) {
$keyDefinitionObject = json_decode($keyDefinition);
if (!empty($keyDefinitionObject->defaultValue)) {
return $keyDefinitionObject->defaultValue;
}
if (!empty($keyDefinitionObject->optionsProviderClass) && !empty($keyDefinitionObject->optionsProviderData)) {
$fieldDefinitionObject = new $fieldDefinitionClass();
$fieldDefinitionObject->setName($keyDefinitionObject->name);
$fieldDefinitionObject->setOptionsProviderClass($keyDefinitionObject->optionsProviderClass);
$fieldDefinitionObject->setOptionsProviderData($keyDefinitionObject->optionsProviderData);
$fieldDefinitionObject->enrichFieldDefinition(['class'=>$keyDefinition]);
if (!empty($keyDefinitionObject->defaultValueGenerator)) {
$providerClass = $keyDefinitionObject->defaultValueGenerator;
} else {
//assume multiselect in which case defaults don't exist
$providerClass = '\\Jabber\\WebthinkingBundle\\Provider\\Defaults\\Multiselect\\' . StringHelper::toPascal($keyDefinitionObject->name) . 'Provider';
}
if (class_exists($providerClass)) {
$provider = new $providerClass();
return $provider->getValue($dataObject, $fieldDefinitionObject, []);
}
}
}
}
private function getActiveGroups(Product $object) {
$originalInheritance = $object->getGetInheritedValues();
$object->setGetInheritedValues(true);
$classificationStore = $object->getWebthinkingAttributeData();
$activeGroups = [];
$groupNames = [];
foreach ($this->classificationGroupMapping as $pimField=>$groups) {
if ($pimField == 'all') {
foreach ($groups as $grp) {
$groupNames[] = $grp;
}
continue;
}
if ($pimField == 'style' && $object->getProductLevel() == 'STYLE') {
foreach ($groups as $grp) {
$groupNames[] = $grp;
}
continue;
}
$pimFieldValue = strtolower($object->get($pimField));
if (in_array($pimFieldValue, $groups)) {
$groupNames[] = $pimFieldValue;
}
}
$fieldDefinition = $object->getClass()->getFieldDefinition('WebthinkingAttributeData');
$storeId = $fieldDefinition->getStoreId();
foreach ($groupNames as $groupName) {
$groupObject = Classificationstore\GroupConfig::getByName(strtoupper($groupName), $storeId);
if (!empty($groupObject)) {
$activeGroups[] = $groupObject->getId();
}
}
$activeGroupArray = [];
foreach ($activeGroups as $activeGroup) {
$activeGroupArray[$activeGroup] = true;
}
$classificationStore->setActiveGroups($activeGroupArray);
$object->setWebthinkingAttributeData($classificationStore);
$object->setGetInheritedValues($originalInheritance);
return $activeGroups;
}
}