<?php
/**
* Active Publishing - Creative Common CC BY 4.0
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Active Publishing (https://activepublishing.fr)
* @license Creative Common CC BY 4.0
* @author Active Publishing <contact@active-publishing.fr>
*/
namespace BricomanBundle\EventListener;
use BricomanBundle\BricomanBundle;
use ActivePublishing\Tool\ApTool;
use BricomanBundle\Model\DataObject\ActivePaginatorChapters;
use Pimcore\Db;
use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Model\DataObject;
use Pimcore\Model\Document;
use Pimcore\Model\Element\ValidationException;
use Pimcore\Model\Property;
use Pimcore\Model\User;
use Symfony\Component\Serializer\Encoder\JsonDecode;
/**
* Class ActivePaginatorListener
* @package BricomanBundle\EventListener
*/
class ActivePaginatorListener
{
// -----------------------------------------------------------------------------------------------------------------
// LISTENERS
// -----------------------------------------------------------------------------------------------------------------
/**
* @param ElementEventInterface $e
* @throws \Exception
*/
public function onPostUpdate (ElementEventInterface $e)
{
if ($e instanceof DataObjectEvent)
{
$object = $e->getObject();
// Update when a ActivePaginator object is saved
if ($object instanceof DataObject\ActivePaginator)
{
// Update properties of document\printcontainer
$dependencies = $object->getDependencies();
$requiredBy = $dependencies->getRequiredBy();
if (!empty($requiredBy))
{
foreach ($requiredBy as $item) {
if ($item['type'] == "document")
{
$document = Document::getById($item['id']);
$NamespaceCatalog = [
"@AP\ActiveWireframeBundle\Controller\CatalogController",
"@ActiveWireframeBundle\Controller\CatalogController",
"catalog"
];
if (in_array($document->getController(), $NamespaceCatalog))
{
$document->save();
}
}
}
}
// Update chapter (In case or the config for recover product data has changed)
if ($object->hasChildren())
{
foreach ($object->getChildren() as $activePaginatorChapters)
{
if ($activePaginatorChapters instanceof ActivePaginatorChapters)
{
$activePaginatorChapters->save();
}
}
}
// Update declinaison data if saving a "master" ActivePaginator object
if (!$object->hasProperty("active_paginator_master_link"))
{
$this->updateDeclinaison($object);
}
}
// Update when a ActivePaginatorChapter object is saved
if ($object instanceof DataObject\ActivePaginatorChapters)
{
$activePaginator = $object->getParent();
if ($activePaginator instanceof DataObject\ActivePaginator
&& !$activePaginator->hasProperty("active_paginator_master_link")
) {
$this->updateDeclinaison($activePaginator);
}
}
}
}
/**
* @param ElementEventInterface $e
* @throws \Exception
*/
public function onPreUpdate (ElementEventInterface $e)
{
if ($e instanceof DataObjectEvent)
{
$object = $e->getObject();
// Update RecoverItem before saving Chapter
if ($object instanceof DataObject\ActivePaginatorChapters)
{
$riOldData = $this->getRiOldData($object);
$riChangeData = [];
$jsonDecode = new JsonDecode(true);
if (array_key_exists('data', $_POST) && is_json($_POST['data']))
{
$riChangeData = $this->getRiChangeData($object, $jsonDecode->decode($_POST['data'], 'json'));
}
$recoverItems = [];
$items = $object->getItems();
$parent = $object->getParent();
$translator = \Pimcore::getContainer()->get('translator');
if ($parent instanceof DataObject\ActivePaginator) {
foreach ($parent->getProperties() as $property) {
if ($property->getName() == 'bricoman_date_pub_obj' || $property->getName() == 'bricoman_date_ref_obj') {
if (empty($property->getData())) {
// Si l'Active paginator parent n'est pas sauvegardé au préalable
throw new ValidationException($translator->trans('bricoman_active_paginator_not_save_msg'));
}
}
}
}
if (!empty($items) && !is_null($items) && $parent instanceof DataObject\ActivePaginator)
{
$targetObjectData = $parent->getBlocTarget();
$targetObjectArray = [];
if (!empty($targetObjectData)) {
foreach ($targetObjectData as $targetObject) {
$targetObjectArray[] = $targetObject['targetObject']->getData();
}
}
$elsMetadata = ['wi' => [], 'oi' => []];
$recoverItemsData = $this->getRi($items, $riOldData, $riChangeData, $targetObjectArray, $elsMetadata);
ksort($recoverItemsData['wi']);
$recoverItems = $recoverItemsData['wi'] + $recoverItemsData['oi'];
}
$object->setRecoverItems($recoverItems);
}
// Updating list in chapter config if a object is added or deleted
if ($object instanceof DataObject\ITNomenclature)
{
if ($object->getDependencies())
{
$arrayRequiredBy = $object->getDependencies()->getRequiredBy();
if ($arrayRequiredBy)
{
foreach ($arrayRequiredBy as $node)
{
if ($node['type'] == 'object')
{
$objectRequiredBy = DataObject::getById($node['id']);
if ($objectRequiredBy instanceof DataObject\ActivePaginatorChapters)
{
$objectRequiredBy->save();
}
}
}
}
}
}
if ($object instanceof DataObject\ActivePaginator)
{
// Gestion des propriétés
$this->addProperties($object);
}
}
}
// -----------------------------------------------------------------------------------------------------------------
// HELP FUNCTIONS
// -----------------------------------------------------------------------------------------------------------------
/**
* @param $items
* @param $riOldData
* @param $riChangeData
* @param $targetObjectArray
* @param array $elsMetadata
* @return array
*/
private function getRi($items, $riOldData, $riChangeData, $targetObjectArray, $elsMetadata = [])
{
try {
foreach ($items as $item) {
if ($item instanceof DataObject\Concrete) {
if (property_exists($item, 'products')) {
$products = $item->getProducts();
if (!empty($products)) {
foreach ($products as $product) {
if (in_array($product->getClassName(), $targetObjectArray)) {
if (array_key_exists($product->getId(), $riChangeData)) {
$index = $riChangeData[$product->getId()]['index'];
$elsMetadata['wi'][$index] = $this->createElementMetadata(
$product, $riOldData, $riChangeData
);
} else {
$elsMetadata['oi'][] = $this->createElementMetadata(
$product, $riOldData, $riChangeData
);
}
}
}
}
} else if (in_array($item->getClassName(), $targetObjectArray)) {
if (array_key_exists($item->getId(), $riChangeData)) {
$index = $riChangeData[$item->getId()]['index'];
$elsMetadata['wi'][$index] = $this->createElementMetadata($item, $riOldData, $riChangeData);
} else {
$elsMetadata['oi'][] = $this->createElementMetadata($item, $riOldData, $riChangeData);
}
}
}
if ($item->hasChildren()) {
$elsMetadata = $this->getRi(
$item->getChildren(), $riOldData, $riChangeData, $targetObjectArray, $elsMetadata
);
}
}
} catch (\Exception $ex) {
ApTool::log(BricomanBundle::BUNDLE_ID, $ex->getTraceAsString());
}
return $elsMetadata;
}
/**
* @param $object
* @param array $riChangeData
* @return array
*/
private function getRiChangeData ($object, $riChangeData = [])
{
$data = [];
if (array_key_exists('recoverItems', $riChangeData)) {
if (!empty($riChangeData['recoverItems'])) {
foreach ($riChangeData['recoverItems'] as $dataIndex => $dataItem) {
$data[$dataItem['id']] = [
'publish' => (bool) $dataItem['publish'],
'index' => intval($dataIndex)
];
}
}
} else {
$database = Db::get();
$cid = trim($object->getClassId());
$oid = trim($object->getId());
if (($cid != "") && ($oid != "")) {
$faObjectApc = $database->fetchAll("SELECT * FROM `object_$cid` WHERE oo_id = $oid");
if (!empty($faObjectApc)) {
foreach ($faObjectApc as $dataObjectApc) {
$recoverItemsArray = explode(",", $dataObjectApc['recoverItems']);
if (!empty($recoverItemsArray)) {
foreach ($recoverItemsArray as $dataIndex => $recoverItemString) {
if ($recoverItemString != "") {
$recoverItemId = str_replace("object|", "", $recoverItemString);
$faObjectMetaApc = $database->fetchAll(
"SELECT * FROM `object_metadata_$cid` WHERE o_id = $oid AND dest_id = $recoverItemId"
. " AND `fieldname` = 'recoverItems' AND `column` = 'publish'"
);
if (!empty($faObjectMetaApc)) {
$data[$recoverItemId] = [
'publish' => $faObjectMetaApc[0]['data'],
'index' => intval($dataIndex)
];
}
}
}
}
}
}
}
}
return $data;
}
/**
* @param DataObject\Concrete $object
* @return array
*/
private function getRiOldData (DataObject\Concrete $object)
{
$database = Db::get();
$cid = $object->getClassId();
$oid = $object->getId();
$data = [];
if (($cid != "") && ($oid != "")) {
$fetchAll = $database->fetchAll(
"SELECT * FROM `object_metadata_$cid` WHERE o_id = $oid"
. " AND `fieldname` = 'recoverItems' AND `column` = 'publish'"
);
if (!empty($fetchAll)) {
foreach ($fetchAll as $dataItem) {
$data[$dataItem['dest_id']] = [
'publish' => (bool)$dataItem['data']
];
}
}
}
return $data;
}
/**
* @param DataObject\Concrete $object
* @param $riOldData
* @param $riChangeData
* @return bool|DataObject\Data\ElementMetadata
*/
private function createElementMetadata (DataObject\Concrete $object, $riOldData, $riChangeData)
{
try {
$publish = true;
// Get AllData
if (array_key_exists($object->getId(), $riOldData)) {
$publish = (bool) $riOldData[$object->getId()]['publish'];
}
// Get New Data
if (array_key_exists($object->getId(), $riChangeData)) {
$publish = (bool) $riChangeData[$object->getId()]['publish'];
}
$elementMetadata = new DataObject\Data\ElementMetadata('recoverItems', [
'publish',
'incoming',
'outgoing',
'ispublishable',
'modificationdatepim',
'rang'
], $object);
$elementMetadata->setPublish($publish);
return $elementMetadata;
} catch (\Exception $ex) {
ApTool::log(BricomanBundle::BUNDLE_ID, $ex->getTraceAsString());
}
return false;
}
/**
* @param DataObject\ActivePaginator $masterConfig
* @throws \Exception
*/
private function updateDeclinaison (DataObject\ActivePaginator $masterConfig)
{
$rootFolder = $masterConfig->getParent();
$doService = new DataObject\Service(User::getById(0));
if ($rootFolder instanceof DataObject\Folder && $rootFolder->hasChildren() && $masterConfig->hasChildren())
{
foreach ($rootFolder->getChildren() as $configChild)
{
if ($configChild instanceof DataObject\ActivePaginator)
{
$propertyMasterLink = $configChild->hasProperty("active_paginator_master_link")
? $configChild->getProperty("active_paginator_master_link")
: null;
// Only ActivePaginator declinaison
if ($configChild->hasChildren() && $propertyMasterLink instanceof DataObject\ActivePaginator)
{
// For each chapter in master object
foreach ($masterConfig->getChildren() as $masterChapter)
{
if ($masterChapter instanceof ActivePaginatorChapters)
{
$chapterChildPath = $configChild->getFullPath() . "/" . $masterChapter->getKey();
// Chapter already exist
if (DataObject\Service::pathExists($chapterChildPath))
{
$chapterChild = DataObject::getByPath($chapterChildPath);
if ($chapterChild instanceof ActivePaginatorChapters)
{
$chapterChild->setItems($masterChapter->getItems());
$chapterChild->setPublished($masterChapter->isPublished());
$chapterChild->save();
}
}
else // Chapter not exist
{
$doService->copyAsChild($configChild, $masterChapter);
}
}
}
}
}
}
}
}
/**
* Add properties if not exist :
* <ul>
* <li>bricoman_date_pub_obj</li>
* <li>bricoman_date_referent_obj</li>
* </ul>
*
* @param DataObject\ActivePaginator $object
*/
private function addProperties(DataObject\ActivePaginator $object)
{
$propertiesToAdd = [
'bricoman_date_pub_obj' => 'bricoman_date_pub_obj',
'bricoman_date_referent_obj' => 'bricoman_date_referent_obj'
];
$properties = array();
// If properties already exist no need to add them
if ($object->getProperties()) {
// Si l'objet a déjà les propriété crées
$regex_data = "/^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))$/";
$error_msg = "";
/** @var Property $p */
foreach($object->getProperties() as $p) {
if(in_array($p->getName(), $propertiesToAdd))
{
$translator = \Pimcore::getContainer()->get('translator');
if (!preg_match($regex_data, $p->getData()))
{
// Si les valeurs des propriétés ne sont pas sous le format "YYYY-MM-dd", on arrête le script
if ($p->getName() == 'bricoman_date_pub_obj') {
throw new ValidationException($translator->trans('bricoman_date_pub_obj_no_valid_msg'));
} else if ($p->getName() == 'bricoman_date_referent_obj') {
throw new ValidationException($translator->trans('bricoman_date_referent_obj_no_valid_msg'));
}
} else {
$properties[$p->getName()] = $p;
}
}
}
} else {
// Lors du premier save, on vient créer les deux propriétés
foreach($propertiesToAdd as $key => $p) {
$predifinedProperty = Property\Predefined::getByKey($p);
$property = new Property();
$property->setType($predifinedProperty->getType());
$property->setCtype($predifinedProperty->getCtype());
$property->setName($predifinedProperty->getKey());
$property->setInheritable($predifinedProperty->getInheritable());
$property->setData("");
$properties[$p] = $property;
}
}
// Adding properties to the object
$object->setProperties($properties);
}
}