<?php
namespace PfcGenerateSkuBundle\EventListener;
use Carbon\Carbon;
use Cocur\Slugify\Slugify;
use mysql_xdevapi\Exception;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\Folder;
use Pimcore\Model\Element\ValidationException;
use Pimcore\Model\Notification\Service\UserService;
use Pimcore\Tool\Admin;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\Event;
use Pimcore\Model\Notification\Service\NotificationService;
use Pimcore\Model\User;
use Symfony\Component\EventDispatcher\GenericEvent;
use Pimcore\Model\DataObject\ClassDefinition\CustomLayout;
use Pimcore\Model\DataObject\Service;
use function Sabre\Event\Loop\instance;
class WorkflowListener implements EventSubscriberInterface
{
const OPTIONCOLORS = [91, 92, 93, 94, 95, 96, 97, 98, 99, 100];
const FOLDER_NAME = "Attributes";
const FOLDER_INSIDE_FOLDER = self::FOLDER_NAME . '/AttributeName';
const FOLDER_INSIDE_ATTRIBUTEVALUE = self::FOLDER_NAME . '/AttributeValue';
const FOLDER_NAME_PFATTRIBUTE = "Attribute name";
const FOLDER_NAME_ATTRIBUTEVALUE = "AttributeValue";
private $workflowRegistry;
protected $slugify;
/** By : Khagendra Wagle
* Unfurtunately Pimcore allows to update the unique code field and there is no field leave security to decide
* on the fly if a field is editable or not. checkPermission function will have some custom logic
* manipulate object layout data before it is opened for users.
* Note: Not sure if this is is the right approach but there is noway we could acheive this in the current PIMCORE
* version 6.4. May be in the future, PIMCORE will come up with the solution for field level security
**/
public function checkPermissions(GenericEvent $event): void
{
$object = $event->getArgument("object");
//data element that is send to Pimcore backend UI
$data = $event->getArgument("data");
if ($object instanceof DataObject\Product) {
$data['hasPreview'] = false;
$currentLayout = explode(",", "-1,1,2");
if(!in_array($data['currentLayoutId'], $currentLayout)){
// Set Model Layout when product is a Model and Sku Layout when it is variant (sku)
$data = $this->f_setLayout($object, $data);
$data = $this->f_setMandatoryAttributes($object, $data);
$data = $this->f_setAuthentication($object, $data);
$data = $this->f_setProductSpecificAttributes($object, $data);
$event->setArgument("data", $data);
}
//modelCode must be locked once product created and locked for further enhancement
if ($data['currentLayoutId'] == "1") {
$data = $this->f_lockModelCode($object, $data);
$event->setArgument("data", $data);
}
if ($data['currentLayoutId'] == "2") {
$data = $this->f_SetSkuGenerateLayout($object, $data);
$event->setArgument("data", $data);
}
//Hide Size grid and size list in SKU genereate Layout when model code is of 6 length
if ($data['currentLayoutId'] != "-1" && (($object instanceof DataObject\Brand && $object->getBrandID() != null)
|| ($object instanceof DataObject\MenuCategory && $object->getUniqueCode() != null)
|| ($object instanceof DataObject\Color1 && $object->getColor1Code() != null)
|| ($object instanceof DataObject\MainColor && $object->getMainColor() != null)
|| ($object instanceof DataObject\SimpleColor && $object->getSimpleColorCode() != null)
|| ($object instanceof DataObject\SizeGroup && $object->getCode() != null)
|| ($object instanceof DataObject\Size && $object->getUniqueCode() != null)
|| ($object instanceof DataObject\Tier1 && $object->getTier1Code() != null)
|| ($object instanceof DataObject\Tier2 && $object->getTier2Code() != null)
|| ($object instanceof DataObject\Tier3 && $object->getTier3Code() != null)
|| ($object instanceof DataObject\Theme && $object->getUniqueCode() != null)
)) {
$data = $this->f_makeUniqueFieldReadOnly($object, $data);
$event->setArgument("data", $data);
}
}
}
public function f_setMandatoryAttributes($object, $data): array
{
if ('variant' != $object->gettype()) {
$settingObject = DataObject\SettingAttributes::getBySettingCode('manadatoryModel', 1);
if ($settingObject) {
$mandatoryAttributes = explode(",", trim($settingObject->getAttributes()));
}
} else {
$settingObject = DataObject\SettingAttributes::getBySettingCode('mandatorySku', 1);
if ($settingObject) {
$mandatoryAttributes = explode(",", trim($settingObject->getAttributes()));
}
}
$layout = \GuzzleHttp\json_encode($data["layout"]);
if (is_array($mandatoryAttributes)) {
$from_man_property = 'mandatory":false';
$to_man_property = 'mandatory":true';
foreach ($mandatoryAttributes as $mandatoryAttribute) {
$key = '"name":"' . $mandatoryAttribute . '"';
$poss = $this->strpos_all($layout, $key);
foreach ($poss as $pos) {
$layout_str1 = substr($layout, 0, $pos);
$layout_str2 = substr($layout, $pos);
$layout_str2 = preg_replace('/' . $from_man_property . '/', $to_man_property, $layout_str2, 1);
$layout = $layout_str1 . $layout_str2;
}
}
}
$layout_data = \GuzzleHttp\json_decode($layout);
$data['layout'] = $layout_data;
return $data;
}
public function f_setProductSpecificAttributes($object, $data): array
{
//Product Specific Attribute
if ($object->getTier3() && (($object->getTier3()->getProductSpecificAttributes() != null && !empty($object->getTier3()->getProductSpecificAttributes()))
|| ($object->getTier3()->getMandatoryAttributes() != null && !empty($object->getTier3()->getMandatoryAttributes())))) {
$tier1Object = $object->getTier3();
} else {
$tier1Object = $object->getTier1();
}
if ($tier1Object) {
$optionalAttributes = explode(",", trim($tier1Object->getProductSpecificAttributes()));
$mandatory = explode(",", trim($tier1Object->getMandatoryAttributes()));
$attributes = array_merge($mandatory, $optionalAttributes);
$attributes = array_unique($attributes);
if (is_array($attributes)) {
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeVisible(true, $layout, $attributes, $mandatory);
/** Not required anymore so commented for now...
* Fabric description is localized and when it must be invisible for any Tier, the language flags are still shown
* To hide those flags we user the trick and hide it. For this purpose localized title is set as Fabric description:
* */
// if (!in_array("fabricDescription", $attributes)) { //means localized flags should be hidden
// $key = '"title":"Fabric description:"';
// $poss = $this->strpos_all($layout_new, $key);
// foreach ($poss as $pos) {
// $layout_str1 = substr($layout_new, 0, $pos);
// $layout_str2 = substr($layout_new, $pos);
// $from_property = 'width":""';
// $to_property = 'width":1';
// $layout_str2 = preg_replace('/' . $from_property . '/', $to_property, $layout_str2, 1);
// $from_property = 'height":""';
// $to_property = 'height":1';
// $layout_str2 = preg_replace('/' . $from_property . '/', $to_property, $layout_str2, 1);
// $from_property = 'border":true';
// $to_property = 'border":false';
// $layout_str2 = preg_replace('/' . $from_property . '/', $to_property, $layout_str2, 1);
//
// $layout_new = $layout_str1 . $layout_str2;
//
// }
// }
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
}
return $data;
}
/**
* @param $object
* @param $data
*/
public function f_setAuthentication($object, $data): array
{
// Translation update should be blocked once it is sent for Review or translation done. Only Translation manager or Admin with Master (Admin mode) layout can update it.
if (!$this->isUserAllowed('editTranslations') && ($object->getTranslationStatus() == "done" || $object->getTranslationStatus() == "send")) {
$settingObject = DataObject\SettingAttributes::getBySettingCode('editTranslations', 1);
if ($settingObject) {
$attributes = explode(",", $settingObject->getAttributes());
if (is_array($attributes)) {
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeReadOnly(true, $layout, $attributes);
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
}
}
// Allow Onboarding status and pfstore status editable for roles setup in the setting
$user = \Pimcore\Tool\Admin::getCurrentUser()->getName();
if ($user == "admin" || $this->isUserAllowed('editStatus')) {
$settingObject = DataObject\SettingAttributes::getBySettingCode('editStatus', 1);
if ($settingObject) {
$attributes = explode(",", $settingObject->getAttributes());
if (is_array($attributes)) {
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeReadOnly(false, $layout, $attributes);
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
}
}
$users = \Pimcore\Tool\Admin::getCurrentUser();
if ($object->getInitialIntroDate() != null || $object->getInitialIntroDate() != "") {
foreach ($users->getRoles() as $user) {
// $userOrRoleToCheck = User\Role::getById($user);
// if (($user == 26 || $userOrRoleToCheck == "Launch_manager") || $this->isUserAllowed('editStatus')) {
if ($object->getInitialIntroDate() != null || $object->getInitialIntroDate != "") {
$settingObject = DataObject\SettingAttributes::getBySettingCode('editStatus', 1);
$attributes = explode(",", $settingObject->getAttributes());
array_push($attributes, "initialIntroDate");
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeReadOnly(true, $layout, $attributes);
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
}
} else {
if (!empty($users->getRoles()) || $users->getRoles() != null || $users->getRoles() != "") {
foreach ($users->getRoles() as $user) {
$userOrRoleToCheck = User\Role::getById($user);
if (($user == 26 || $userOrRoleToCheck == "Launch_manager") || $this->isUserAllowed('editStatus')) {
$settingObject = DataObject\SettingAttributes::getBySettingCode('editStatus', 1);
$attributes = explode(",", $settingObject->getAttributes());
array_push($attributes, "initialIntroDate");
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeReadOnly(false, $layout, $attributes);
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
}
}
}
return $data;
}
public function f_SetSkuGenerateLayout($object, $data): array
{
DataObject\Product::setGetInheritedValues(true);
$attributes = [];
$layout = \GuzzleHttp\json_encode($data["layout"]);
if (strlen($object->getModelCode()) > 5) {
$attributes = explode(",", "sizeGroup,sizeList");
$layout = $this->makeAttributeVisible(false, $layout, $attributes);
} //if model code is 5 and sizegrid was already saved with sku generation, do not allow to switch sizeGrid
else if ($object->getSizeGrid()) {
$attributes = explode(",", "sizeGroup");
$layout = $this->makeAttributeReadOnly(true, $layout, $attributes);
}
$layout_data = \GuzzleHttp\json_decode($layout);
$data['layout'] = $layout_data;
return $data;
}
/**
* @param $object
* @param $data
* @return mixed
*/
public function f_setLayout($object, $data): array
{
DataObject\Product::setGetInheritedValues(true);
if ('variant' == $object->gettype()) {
$customLayoutToSelect = 4;
} else {
$customLayoutToSelect = 3;
}
if ($customLayoutToSelect != null) {
//set current layout to subcategory layout
$data['currentLayoutId'] = $customLayoutToSelect;
$customLayout = CustomLayout::getById($customLayoutToSelect);
$data['layout'] = $customLayout->getLayoutDefinitions();
Service::enrichLayoutDefinition($data["layout"], $object);
}
if (!empty($layoutsToRemove)) {
//remove master layout from valid layouts
$validLayouts = $data["validLayouts"];
foreach ($validLayouts as $key => $validLayout) {
if (in_array($validLayout['id'], $layoutsToRemove)) {
unset($validLayouts[$key]);
}
}
$data["validLayouts"] = array_values($validLayouts);
}
return $data;
}
/**
* @param $object
* @param $data
* Lock modelcode field after Model code is locked in layout 1.
*/
public function f_lockModelCode($object, $data): array
{
if ($this->getWorkflowStatus($object) != "mode_create") {
$attributes = explode(",", "modelCode");
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeAttributeReadOnly(true, $layout, $attributes);
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
}
return $data;
}
/**
* @param $data
* @param $object
* make attribute read-only when there Unique (code) defined in the Master Data class.
* Admin can alwayas do using Master(admin mode) layout
*/
public function f_makeUniqueFieldReadOnly($object, $data): array
{
$layout = \GuzzleHttp\json_encode($data["layout"]);
$layout_new = $this->makeUniqueFieldReadOnly($layout, '"unique":true');
$layout_data = \GuzzleHttp\json_decode($layout_new);
$data['layout'] = $layout_data;
return $data;
}
public function isUserAllowed($settingCode): bool
{
$userAllowed = false;
$settingObject = DataObject\SettingAttributes::getBySettingCode($settingCode, 1);
if ($settingObject) {
$roles_setting = $settingObject->getRoles();
if ($roles_setting != null && $roles_setting != "") {
$allowedRoles = explode(",", $roles_setting); //We can move this to setting in the future
$roles = $this->rolesName(); // All the roles current user has got
foreach ($roles as $role) {
if (in_array($role, $allowedRoles)) {
$userAllowed = true;
break;
}
}
}
}
return $userAllowed;
}
public function rolesName(): array
{
// get available roles
$roles = [];
$currentRoles = \Pimcore\Tool\Admin::getCurrentUser()->getRoles();
$list = new User\Role\Listing();
$list->setCondition('`type` = ?', ['role']);
$list->load();
foreach ($currentRoles as $currentRole) {
if (is_array($list->getItems())) {
foreach ($list->getItems() as $role) {
if ($role->getId() == $currentRole) {
$roles = $role->getName();
}
}
}
}
return [$roles];
}
public function makeAttributeReadOnly($flag_readonly, $layout, $attributes): string
{
if ($flag_readonly) {
$from_property = 'noteditable":false';
$to_property = 'noteditable":true';
} else {
$from_property = 'noteditable":true';
$to_property = 'noteditable":false';
}
foreach ($attributes as $attribute) {
$key = '"name":"' . $attribute . '"';
$poss = $this->strpos_all($layout, $key);
foreach ($poss as $pos) {
$layout_str1 = substr($layout, 0, $pos);
$layout_str2 = substr($layout, $pos);
$layout_str2 = preg_replace('/' . $from_property . '/', $to_property, $layout_str2, 1);
//mark as mandatory if it is in mandatory attribute list under Tier1. used only for product specific attributes.
$layout = $layout_str1 . $layout_str2;
}
}
return $layout;
}
public function makeAttributeVisible($flag_visible, $layout, $attributes, $mandatory = null): string
{
if ($flag_visible) {
$from_property = 'invisible":true';
$to_property = 'invisible":false';
} else {
$from_property = 'invisible":false';
$to_property = 'invisible":true';
}
foreach ($attributes as $attribute) {
$key = '"name":"' . $attribute . '"';
$poss = $this->strpos_all($layout, $key);
foreach ($poss as $pos) {
$layout_str1 = substr($layout, 0, $pos);
$layout_str2 = substr($layout, $pos);
$layout_str2 = preg_replace('/' . $from_property . '/', $to_property, $layout_str2, 1);
if (is_array($mandatory) && in_array($attribute, $mandatory)) {
$from_man_property = 'mandatory":false';
$to_man_property = 'mandatory":true';
$layout_str2 = preg_replace('/' . $from_man_property . '/', $to_man_property, $layout_str2, 1);
}
$layout = $layout_str1 . $layout_str2;
}
}
return $layout;
}
public function makeUniqueFieldReadOnly($layout, $key): string
{
$poss = $this->strpos_all($layout, $key);
foreach ($poss as $pos) {
$layout_str1 = substr($layout, 0, $pos);
$layout_str2 = substr($layout, $pos);
$layout_str2 = preg_replace('/' . 'noteditable":false' . '/', 'noteditable":true', $layout_str2, 1);
$layout = $layout_str1 . $layout_str2;
}
return $layout;
}
public function strpos_all($layout, $key): array
{
$offset = 0;
$allpos = array();
while (($pos = strpos($layout, $key, $offset)) !== FALSE) {
$offset = $pos + 1;
$allpos[] = $pos;
}
return $allpos;
}
public function __construct(Registry $workflowRegistry)
{
$this->workflowRegistry = $workflowRegistry;
}
/** By Khagendra
* The onleave event will catch the workflow transition and setLastWorkflowAction
* which will later be used to skip validation while creating model for the first time
* This is also the place when you want to hook any validation for any workflow transition
*/
public function onLeave(Event $event): void
{
$errors = [];
$object = $event->getSubject();
$eventTransition = $event->getTransition();
$transitionName = $eventTransition->getName();
$this->workflowActionValidation($object, $transitionName);
$object->setSkipValidation(true);
$user = \Pimcore\Tool\Admin::getCurrentUser();
if ($user) {
$username = $user->getName();
}
if ($transitionName == 'create_done') {
$user = \Pimcore\Tool\Admin::getCurrentUser();
$object->setProductCreator($username);
$object->setProductType("Model");
$this->setProductOwner($object, $username);
$object->setProductCreateDate(Carbon::now());
if (strlen($object->getModelCode()) == 6) {
$gridObject = DataObject\SizeGroup::getByCode('NA', 1);
if ($gridObject) {
$object->setSizeGrid($gridObject);
}
}
} else if ($transitionName == 'create_sku') {
if (strlen($object->getModelCode()) == 6) {
$this->CreateSkuWithColorVariants($object);
} elseif (strlen($object->getModelCode()) == 5) {
$this->CreateSkuWithColorSizeVariants($object);
} else {
$message = 'Model code length must be either 5 or 6 for Sku generation.';
array_push($errors, $message);
$this->ValidationExceptionWorkflow($errors);
}
} else if ($transitionName == 'ready_for_review') {
$object->setTranslationStatus('send');
$object->setTranslationSentBy($username);
} else if ($transitionName == 'translation_done') {
$object->setTranslationStatus('done');
} else if ($transitionName == 'reopen_product_enrich') {
$object->setTranslationStatus('reopen');
} else if ($transitionName == 'ready_for_translation' || $transitionName == 'ready_for_translation2') {
$object->setTranslationStatus('translating');
} else if ($transitionName == 'reject_review') {
$object->setTranslationStatus('rejected');
$user_receipient = $object->getTranslationSentBY();
if ($user_receipient != null) {
$title = 'Request for translation is rejected for product ' . $object->getModelCode();
$message = $title . '<br>' . 'Please open the product and check details under "Notes & Events"';
$this->createUserNotification($object, $user_receipient, $title, $message);
}
}
}
public function setProductOwner($object, $userid): void
{
$uname = '';
$userObject = User::getByName($userid);
if ($userObject) {
$uname = $userObject->getFirstname() . " " . $userObject->getLastname();
}
if ($uname == '' || $uname == null || $userid == 'admin') {
$uname = $userid;
}
$object->setProductOwner($uname);
}
/** By Khagendra
* The Guard event is use to block Workflow transition without minimum required feilds are available
*/
public function guardPublish(GuardEvent $event): void
{
$objects = $event->getSubject();
if ('variant' == $objects->gettype()) { // Workflow action is blocked on variant level
$event->setBlocked(true);
}
if ($objects->getModelCode() == null || $objects->getTier3() == null) {
$event->setBlocked(true);
}
}
public static function getSubscribedEvents(): array
{
return [
'workflow.Product_Workflow.guard' => ['guardPublish'],
'workflow.Product_Workflow.leave' => ['onLeave'],
];
}
public function workflowActionValidation($object, $transitionName): void
{
if ($transitionName == "ready_for_translation") {
$errors = [];
if ($object->getProductTitle('en') == null) {
$message = 'Product title is empty.';
array_push($errors, $message);
}
if ($object->getProductDescription('en') == null) {
$message = 'Product description is empty.';
array_push($errors, $message);
}
$this->ValidationExceptionWorkflow($errors);
}
}
public function createUserNotification($object, $user_receiver, $title, $message): void
{
try {
$element = DataObject::getById($object->getId());
$userService = new UserService();
$notificationService = new NotificationService($userService);
$recipient = User::getByName($user_receiver)->getId();
$notificationService->sendToUser(
$recipient, // User recipient
0, // User sender 0 - system
$title,
$message . '<br>' . $element,
$element
);
} catch (\Exception $e) {
}
}
public function ValidationExceptionWorkflow($errors): void
{
// throw ExceptionMessage of validation
if (!empty($errors)) {
$result = null;
foreach ($errors as $error) {
$result .= $error . '<br>';
}
throw new \UnexpectedValueException($result);
}
}
public function getWorkflowStatus($object): string
{
$workflow = $this->workflowRegistry->get($object, 'Product_Workflow');
return implode(', ', array_keys($workflow->getMarking($object)->getPlaces()));
}
/**
* @param $object
*/
public function CreateSkuWithColorVariants($object): void
{
$skuList = [];
$colorList = [];
$colorCodeList = [];
$skuMessages = [];
if (($object->getSelectColors()) == null) {
$message = "Color1 is required. Select Color1 and save first.";
array_push($skuMessages, $message);
$this->ValidationExceptionWorkflow($skuMessages);
}
if ($object->getSelectColors()) {
foreach ($object->getSelectColors() as $SelectColor) {
$SelectColorObject = DataObject\Color1::getById($SelectColor->getElementId());
$listing = new DataObject\Product\Listing();
$listing->setCondition('ModelCode = ?', $object->getModelCode());
$listing->setObjectTypes([DataObject\AbstractObject::OBJECT_TYPE_VARIANT]);
if ($object->getselectedColors()) {
if (in_array(trim($SelectColorObject->getColor1Code()), explode(',', $object->getselectedColors()))) {
continue;
}
}
$skus = $listing->getObjects();
foreach ($skus as $sku) {
array_push($skuList, $sku->getSku());
if (!in_array($sku->getColor1Code(), $colorList)) {
array_push($colorList, $sku->getColor1Code());
}
//Check if there is sku already generated with selected color now
// if ($object->getColors()->getColor1Code() == $sku->getColor1Code()) {
// $message = "Sku " . $sku->getSku() . " already exists with Color " . $object->getColors()->getColor1Code();
// array_push($skuMessages, $message);
// $this->ValidationExceptionWorkflow($skuMessages);
// }
array_push($colorCodeList, substr($sku->getSku(), 6, 2));
}
/** Now generate sku with selected color
*1. First calculate what is the sku code for selected color */
$skuNumber = $object->getModelCode() . $SelectColorObject->getParent()->getSkuColorCode();
/** 2 . First check if this skuNumber already exits */
if (!in_array($skuNumber, $skuList)) {
/** 2.1 Does not exists so create it with $skuNumber */
$this->CreateSku($object, $sizeObjects = null, $skuNumber, $SelectColorObject->getColor1Code(), $SelectColorObject->getHexColor1());
} else {
/** 2.2 exists so deviate to sku code miscellaneous range */
$deviationCode = 91;
do {
if (in_array($deviationCode, $colorCodeList)) {
$deviationCode = $deviationCode + 1;
} else {
break;
}
} while ($deviationCode < 100);
if ($deviationCode > 99) {
$message = "Miscellaneous sku color code range 91-99 exceeds.";
array_push($skuMessages, $message);
$this->ValidationExceptionWorkflow($skuMessages);
}
$skuNumber = $object->getModelCode() . $deviationCode;
$this->CreateSku($object, $sizeObjects = null, $skuNumber, $SelectColorObject->getColor1Code(), $SelectColorObject->getHexColor1());
}
// set list of colors created on model level
$modelSelectedColor = implode(",", $colorList) . "," . $SelectColorObject->getColor1Code();
$object->setselectedColors(trim($modelSelectedColor, ","));
// $object->save();
// \Pimcore\Cache::clearAll();
//throw new ValidationException("Created sku is ".$skuNumber, 409);
}
}
$object->setSelectColors(null); // reset select color 1 after sku is generated
$object->setColors2(null); // reset select color 2 after sku is generated
$object->setColors3(null); // reset select color 3 after sku is generated
$object->setOmitMandatoryCheck(true);
$object->setSkipValidation(true);
$object->setPublished(true);
}
/**
* @param $object
*/
public function CreateSkuWithColorSizeVariants($object): void
{
$skuList = [];
$colorList = [];
$colorCodeList = [];
$skuMessages = [];
$skuNumbers = [];
$sizeList = [];
$skuColorCode = 0;
if (($object->getSelectColors()) == null) {
$message = "Color1 is required.";
array_push($skuMessages, $message);
//$this->ValidationExceptionWorkflow($skuMessages);
}
if ($object->getSizeGroup() == null) {
$message = "Size group is required.";
array_push($skuMessages, $message);
}
if (empty($object->getSizeList())) {
$message = "Select size and save.";
array_push($skuMessages, $message);
}
$this->ValidationExceptionWorkflow($skuMessages);
foreach ($object->getSelectColors() as $SelectColor) {
$SelectColorObject = DataObject\Color1::getById($SelectColor->getElementId());
$listing = new DataObject\Product\Listing();
$listing->setCondition('ModelCode = ?', $object->getModelCode());
$listing->setObjectTypes([DataObject\AbstractObject::OBJECT_TYPE_VARIANT]);
$skus = $listing->getObjects();
foreach ($skus as $sku) {
array_push($skuList, $sku->getSku());
if (!in_array($sku->getColor1Code(), $colorList)) {
array_push($colorList, $sku->getColor1Code());
}
/** Build Size string to calucate later SizeRange and SizeRangeDetails */
$sizeCodeObject = DataObject\Size::getByCode($sku->getSizeCode(), 1);
if ($sizeCodeObject) {
if (strlen($sizeCodeObject->getSizeSequence()) == 1) {
$sizeString = "0" . $sizeCodeObject->getSizeSequence() . "-" . $sku->getSizeCode();
} else {
$sizeString = $sizeCodeObject->getSizeSequence() . "-" . $sku->getSizeCode();
}
} else {
$sizeString = "01-" . $sku->getSizeCode();
}
if (!in_array($sizeString, $sizeList)) {
array_push($sizeList, $sizeString);
}
array_push($colorCodeList, substr($sku->getSku(), 5, 2));
if ($skuColorCode == 0 && $SelectColorObject->getColor1Code() == $sku->getColor1Code()) {
$skuColorCode = substr($sku->getSku(), 5, 2);
}
}
/** Now generate sku with selected color
* 1. First check if deviation is needed or not
* Deviation rule is simple here.
* When selected color does not exist in already created SKU List and SKU color code is already used by
* another color from simple color of an item, then deviation is needed.
*/
if ($skuColorCode == 0) {
$skuColorCode = $SelectColorObject->getParent()->getSkuColorCode(); // SKu Code of simple color
}
$deviationCode = 0;
if (!in_array($SelectColorObject->getColor1Code(), $colorList)
&& in_array($SelectColorObject->getParent()->getSkuColorCode(), $colorCodeList)) {
$deviationCode = 91;
do {
if (in_array($deviationCode, $colorCodeList)) {
$deviationCode = $deviationCode + 1;
} else {
break;
}
} while ($deviationCode < 100);
if ($deviationCode > 99) {
$message = "Miscellaneous sku color code range 91-99 exceeds.";
array_push($skuMessages, $message);
$this->ValidationExceptionWorkflow($skuMessages);
}
} else {
$skuColorCode = $SelectColorObject->getParent()->getSkuColorCode();
}
/**2. We know now if deviation is needed and what would be sku color code. Let's define all the sku numbers
* to be created per size
*/
foreach ($object->getSizeList() as $key => $sizeObject) {
$sizeCodeObject = DataObject\Size::getById($sizeObject);
$sizeSkuCode = $sizeCodeObject->getSkuCode();
if ($deviationCode > 0) {
$skuKey = $object->getModelCode() . $deviationCode . $sizeSkuCode;
} else {
$skuKey = $object->getModelCode() . $skuColorCode . $sizeSkuCode;
}
// needed for SizeRange and SizeDetail
if (strlen($sizeCodeObject->getSizeSequence()) == 1) {
$sizeString = "0" . $sizeCodeObject->getSizeSequence() . "-" . $sizeCodeObject->getCode();
} else {
$sizeString = $sizeCodeObject->getSizeSequence() . "-" . $sizeCodeObject->getCode();
}
if (!in_array($sizeString, $sizeList)) {
array_push($sizeList, $sizeString);
}
/** 2.1 First check if this skuNumber already exits with the size in $skuList(already created list)*/
if (in_array($skuKey, $skuList)) {
/** exists so block to proceed further */
// $message = "Sku creation not possible with Size code " . $sizeCodeObject->getCode() . "<br>" . $skuKey . " already exists.";
// array_push($skuMessages, $message);
// $this->ValidationExceptionWorkflow($skuMessages);
continue;
}
$skuString = $skuKey . $sizeCodeObject;
array_push($skuNumbers, $skuString);
}
/** All the validation passed now, so we can start creating SKUs based on the list built in step 2.1 */
foreach ($skuNumbers as $skuNumber) {
$sku = substr($skuNumber, 0, 8);
$sizePath = substr($skuNumber, 8);
$listing = new DataObject\Product\Listing();
$listing->setCondition('Sku = ?', $sku);
$listing->setObjectTypes([DataObject\AbstractObject::OBJECT_TYPE_VARIANT]);
if ($listing->getObjects() != null && $listing->getObjects()[0]->getSku() == $sku) {
continue;
}
$this->CreateSku($object, $sizePath, $sku, $SelectColorObject->getColor1Code(), $SelectColorObject->getHexColor1());
}
// set list of colors created on model level
if (!in_array($SelectColorObject->getColor1Code(), $colorList)) {
$modelSelectedColor = implode(",", $colorList) . "," . $SelectColorObject->getColor1Code();
} else {
$modelSelectedColor = implode(",", $colorList);
}
$object->setselectedColors(trim($modelSelectedColor, ","));
if ($object->getSizeGrid() == null) {
$object->setSizeGrid($object->getSizeGroup());
}
//Set size range and size details
asort($sizeList);
// file_put_contents("D:\Projects\objectdata2.json", json_encode($sizeList,JSON_PRETTY_PRINT));
$minSize = "";
$sizeDetails = "";
foreach ($sizeList as $size) {
$sizestr = explode("-", $size);
if ($sizeDetails == "") {
$minSize = $sizestr[1];
}
$maxSize = $sizestr[1];
$sizeDetails = $sizeDetails . "," . $sizestr[1];;
}
$object->setsizeRange($minSize . "-" . $maxSize);
$object->setSizeRangeDetail(trim($sizeDetails, ","));
// $object->save();
// Pimcore\Cache::clearAll();
}
$object->setSelectColors(null); // reset select color 1 after sku is generated
$object->setColors2(null); // reset select color 2 after sku is generated
$object->setColors3(null); // reset select color 3 after sku is generated
$object->setOmitMandatoryCheck(true);
$object->setSkipValidation(true);
$object->setPublished(true);
}
/**
* @param $objects
* @throws \Exception
*/
public function CreateSku($modelObject, $sizePath, $skuNumber, $color1Code, $color1HexColor1): void
{
if (strlen($skuNumber) != 8) {
return;
}
$skuObject = new DataObject\Product();
$skuObject->setType(DataObject\Product::OBJECT_TYPE_VARIANT);
$skuObject->setKey($skuNumber);
$skuObject->setParentId($modelObject->getId());
$skuObject->setSku($skuNumber);
$skuObject->setProductType('Sku');
$skuObject->setProductIdentifier($skuNumber);
$skuObject->setColor1Code($color1Code);
$skuObject->setHexColor1($color1HexColor1);
// $skuObject->setColor1Code($modelObject->getColors()->getColor1Code());
// $skuObject->setHexColor1($modelObject->getColors()->getHexColor1());
if ($modelObject->getColors2()) {
$skuObject->setColor2Code($modelObject->getColors2());
$skuObject->setHexColor2($modelObject->getColors2()->getHexColor1());
}
if ($modelObject->getColors3()) {
$skuObject->setColor3Code($modelObject->getColors3());
$skuObject->setHexColor3($modelObject->getColors3()->getHexColor1());
}
$skuObject->setOnboardingStatus('pafPhase');
$skuObject->setpfstoreStatus('new');
$skuObject->setErpStatus('new');
$user = \Pimcore\Tool\Admin::getCurrentUser();
if ($user) {
$username = $user->getName();
}
$skuObject->setSkuCreator($username);
$skuObject->setSkuCreateDate(Carbon::now());
if ($sizePath != null) {
$sizeCodeObject = DataObject\Size::getByPath($sizePath);
$skuObject->setSizeCode($sizeCodeObject->getCode());
} else {
$skuObject->setSizeCode("NA");
}
$skuObject->setOmitMandatoryCheck(true);
$skuObject->setPublished(true);
$skuObject->save();
}
/**
* @param ElementEventInterface $event
*
* @throws \Pimcore\Model\Element\ValidationException
*/
public function onPreUpdate(ElementEventInterface $event): void
{
if ($event instanceof DataObjectEvent) {
$objects = $event->getObject();
$this->checkValidation($objects);
}
}
/**
* @param ElementEventInterface $event
* Set inital workflow state to sku_created to avoid further workflow on variant
*/
public
function postAdd(ElementEventInterface $event): void
{
if ($event instanceof DataObjectEvent) {
$object = $event->getObject();
if ($object instanceof DataObject\Product) {
if ('variant' == $object->gettype()) { // default workflow is added for variant
$this->setSkuWorkFlowState($object);
}
}
}
}
/**
* @param $object
* Set inital workflow state to sku_created to avoid further workflow on variant
*/
public
function setSkuWorkFlowState($object): void
{
$skuObjectId = $object->getId();
$db = \Pimcore\Db::get();
$db->query("INSERT element_workflow_state(cid, ctype, place, workflow) VALUES($skuObjectId, 'object', 'sku_created', 'Product_Workflow') ");
}
/**
* @param $message
* @throws ValidationException
*/
public function getExceptionMessage($skuMessages, $object): void
{
if (!empty($skuMessages)) {
$result = null;
// if($this->getWorkflowStatus($object) != "mode_create") {
// $message = "<h4><u>Use temporary save to save work in progress</u></h4>";
// }
// $result .= $message;
foreach ($skuMessages as $skuMessage) {
$result .= $skuMessage . "<span style='color: red;'>*</span>" . '<br>';
}
throw new ValidationException($result, 403);
}
}
/**
* @param $objects
* @throws \Exception
*/
public
function getProductTierTree($objects): void
{
$this->slugify = new Slugify();
if (null != $objects->getProductName()) {
$productName = $objects->getProductName() . '_' . $objects->getProductTitle('en');
} else {
$productName = $objects->getProductTitle('en');
}
$keyValue = $objects->getModelCode() . '_' . $this->slugify->slugify($productName);
if ($keyValue != $objects->getKey()) {
$objects->setKey($keyValue);
}
$tier_3 = $objects->getTier3();
$tier_2 = $tier_3->getParent();
$tier_1 = $tier_2->getParent();
$objects->setTier2($tier_2);
$objects->setTier1($tier_1);
$tier1Key = $objects->getTier1()->getKey();
$tier2Key = $objects->getTier2()->getKey();
$tier3Key = $objects->getTier3()->getKey();
$objectPath = explode('/', $objects->getFullPath());
$productFolder = $objectPath[1];
/* Check if Tier3 sub-folder was already created*/
if (0 == substr_count($objects->getFullPath(), "/" . $tier3Key)) {
$tierFoldersPath = $productFolder . '/' . $tier1Key . '/' . $tier2Key . '/' . $tier3Key;
$tierPathExist = DataObject\Service::pathExists('/' . $tierFoldersPath);
if (!$tierPathExist) {
DataObject\Service::createFolderByPath($tierFoldersPath);
}
$Tier3Object = DataObject::getByPath('/' . $tierFoldersPath);
$objectPath = '/' . $tierFoldersPath . '/';
$objects->setParentId($Tier3Object->getID());
$objects->setPath($objectPath);
}
}
/**
* @param $folderName
* @param int $parentId
* @return bool|int
* @throws \Exception
*/
protected
function createFolder($folderName, $parentId = 1): bool|int
{
// check if folder exists
if ($folderId = $this->isFolderExists($folderName, $parentId)) {
// var_dump($folderId);die;
return $folderId;
} else {
// create folder
$folder = Folder::create(['o_key' => $folderName, 'o_parentId' => $parentId]);
$folder->save();
// var_dump($folderId);
// var_dump('folder');die;
return $folder->getId();
}
}
protected function isFolderExists($folderName, $parentId = 1): bool|int
{
// search if folder exists
if (1 == $parentId) {
$folder = Folder::getByPath("/$folderName");
} else {
$path = Folder::getById($parentId)->getRealFullPath();
$folder = Folder::getByPath("$path/$folderName");
}
if ($folder) {
return $folder->getId();
}
return false;
}
/**
* @param $objects
* @throws ValidationException
*/
public function checkValidation($objects): void
{
$baseMaterial1percentage = 0;
$baseMaterial2percentage = 0;
$baseMaterial3percentage = 0;
$errors = [];
$hastDate = date("Y-m-d h:i:s A");
$onboaringDate = date("Y-m-d");
if ($objects instanceof DataObject\Product) {
if ($objects instanceof DataObject\Product and 'variant' != $objects->gettype()) {
$skipValidation = $objects->getSkipValidation();
/** TODO: Refactor this chain of validations
* Instead of a massive chain of ifs with mostly repeated code, we should add these checks in an array
* Then associate the corresponding error messages
* And finally call these checks inside a foreach loop
* This way it is easier to read and understand the code as well as locate specific checks and change them
* Ex:
* $checks = [
* [$objects->getTier3(), 'Tier3 is required.'],
* [$objects->getMarkSegment(), 'Market segment is required.'],
* [$objects->getModelCode(), 'Model code is required.'],
* …
* …
* ];
*
* foreach ($checks as $check) {
* if ($check[0] === null || $check[0] === false) {
* array_push($errors, $check[1]);
* }
* }
*
*/
// This validation is must to save Product data
if (null == $objects->getTier3()) {
$message = 'Tier3 is required.';
array_push($errors, $message);
}
if (null == $objects->getMarkSegment()) {
$message = 'Market segment is required.';
array_push($errors, $message);
}
if (null == $objects->getModelCode()) {
$message = 'Model code is required.';
array_push($errors, $message);
}
if ($objects->getConfiguratorType() == 'base_component') {
if (substr($objects->getModelCode(), 0, 2) != 'CB') {
$message = "Model code should start with CB ";
array_push($errors, $message);
}
}
if ('yes' == $objects->getIsConfigurable() && ($objects->getConfiguratorType() == "" || $objects->getConfiguratorType() == null)) {
$message = 'Configurator type is required.';
array_push($errors, $message);
}
if ($this->getWorkflowStatus($objects) == "mode_create" && preg_match('/[^A-Z0-9]/', ($objects->getModelCode()))) {
$message = 'Model code cannot be special character and lower case !';
array_push($errors, $message);
}
$productModelObject = DataObject\Product::getByModelCode($objects->getModelCode(), ['limit' => 1, 'unpublished' => false]);
if (null != $productModelObject && $productModelObject->getId() !== $objects->getId()) {
$message = 'Model number already taken. Please enter new model code';
array_push($errors, $message);
}
if ($this->getWorkflowStatus($objects) == "mode_create" && null != $objects->getModelCode() && strlen($objects->getModelCode()) <= 4) {
$message = 'Model code length should be either 5 or 6.';
array_push($errors, $message);
}
if ($this->getWorkflowStatus($objects) == "mode_create" && null != $objects->getModelCode() && strlen($objects->getModelCode()) >= 7) {
$message = 'Model code length can not exceed 6';
array_push($errors, $message);
}
if (null == $objects->getProductTitle('en')) {
$message = 'Product title is required.';
array_push($errors, $message);
}
/** Block adding sku description, color data to Model, those attributes must be under sku */
if (null != $objects->getSkuDescription()) {
$message = 'Sku description is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor1Code()) {
$message = 'Color1 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor2Code()) {
$message = 'Color2 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor3Code()) {
$message = 'Color3 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getHexColor1()) {
$message = 'Hex color1 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getHexColor2()) {
$message = 'Hex color2 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getHexColor3()) {
$message = 'Hex color3 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor1PmsReference()) {
$message = 'Color1 PMS is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor1PmsReference()) {
$message = 'Color2 PMS is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getColor1PmsReference()) {
$message = 'Color3 PMS is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getTcxColor1()) {
$message = 'TCX color1 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getTcxColor2()) {
$message = 'TCX color2 is of sku, not Model.';
array_push($errors, $message);
}
if (null != $objects->getTcxColor3()) {
$message = 'TCX color3 is of sku, not Model.';
array_push($errors, $message);
}
//!Commented on 2023-09-21
//!NOTES: SkipValidation is only being set in a later stage
/*
* When creating a product, it will always throw this error
* because at this stage you cannot add yet a Link Component to the model
*/
/*if ($objects->getSkipValidation() == false) {
if ($objects->getConfiguratorType() == 'base_component') {
if (null == $objects->getLinkComponent()) {
$message = 'Link Component is required.';
array_push($errors, $message);
}
}
}*/
}
if ($objects instanceof DataObject\Product and 'variant' != $objects->gettype()) {
// Fill in unique Product Identifier as ModelCode
if (null != $objects->getModelCode() && $objects->getModelCode() != $objects->getProductIdentifier()) {
$objects->setProductIdentifier($objects->getModelCode());
}
//Model with tier hiearchy
if (null != $objects->getTier3()) {
$this->getProductTierTree($objects);
}
$this->getSustainability($objects);
}
/**
* Further validation is skipped while creating model or item. Otherwise full
* validaiton is done based on the attribute matrix provide by PD.
* End user wil have force save toggle on the screen to validation and save
*/
if ($objects->getSkipValidation() || $this->getWorkflowStatus($objects) == "mode_create") {
$objects->setSkipValidation(false);
$objects->setOmitMandatoryCheck(true);
} else {
/** Based on mandatory setting for model or sku, validation is applied */
if ($objects instanceof DataObject\Product) {
$manAttributes = [];
if ('variant' != $objects->gettype()) {
$settingObject = DataObject\SettingAttributes::getBySettingCode('manadatoryModel', 1);
if ($settingObject) {
$manAttributes = explode(",", trim($settingObject->getAttributes()));
}
/** Get the mandatory attributes setup on Tier3 or Tier1 level
*/
if ($objects->getTier3()->getMandatoryAttributes()) {
$manProdSpecific = explode(",", trim($objects->getTier3()->getMandatoryAttributes()));
} else {
$manProdSpecific = explode(",", trim($objects->getTier1()->getMandatoryAttributes()));
}
$manAttributes = array_merge($manAttributes, $manProdSpecific);
} else {
$settingObject = DataObject\SettingAttributes::getBySettingCode('mandatorySku', 1);
if ($settingObject) {
$manAttributes = explode(",", trim($settingObject->getAttributes()));
}
}
if (is_array($manAttributes)) {
foreach ($manAttributes as $manAttribute) {
if (strlen($manAttribute) > 1) {
$getattribute = 'get' . $manAttribute;
if (null == $objects->$getattribute()) {
$message = $this->getPimMessage($manAttribute);
if ($message != "") {
array_push($errors, $this->getPimMessage($manAttribute));
} else {
array_push($errors, $manAttribute . " is required.");
}
}
}
}
}
if ($objects instanceof DataObject\Product and 'variant' == $objects->gettype()) {
/** Hex Color1 validation */
if ($objects->getHexColor1()) {
if (strlen($objects->getHexColor1()) != 6) {
$message = 'Length of Color1 hex code must be 6.';
array_push($errors, $message);
}
}
/** Hex Color2 validation */
if ($objects->getHexColor2()) {
if (strlen($objects->getHexColor2()) != 6) {
$message = 'Length of Color2 hex code must be 6.';
array_push($errors, $message);
}
}
/** Hex Color3 validation */
if ($objects->getHexColor3()) {
if (strlen($objects->getHexColor3()) != 6) {
$message = 'Length of Color3 hex code must be 6.';
array_push($errors, $message);
}
}
/** update hexColorcode when it is still empty and color2 or color3 is added or updated */
if ($objects->getColor2Code() && $objects->getHexColor2() == null) {
$objects->setHexColor2($objects->getColor2Code()->getHexColor1());
}
/** update hexColorcode when it is still empty and color2 or color3 is added or updated */
if ($objects->getColor3Code() && $objects->getHexColor3() == null) {
$objects->setHexColor3($objects->getColor3Code()->getHexColor1());
}
}
}
/** Base Material 1 exceed 100 */
if ($objects->getBaseMaterial1()) {
foreach ($objects->getBaseMaterial1() as $baseMaterial1) {
$baseMaterial1Object = DataObject\MaterialDetail::getById($baseMaterial1->getElementId());
if ($baseMaterial1->getCompositionofmaterial1() != null) {
$baseMaterial1percentage = $baseMaterial1percentage + $baseMaterial1->getCompositionofmaterial1();
} else {
$message = "Base material 1 [" . $baseMaterial1Object->getMaterialDetail() . "] cannot be empty";
array_push($errors, $message);
}
}
if ($baseMaterial1percentage != 100) {
$message = 'Base material 1 composition must be 100 %';
array_push($errors, $message);
}
}
/** Base Material 2 exceed 100 */
if ($objects->getBaseMaterial2()) {
foreach ($objects->getBaseMaterial2() as $baseMaterial2) {
$baseMaterial2Object = DataObject\MaterialDetail::getById($baseMaterial2->getElementId());
if ($baseMaterial2->getCompositionofmaterial2() != null) {
$baseMaterial2percentage = $baseMaterial2percentage + $baseMaterial2->getCompositionofmaterial2();
} else {
$message = "Base material 2 [" . $baseMaterial2Object->getMaterialDetail() . "] cannot be empty";
array_push($errors, $message);
}
}
if ($baseMaterial2percentage != 100) {
$message = 'Base material 2 composition must be 100 %';
array_push($errors, $message);
}
}
/** Base Material 3 exceed 100 */
if ($objects->getBaseMaterial3()) {
foreach ($objects->getBaseMaterial3() as $baseMaterial3) {
$baseMaterial3Object = DataObject\MaterialDetail::getById($baseMaterial3->getElementId());
if ($baseMaterial3->getCompositionofmaterial3() != null) {
$baseMaterial3percentage = $baseMaterial3percentage + $baseMaterial3->getCompositionofmaterial3();
} else {
$message = "Base material 3 [" . $baseMaterial3Object->getMaterialDetail() . "] cannot be empty";
array_push($errors, $message);
}
}
if ($baseMaterial3percentage != 100) {
$message = 'Base material 3 composition must be 100 %';
array_push($errors, $message);
}
}
if ($objects->getSkipValidation() == false) {
if ($objects->getConfiguratorType() == 'base_component') {
if (null == $objects->getLinkComponent()) {
$message = 'Link Component is required.';
array_push($errors, $message);
}
}
}
if ('variant' != $objects->gettype()) {
if ($objects->getSkipValidation() == false) {
if ($objects->getConfiguratorType() == 'component') {
if ($objects->getStoreVisibility() != "1" || $objects->getStoreVisibility() != 1) {
$message = 'For the configurator components only “Not display individually” is allowed. Please adjust the Store visibility setting to this required value';
array_push($errors, $message);
}
}
}
}
}
// throw ExceptionMessage of validation
$this->getExceptionMessage($errors, $objects);
if ($objects instanceof DataObject\Product and 'variant' == $objects->gettype()) {
$errors = [];
// Fill in unique Product Identifier as skuCode
if (null != $objects->getSku() && $objects->getSku() != $objects->getProductIdentifier()) {
$objects->setProductIdentifier($objects->getSku());
}
if ($objects->getOnboardingStatus() == "pafPhase") {
$objects->setDatePafPhase(Carbon::parse($onboaringDate));
} elseif ($objects->getOnboardingStatus() == "preProductionPhase") {
$objects->setDatePreproductionPhase(Carbon::parse($onboaringDate));
} elseif ($objects->getOnboardingStatus() == "productionPhase") {
$objects->setDateProductionPhase(Carbon::parse($onboaringDate));
} elseif ($objects->getOnboardingStatus() == "shippingPhase") {
$objects->setDateShippingPhase(Carbon::parse($onboaringDate));
} elseif ($objects->getOnboardingStatus() == "readyForSale") {
$objects->setDateReadyForSale(Carbon::parse($onboaringDate));
} elseif ($objects->getOnboardingStatus() == "launched") {
$objects->setDateLaunched(Carbon::parse($onboaringDate));
}
// When pfstore status is move to Active, set onboarding status to Launched
// if($objects->getPfstoreStatus() == "active" && $objects->getOnboardingStatus() != 'launched' ) {
// $objects->setOnboardingStatus('launched');
// }
}
$this->checkForSubMenuCategory($objects);
$this->correctFabricWeight($objects);
$this->updateSkuParentModificationDate($objects);
if ($user = Admin::getCurrentUser()) {
if ($objects->gettype() == 'object') {
$productVaiants = $objects->getChildren([\Pimcore\Model\DataObject\AbstractObject::OBJECT_TYPE_VARIANT], true);
foreach ($productVaiants as $productVaiant) {
$productObject = DataObject\Product::getById($productVaiant->getId(), ['force'=> true]);
if ($productObject) {
// if ($skipValidation == false || $skipValidation != true) {
$productObject->setSkipValidation(true);
$productObject->setOmitMandatoryCheck(true);
$productObject->setHashDate(strtotime($hastDate));
$productObject->setPublished(true);
$productObject->save();
// }
}
}
// if ($objects->getSkipValidation() == false) {
$objects->setHashDate(strtotime($hastDate));
// }
} else {
// if ($objects->getSkipValidation() == false) {
$objects->setHashDate(strtotime($hastDate));
// }
}
}
}
}
public function getPimMessage($messageCode)
{
$pimMessageObject = DataObject\PimMessages::getByMessageCode($messageCode, 1);
if ($pimMessageObject) {
return $pimMessageObject->getMessage();
} else {
return "";
}
}
/**
* @param $object
* @throws \Exception
*
* Check for Variant and Update Parent Modification Date only.
* Update only when pfstore_status is active and no change today
*/
protected function updateSkuParentModificationDate($object)
{
if ($object instanceof DataObject\Product && $object->getType() == 'variant') {
$parent = $object->getParent();
if (date("Ymd") != date("Ymd", $parent->getModificationDate()) && $object->getPfstoreStatus() == "active") {
$parent->setModificationDate(Carbon::now()->timestamp);
$parent->setSkipValidation(true);
$parent->save();
};
}
}
/**
* When product weight is not entered and unit is selected, reset unit to empty to avoid inhertiance issue
*/
protected function correctFabricWeight($object)
{
if ($object instanceof DataObject\Product) {
if (in_array(trim($object->getFabricWeight(), " "), array("g/m2", "gauge", "gram"))) {
$object->setFabricWeight(null);
}
if (in_array(trim($object->getFabricWeight2(), " "), array("g/m2", "gauge", "gram"))) {
$object->setFabricWeight2(null);
}
if (in_array(trim($object->getFabricWeight3(), " "), array("g/m2", "gauge", "gram"))) {
$object->setFabricWeight3(null);
}
}
}
/**
* @param $objects
* @throws ValidationException
*/
private function checkForSubMenuCategory($objects)
{
$menuSub = new DataObject\MenuCategory\Listing();
$menuChild = $menuSub->getObjects();
if ($objects->getDefaultSubCategory()) {
foreach ($menuChild as $child) {
if ($objects->getDefaultSubCategory()->getChildren() == true) {
$message[] = "You have selected a menu category. Please select a sub-menucategory";
$this->getExceptionMessage($message, $child);
}
}
}
}
public function getSustainability($objects)
{
$sustainabilityTotalScore = 0;
if (!empty($objects->getSustainablity()->getSustainabilityRanking()) || ($objects->getSustainablity()->getSustainabilityRanking() != null || $objects->getSustainablity()->getSustainabilityRanking() != "")) {
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getMaterials50pctinformation()) || $objects->getSustainablity()->getSustainabilityRanking()->getMaterials50pctinformation() == null || $objects->getSustainablity()->getSustainabilityRanking()->getMaterials50pctinformation() == "") {
$materialsScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('materials50pct', '1');
$materialsScoreTotal = $objects->getSustainablity()->getSustainabilityRanking()->getMaterials50pctinformation()->getSustainableMaterialInformationScore() * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $materialsScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getEndoflifeInformation()) || $objects->getSustainablity()->getSustainabilityRanking()->getEndoflifeInformation() == null || $objects->getSustainablity()->getSustainabilityRanking()->getEndoflifeInformation() == "") {
$endOfLifeProductLevelScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('endOfLifeProductLevel', '1');
$endOfLifeProductLevelScoreTotal = $objects->getSustainablity()->getSustainabilityRanking()->getEndoflifeInformation()->getEndOfLifeInformationScore() * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $endOfLifeProductLevelScoreTotal;
}
if ($objects->getCountryOfOrigin() == null || empty($objects->getCountryOfOrigin()) || $objects->getCountryOfOrigin()->getEpiScore() == null || $objects->getCountryOfOrigin()->getEpiScore() == "") {
$productionEpiScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('productionEpi', '1');
$productionEpiScoreTotal = $objects->getCountryOfOrigin()->getEpiScore() * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $productionEpiScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getCertificationsEnvironmental()) || $objects->getSustainablity()->getSustainabilityRanking()->getCertificationsEnvironmental() == null || $objects->getSustainablity()->getSustainabilityRanking()->getCertificationsEnvironmental() == "") {
$certificationEnvironmentScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('certificationEnvironment', '1');
$certificationMaxScore = $this->getCertificationData($objects, 'certificationsEnvironmental', 'certificationEnvironmentalScore');
$certificationEnvironmentScoreTotal = $certificationMaxScore * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $certificationEnvironmentScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getCertificationsSocial()) || $objects->getSustainablity()->getSustainabilityRanking()->getCertificationsSocial() == null || $objects->getSustainablity()->getSustainabilityRanking()->getCertificationsSocial() == "") {
$certificationSocialScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('certificationSocial', '1');
$certificationSocialMaxScore = $this->getCertificationData($objects, 'certificationsSocial', 'certificationSocialScore');
$certificationSocialScoreTotal = $certificationSocialMaxScore * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $certificationSocialScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getSustainableBranding()) || $objects->getSustainablity()->getSustainabilityRanking()->getSustainableBranding() == null || $objects->getSustainablity()->getSustainabilityRanking()->getSustainableBranding() == "") {
$sustainabilityBrandingScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('sustainabilityBranding', '1');
$sustainabilityMaxScore = $this->getCertificationData($objects, 'sustainableBranding', 'sustainableBrandingScore');
$sustainabilityBrandingScoreTotal = $sustainabilityMaxScore * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $sustainabilityBrandingScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getPackaging50pctinformation()) || $objects->getSustainablity()->getSustainabilityRanking()->getPackaging50pctinformation() == null || $objects->getSustainablity()->getSustainabilityRanking()->getPackaging50pctinformation() == "") {
$packagingScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('packaging50pct', '1');
$packagingScoreTotal = $objects->getSustainablity()->getSustainabilityRanking()->getPackaging50pctinformation()->getSustainablePackagingInformationScore() * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $packagingScoreTotal;
}
if (empty($objects->getSustainablity()->getSustainabilityRanking()->getTraceableSupplyChainInformation()) || $objects->getSustainablity()->getSustainabilityRanking()->getTraceableSupplyChainInformation() == null || $objects->getSustainablity()->getSustainabilityRanking()->getTraceableSupplyChainInformation() == "") {
$traceableSupplyChainScoreTotal = "No score set!";
} else {
$sustainabilitySettings = DataObject\SustainabilitySettings::getByCode('traceableSupplyChain', '1');
$traceableSupplyChainScoreTotal = $objects->getSustainablity()->getSustainabilityRanking()->getTraceableSupplyChainInformation()->getTraceableSupplyChainInformationScore() * $sustainabilitySettings->getWeight();
$sustainabilityTotalScore = $sustainabilityTotalScore + $traceableSupplyChainScoreTotal;
}
if ($sustainabilityTotalScore < 25) {
$rankingLabel = "0 to 24";
$collectionLabel = null;
} elseif ($sustainabilityTotalScore >= 25 && $sustainabilityTotalScore <= 49) {
$rankingLabel = "25 to 49";
$collectionLabel = 'greenConcept';
} elseif ($sustainabilityTotalScore >= 50 && $sustainabilityTotalScore <= 74) {
$rankingLabel = "50 to 74";
$collectionLabel = 'greenConcept';
} elseif ($sustainabilityTotalScore >= 75) {
$rankingLabel = "75 to 100";
$collectionLabel = 'greenConcept';
} else {
$rankingLabel = "0 to 24";
$collectionLabel = '';
}
if (empty($objects->getCollectionLabel()) || $objects->getCollectionLabel() == "" || $objects->getCollectionLabel() == null) {
$collectionLabelValue = array_filter(array_unique(array_merge([$objects->getCollectionLabel()], [$collectionLabel])));
} else {
$collectionLabelValue = array_filter(array_unique(array_merge($objects->getCollectionLabel(), [$collectionLabel])));
}
if($objects->getCountryOfOrigin() != null || $objects->getCountryOfOrigin() != "" || !empty($objects->getCountryOfOrigin())) {
if ($objects->getCountryOfOrigin()->getCountryName() == 'PRC') {
$objects->getSustainablity()->getSustainabilityRanking()->setCountryOfOriginInformation('China');
} else {
$lowerCase = strtolower($objects->getCountryOfOrigin()->getCountryName());
$objects->getSustainablity()->getSustainabilityRanking()->setCountryOfOriginInformation(ucfirst($lowerCase));
}
}
$objects->getSustainablity()->getSustainabilityRanking()->setMaterialsScoreTotal($materialsScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setEndOfLifeProductLevelScoreTotal($endOfLifeProductLevelScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setProductionEpiScoreTotal($productionEpiScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setCertificationEnvironmentScoreTotal($certificationEnvironmentScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setCertificationSocialScoreTotal($certificationSocialScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setSustainabilityBrandingScoreTotal($sustainabilityBrandingScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setPackagingScoreTotal($packagingScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setTraceableSupplyChainScoreTotal($traceableSupplyChainScoreTotal);
$objects->getSustainablity()->getSustainabilityRanking()->setSustainabilityTotalScore($sustainabilityTotalScore);
$objects->getSustainablity()->getSustainabilityRanking()->setRankingLabel($rankingLabel);
$objects->getSustainablity()->getSustainabilityRanking()->setCollectionLabel($collectionLabel);
$objects->setCollectionLabel($collectionLabelValue);
}
}
private function getCertificationData($object, $relationName, $score)
{
$relationName = 'get' . ucfirst($relationName);
$score = 'get' . ucfirst($score);
$allScore = [];
if($object->getSustainablity()->getSustainabilityRanking()->$relationName() != null || !empty($object->getSustainablity()->getSustainabilityRanking()->$relationName())) {
$scoreData = $object->getSustainablity()->getSustainabilityRanking()->$relationName();
foreach ($scoreData as $scores) {
array_push($allScore, $scores->$score());
}
$maxValue = max($allScore);
return $maxValue;
}
return 0;
}
/**
* @param GenericEvent $objectBrickDefinitionGenericEvent
* @throws \Exception
*/
public function generatePfAttributeDefinition(GenericEvent $objectBrickDefinitionGenericEvent)
{
$folderId = $this->createFolder(self::FOLDER_NAME);
$objects = $objectBrickDefinitionGenericEvent->getArguments();
foreach ($objects as $object) {
foreach (($object) as $brick) {
$objectBrickObjects = json_decode(json_encode($object), true);
if ($objectBrickObjects['key'] != null || $objectBrickObjects['key'] != "") {
if ($objectBrickObjects['layoutDefinitions'] != null || $objectBrickObjects['layoutDefinitions'] != "") {
if (($objectBrickObjects['layoutDefinitions']['children'])) {
foreach ($objectBrickObjects['layoutDefinitions']['children'] as $layoutDefinition) {
if ($layoutDefinition['children']) {
$optionName = null;
//attribute child to import in Pf Attribute classes
foreach ($layoutDefinition['children'] as $valueClass) {
$optionValue = [];
$attributeChildValuesObject = [];
$optionName = $valueClass['name'];
if ($valueClass['fieldtype'] == "select" || $valueClass['fieldtype'] == "multiselect") {
if ($valueClass['options']) {
foreach ($valueClass['options'] as $options) {
$optionValue[] = $options['value'];
}
}
$attributeChildValuesObject = $this->associateAttributeValue($optionValue, $folderId, $objectBrickObjects['key']);
$this->associatePfAttribute($valueClass['name'], $attributeChildValuesObject, $objectBrickObjects['key'],$valueClass['fieldtype']);
} else {
$attributeChildValuesObject = $this->associateAttributeValue(array($valueClass['name']), $folderId, $objectBrickObjects['key']);
$this->associatePfAttribute($valueClass['name'], $attributeChildValuesObject, $objectBrickObjects['key'],$valueClass['fieldtype']);
}
}
}
}
}
}
}
}
}
}
/**
* @param $attributeValues
* @return array
* @throws \Exception
*/
public function associateAttributeValue($attributeValues, $folderId, $dynamicFolderName)
{
$attributeObjectValues = [];
$dynamicFolderId = $this->createFolder($dynamicFolderName, $folderId);
$valueFolderId=$this->createFolder( self::FOLDER_NAME_ATTRIBUTEVALUE, $dynamicFolderId);
// $folderId = $this->createFolder(self::FOLDER_INSIDE_ATTRIBUTEVALUE, $this->createFolder(self::FOLDER_INSIDE_FOLDER));
foreach ($attributeValues as $attributeValue) {
$attributeValueObject = DataObject\AttributeValue::getByCode($attributeValue, 1);
$key = strtolower($attributeValue);
if (!$attributeValueObject) {
$attributeValueObject = new DataObject\AttributeValue();
$attributeValueObject->setCode($attributeValue);
$attributeValueObject->setKey($key);
$attributeValueObject->setParentId($valueFolderId);
}
// $attributeValueObject->setName($attributeValue);
$attributeValueObject->setPublished(true);
$attributeValueObject->save();
$attributeObjectValues[$attributeValue] = $attributeValueObject;
}
return $attributeObjectValues;
}
/**
* @param $attributes
* @param $attributeValueObject
* @throws \Exception
*/
public function associatePfAttribute($attributes, $attributeValueObject, $dynamicFolderId, $fieldtype)
{
$createDynamicFolderId = $this->createFolder($dynamicFolderId, $this->createFolder(self::FOLDER_NAME));
$folderId = $this->createFolder(self::FOLDER_NAME_PFATTRIBUTE, $createDynamicFolderId);
foreach (array($attributes) as $attribute) {
$attributeObject = DataObject\AttributeName::getByCode($attribute, 1);
$key = strtolower($attribute);
if (!$attributeObject) {
$attributeObject = new DataObject\AttributeName();
$attributeObject->setCode($attribute);
$attributeObject->setKey($key);
$attributeObject->setParentId($folderId);
}
$attributeObject->setFieldType($fieldtype);
$attributeObject->setLinkedAttributeValue($attributeValueObject);
$attributeObject->setPublished(true);
$attributeObject->save();
}
}
}