Rajout du dossier core + MAJ .gitignore
This commit is contained in:
108
core/lib/Thelia/Action/Address.php
Normal file
108
core/lib/Thelia/Action/Address.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Address\AddressCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\Address\AddressEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Address as AddressModel;
|
||||
use Thelia\Model\Map\AddressTableMap;
|
||||
|
||||
/**
|
||||
* Class Address
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Address extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(AddressCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$address = new AddressModel();
|
||||
$address->setCustomer($event->getCustomer());
|
||||
$this->createOrUpdate($address, $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function update(AddressCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$addressModel = $event->getAddress();
|
||||
|
||||
$this->createOrUpdate($addressModel, $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function delete(AddressEvent $event)
|
||||
{
|
||||
$address = $event->getAddress();
|
||||
|
||||
$address->delete();
|
||||
}
|
||||
|
||||
public function useDefault(AddressEvent $event)
|
||||
{
|
||||
$address = $event->getAddress();
|
||||
|
||||
$address->makeItDefault();
|
||||
}
|
||||
|
||||
protected function createOrUpdate(AddressModel $addressModel, AddressCreateOrUpdateEvent $event, $dispatcher)
|
||||
{
|
||||
$addressModel->setDispatcher($dispatcher);
|
||||
$con = Propel::getWriteConnection(AddressTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
try {
|
||||
$addressModel
|
||||
->setLabel($event->getLabel())
|
||||
->setTitleId($event->getTitle())
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setAddress1($event->getAddress1())
|
||||
->setAddress2($event->getAddress2())
|
||||
->setAddress3($event->getAddress3())
|
||||
->setZipcode($event->getZipcode())
|
||||
->setCity($event->getCity())
|
||||
->setCountryId($event->getCountry())
|
||||
->setStateId($event->getState())
|
||||
->setCellphone($event->getCellphone())
|
||||
->setPhone($event->getPhone())
|
||||
->setCompany($event->getCompany())
|
||||
->save()
|
||||
;
|
||||
|
||||
if ($event->getIsDefault() && !$addressModel->getIsDefault()) {
|
||||
$addressModel->makeItDefault();
|
||||
}
|
||||
|
||||
$event->setAddress($addressModel);
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::ADDRESS_CREATE => array("create", 128),
|
||||
TheliaEvents::ADDRESS_UPDATE => array("update", 128),
|
||||
TheliaEvents::ADDRESS_DELETE => array("delete", 128),
|
||||
TheliaEvents::ADDRESS_DEFAULT => array('useDefault', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
155
core/lib/Thelia/Action/Administrator.php
Normal file
155
core/lib/Thelia/Action/Administrator.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Administrator\AdministratorEvent;
|
||||
use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Mailer\MailerFactory;
|
||||
use Thelia\Model\Admin as AdminModel;
|
||||
use Thelia\Model\AdminQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Tools\TokenProvider;
|
||||
|
||||
class Administrator extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var MailerFactory */
|
||||
protected $mailer;
|
||||
|
||||
/** @var TokenProvider */
|
||||
protected $tokenProvider;
|
||||
|
||||
public function __construct(MailerFactory $mailer, TokenProvider $tokenProvider)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->tokenProvider = $tokenProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AdministratorEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(AdministratorEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$administrator = new AdminModel();
|
||||
|
||||
$administrator
|
||||
->setDispatcher($dispatcher)
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setEmail($event->getEmail())
|
||||
->setLogin($event->getLogin())
|
||||
->setPassword($event->getPassword())
|
||||
->setProfileId($event->getProfile())
|
||||
->setLocale($event->getLocale())
|
||||
;
|
||||
|
||||
$administrator->save();
|
||||
|
||||
$event->setAdministrator($administrator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AdministratorEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(AdministratorEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $administrator = AdminQuery::create()->findPk($event->getId())) {
|
||||
$administrator
|
||||
->setDispatcher($dispatcher)
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setLogin($event->getLogin())
|
||||
->setEmail($event->getEmail())
|
||||
->setProfileId($event->getProfile())
|
||||
->setLocale($event->getLocale())
|
||||
;
|
||||
|
||||
if ('' !== $event->getPassword()) {
|
||||
$administrator->setPassword($event->getPassword());
|
||||
}
|
||||
|
||||
$administrator->save();
|
||||
|
||||
$event->setAdministrator($administrator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AdministratorEvent $event
|
||||
*/
|
||||
public function delete(AdministratorEvent $event)
|
||||
{
|
||||
if (null !== $administrator = AdminQuery::create()->findPk($event->getId())) {
|
||||
$administrator
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setAdministrator($administrator);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatePassword(AdministratorUpdatePasswordEvent $event)
|
||||
{
|
||||
$admin = $event->getAdmin();
|
||||
|
||||
$admin
|
||||
->setPassword($event->getPassword())
|
||||
->setPasswordRenewToken(null)
|
||||
->save();
|
||||
}
|
||||
|
||||
public function createPassword(AdministratorEvent $event)
|
||||
{
|
||||
$admin = $event->getAdministrator();
|
||||
|
||||
$email = $admin->getEmail();
|
||||
|
||||
if (! empty($email)) {
|
||||
$renewToken = $this->tokenProvider->getToken();
|
||||
|
||||
$admin
|
||||
->setPasswordRenewToken($renewToken)
|
||||
->save();
|
||||
|
||||
$this->mailer->sendEmailMessage(
|
||||
'new_admin_password',
|
||||
[ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ],
|
||||
[ $email => $admin->getFirstname() . ' ' . $admin->getLastname() ],
|
||||
[
|
||||
'token' => $renewToken,
|
||||
'admin' => $admin
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::ADMINISTRATOR_CREATE => array('create', 128),
|
||||
TheliaEvents::ADMINISTRATOR_UPDATE => array('update', 128),
|
||||
TheliaEvents::ADMINISTRATOR_DELETE => array('delete', 128),
|
||||
TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD => array('updatePassword', 128),
|
||||
TheliaEvents::ADMINISTRATOR_CREATEPASSWORD => array('createPassword', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
65
core/lib/Thelia/Action/Api.php
Normal file
65
core/lib/Thelia/Action/Api.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Api\ApiCreateEvent;
|
||||
use Thelia\Core\Event\Api\ApiDeleteEvent;
|
||||
use Thelia\Core\Event\Api\ApiUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Api as ApiModel;
|
||||
|
||||
/**
|
||||
* Class Api
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Api extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function createApi(ApiCreateEvent $event)
|
||||
{
|
||||
$api = new ApiModel();
|
||||
|
||||
$api->setLabel($event->getLabel())
|
||||
->setProfileId($event->getProfile())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
|
||||
public function deleteApi(ApiDeleteEvent $event)
|
||||
{
|
||||
$api = $event->getApi();
|
||||
|
||||
$api->delete();
|
||||
}
|
||||
|
||||
public function updateApi(ApiUpdateEvent $event)
|
||||
{
|
||||
$api = $event->getApi();
|
||||
|
||||
$api->setProfileId($event->getProfile())
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::API_CREATE => ['createApi', 128],
|
||||
TheliaEvents::API_DELETE => ['deleteApi', 128],
|
||||
TheliaEvents::API_UPDATE => ['updateApi', 128],
|
||||
];
|
||||
}
|
||||
}
|
||||
137
core/lib/Thelia/Action/Area.php
Normal file
137
core/lib/Thelia/Action/Area.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Area\AreaAddCountryEvent;
|
||||
use Thelia\Core\Event\Area\AreaCreateEvent;
|
||||
use Thelia\Core\Event\Area\AreaDeleteEvent;
|
||||
use Thelia\Core\Event\Area\AreaRemoveCountryEvent;
|
||||
use Thelia\Core\Event\Area\AreaUpdateEvent;
|
||||
use Thelia\Core\Event\Area\AreaUpdatePostageEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Area as AreaModel;
|
||||
use Thelia\Model\AreaQuery;
|
||||
use Thelia\Model\CountryArea;
|
||||
use Thelia\Model\CountryAreaQuery;
|
||||
|
||||
/**
|
||||
* Class Area
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Area extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function addCountry(AreaAddCountryEvent $event)
|
||||
{
|
||||
$countryIds = $event->getCountryId();
|
||||
|
||||
$areaId = $event->getAreaId();
|
||||
|
||||
foreach ($countryIds as $countryId) {
|
||||
$countryArea = new CountryArea();
|
||||
|
||||
$country = explode('-', $countryId);
|
||||
if (count($country) === 1) {
|
||||
$country[1] = null;
|
||||
}
|
||||
if ($country[1] == 0) {
|
||||
$country[1] = null;
|
||||
}
|
||||
|
||||
$countryArea
|
||||
->setAreaId($areaId)
|
||||
->setCountryId($country[0])
|
||||
->setStateId($country[1])
|
||||
->save()
|
||||
;
|
||||
}
|
||||
|
||||
$event->setArea(AreaQuery::create()->findPk($areaId));
|
||||
}
|
||||
|
||||
public function removeCountry(AreaRemoveCountryEvent $event)
|
||||
{
|
||||
CountryAreaQuery::create()
|
||||
->filterByCountryId($event->getCountryId())
|
||||
->filterByStateId($event->getStateId())
|
||||
->filterByAreaId($event->getAreaId())
|
||||
->delete();
|
||||
|
||||
if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) {
|
||||
$event->setArea($area);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatePostage(AreaUpdatePostageEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) {
|
||||
$area->setDispatcher($dispatcher);
|
||||
$area
|
||||
->setPostage($event->getPostage())
|
||||
->save();
|
||||
|
||||
$event->setArea($area);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(AreaDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) {
|
||||
$area->setDispatcher($dispatcher);
|
||||
$area->delete();
|
||||
|
||||
$event->setArea($area);
|
||||
}
|
||||
}
|
||||
|
||||
public function create(AreaCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$area = new AreaModel();
|
||||
|
||||
$area
|
||||
->setDispatcher($dispatcher)
|
||||
->setName($event->getAreaName())
|
||||
->save();
|
||||
|
||||
$event->setArea($area);
|
||||
}
|
||||
|
||||
public function update(AreaUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) {
|
||||
$area
|
||||
->setDispatcher($dispatcher)
|
||||
->setName($event->getAreaName())
|
||||
->save();
|
||||
|
||||
$event->setArea($area);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::AREA_ADD_COUNTRY => array('addCountry', 128),
|
||||
TheliaEvents::AREA_REMOVE_COUNTRY => array('removeCountry', 128),
|
||||
TheliaEvents::AREA_POSTAGE_UPDATE => array('updatePostage', 128),
|
||||
TheliaEvents::AREA_DELETE => array('delete', 128),
|
||||
TheliaEvents::AREA_CREATE => array('create', 128),
|
||||
TheliaEvents::AREA_UPDATE => array('update', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
157
core/lib/Thelia/Action/Attribute.php
Normal file
157
core/lib/Thelia/Action/Attribute.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\AttributeQuery;
|
||||
use Thelia\Model\Attribute as AttributeModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Attribute\AttributeUpdateEvent;
|
||||
use Thelia\Core\Event\Attribute\AttributeCreateEvent;
|
||||
use Thelia\Core\Event\Attribute\AttributeDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\Attribute\AttributeEvent;
|
||||
use Thelia\Model\AttributeTemplate;
|
||||
use Thelia\Model\AttributeTemplateQuery;
|
||||
use Thelia\Model\TemplateQuery;
|
||||
|
||||
class Attribute extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new attribute entry
|
||||
*
|
||||
* @param AttributeCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(AttributeCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$attribute = new AttributeModel();
|
||||
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setAttribute($attribute);
|
||||
|
||||
// Add atribute to all product templates if required
|
||||
if ($event->getAddToAllTemplates() != 0) {
|
||||
$this->doAddToAllTemplates($attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product attribute
|
||||
*
|
||||
* @param AttributeUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(AttributeUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $attribute = AttributeQuery::create()->findPk($event->getAttributeId())) {
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setAttribute($attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product attribute entry
|
||||
*
|
||||
* @param AttributeDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(AttributeDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($attribute = AttributeQuery::create()->findPk($event->getAttributeId()))) {
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setAttribute($attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(AttributeQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
protected function doAddToAllTemplates(AttributeModel $attribute)
|
||||
{
|
||||
$templates = TemplateQuery::create()->find();
|
||||
|
||||
foreach ($templates as $template) {
|
||||
$attribute_template = new AttributeTemplate();
|
||||
|
||||
if (null === AttributeTemplateQuery::create()->filterByAttribute($attribute)->filterByTemplate($template)->findOne()) {
|
||||
$attribute_template
|
||||
->setAttribute($attribute)
|
||||
->setTemplate($template)
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addToAllTemplates(AttributeEvent $event)
|
||||
{
|
||||
$this->doAddToAllTemplates($event->getAttribute());
|
||||
}
|
||||
|
||||
public function removeFromAllTemplates(AttributeEvent $event)
|
||||
{
|
||||
// Delete this attribute from all product templates
|
||||
AttributeTemplateQuery::create()->filterByAttribute($event->getAttribute())->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::ATTRIBUTE_CREATE => array("create", 128),
|
||||
TheliaEvents::ATTRIBUTE_UPDATE => array("update", 128),
|
||||
TheliaEvents::ATTRIBUTE_DELETE => array("delete", 128),
|
||||
TheliaEvents::ATTRIBUTE_UPDATE_POSITION => array("updatePosition", 128),
|
||||
|
||||
TheliaEvents::ATTRIBUTE_REMOVE_FROM_ALL_TEMPLATES => array("removeFromAllTemplates", 128),
|
||||
TheliaEvents::ATTRIBUTE_ADD_TO_ALL_TEMPLATES => array("addToAllTemplates", 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
119
core/lib/Thelia/Action/AttributeAv.php
Normal file
119
core/lib/Thelia/Action/AttributeAv.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\AttributeAvQuery;
|
||||
use Thelia\Model\AttributeAv as AttributeAvModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Attribute\AttributeAvUpdateEvent;
|
||||
use Thelia\Core\Event\Attribute\AttributeAvCreateEvent;
|
||||
use Thelia\Core\Event\Attribute\AttributeAvDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
|
||||
class AttributeAv extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new attribute entry
|
||||
*
|
||||
* @param AttributeAvCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(AttributeAvCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$attribute = new AttributeAvModel();
|
||||
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setAttributeId($event->getAttributeId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setAttributeAv($attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product attribute
|
||||
*
|
||||
* @param AttributeAvUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(AttributeAvUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $attribute = AttributeAvQuery::create()->findPk($event->getAttributeAvId())) {
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setAttributeAv($attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product attribute entry
|
||||
*
|
||||
* @param AttributeAvDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(AttributeAvDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($attribute = AttributeAvQuery::create()->findPk($event->getAttributeAvId()))) {
|
||||
$attribute
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setAttributeAv($attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(AttributeAvQuery::create(), $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::ATTRIBUTE_AV_CREATE => array("create", 128),
|
||||
TheliaEvents::ATTRIBUTE_AV_UPDATE => array("update", 128),
|
||||
TheliaEvents::ATTRIBUTE_AV_DELETE => array("delete", 128),
|
||||
TheliaEvents::ATTRIBUTE_AV_UPDATE_POSITION => array("updatePosition", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
146
core/lib/Thelia/Action/BaseAction.php
Normal file
146
core/lib/Thelia/Action/BaseAction.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Thelia\Core\Event\ToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Exception\UrlRewritingException;
|
||||
use Thelia\Form\Exception\FormValidationException;
|
||||
use Thelia\Model\ProductCategory;
|
||||
|
||||
class BaseAction
|
||||
{
|
||||
/**
|
||||
* Changes object position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param ModelCriteria $query
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
protected function genericUpdatePosition(ModelCriteria $query, UpdatePositionEvent $event, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if (null !== $object = $query->findPk($event->getObjectId())) {
|
||||
if (!isset(class_uses($object)['Thelia\Model\Tools\PositionManagementTrait'])) {
|
||||
throw new \InvalidArgumentException("Your model does not implement the PositionManagementTrait trait");
|
||||
}
|
||||
|
||||
$object->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher());
|
||||
|
||||
$mode = $event->getMode();
|
||||
|
||||
if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) {
|
||||
$object->changeAbsolutePosition($event->getPosition());
|
||||
} elseif ($mode == UpdatePositionEvent::POSITION_UP) {
|
||||
$object->movePositionUp();
|
||||
} elseif ($mode == UpdatePositionEvent::POSITION_DOWN) {
|
||||
$object->movePositionDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModelCriteria $query
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param EventDispatcherInterface|null $dispatcher
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
protected function genericUpdateDelegatePosition(ModelCriteria $query, UpdatePositionEvent $event, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if (null !== $object = $query->findOne()) {
|
||||
if (!isset(class_uses($object)['Thelia\Model\Tools\PositionManagementTrait'])) {
|
||||
throw new \InvalidArgumentException("Your model does not implement the PositionManagementTrait trait");
|
||||
}
|
||||
|
||||
//$object->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher());
|
||||
|
||||
$mode = $event->getMode();
|
||||
|
||||
if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) {
|
||||
$object->changeAbsolutePosition($event->getPosition());
|
||||
} elseif ($mode == UpdatePositionEvent::POSITION_UP) {
|
||||
$object->movePositionUp();
|
||||
} elseif ($mode == UpdatePositionEvent::POSITION_DOWN) {
|
||||
$object->movePositionDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes SEO Fields for an object.
|
||||
*
|
||||
* @param ModelCriteria $query
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @return mixed an SEOxxx object
|
||||
* @throws FormValidationException if a rewritten URL cannot be created
|
||||
*/
|
||||
protected function genericUpdateSeo(ModelCriteria $query, UpdateSeoEvent $event, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if (null !== $object = $query->findPk($event->getObjectId())) {
|
||||
$object
|
||||
//for backward compatibility
|
||||
->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher())
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setMetaTitle($event->getMetaTitle())
|
||||
->setMetaDescription($event->getMetaDescription())
|
||||
->setMetaKeywords($event->getMetaKeywords())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
// Update the rewritten URL, if required
|
||||
try {
|
||||
$object->setRewrittenUrl($event->getLocale(), $event->getUrl());
|
||||
} catch (UrlRewritingException $e) {
|
||||
throw new FormValidationException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
$event->setObject($object);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle visibility for an object
|
||||
*
|
||||
* @param ModelCriteria $query
|
||||
* @param ToggleVisibilityEvent $event
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function genericToggleVisibility(ModelCriteria $query, ToggleVisibilityEvent $event, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if (null !== $object = $query->findPk($event->getObjectId())) {
|
||||
$newVisibility = !$object->getVisible();
|
||||
$object
|
||||
//for backward compatibility
|
||||
->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher())
|
||||
->setVisible($newVisibility)
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setObject($object);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
276
core/lib/Thelia/Action/BaseCachedFile.php
Normal file
276
core/lib/Thelia/Action/BaseCachedFile.php
Normal file
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Thelia\Core\Event\CachedFileEvent;
|
||||
use Thelia\Core\Event\File\FileCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||
use Thelia\Core\Event\File\FileToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\UpdateFilePositionEvent;
|
||||
use Thelia\Exception\FileException;
|
||||
use Thelia\Files\FileManager;
|
||||
use Thelia\Model\Map\ProductImageTableMap;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
/**
|
||||
*
|
||||
* Cached file management actions. This class handles file caching in the web space
|
||||
*
|
||||
* Basically, files are stored outside the web space (by default in local/media/<dirname>),
|
||||
* and cached in the web space (by default in web/local/<dirname>).
|
||||
*
|
||||
* In the file cache directory, a subdirectory for files categories (eg. product, category, folder, etc.) is
|
||||
* automatically created, and the cached file is created here. Plugin may use their own subdirectory as required.
|
||||
*
|
||||
* A copy (or symbolic link, by default) of the original file is created in the cache.
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
abstract class BaseCachedFile extends BaseAction
|
||||
{
|
||||
/**
|
||||
* @var FileManager
|
||||
*/
|
||||
protected $fileManager;
|
||||
|
||||
public function __construct(FileManager $fileManager)
|
||||
{
|
||||
$this->fileManager = $fileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string root of the file cache directory in web space
|
||||
*/
|
||||
abstract protected function getCacheDirFromWebRoot();
|
||||
|
||||
/**
|
||||
* Clear the file cache. Is a subdirectory is specified, only this directory is cleared.
|
||||
* If no directory is specified, the whole cache is cleared.
|
||||
* Only files are deleted, directories will remain.
|
||||
*
|
||||
* @param CachedFileEvent $event
|
||||
*/
|
||||
public function clearCache(CachedFileEvent $event)
|
||||
{
|
||||
$path = $this->getCachePath($event->getCacheSubdirectory(), false);
|
||||
|
||||
$this->clearDirectory($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively clears the specified directory.
|
||||
*
|
||||
* @param string $path the directory path
|
||||
*/
|
||||
protected function clearDirectory($path)
|
||||
{
|
||||
$iterator = new \DirectoryIterator($path);
|
||||
|
||||
/** @var \DirectoryIterator $fileinfo */
|
||||
foreach ($iterator as $fileinfo) {
|
||||
if ($fileinfo->isDot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fileinfo->isFile() || $fileinfo->isLink()) {
|
||||
@unlink($fileinfo->getPathname());
|
||||
} elseif ($fileinfo->isDir()) {
|
||||
$this->clearDirectory($fileinfo->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute URL to the cached file
|
||||
*
|
||||
* @param string $subdir the subdirectory related to cache base
|
||||
* @param string $safe_filename the safe filename, as returned by getCacheFilePath()
|
||||
* @return string the absolute URL to the cached file
|
||||
*/
|
||||
protected function getCacheFileURL($subdir, $safe_filename)
|
||||
{
|
||||
$path = $this->getCachePathFromWebRoot($subdir);
|
||||
|
||||
return URL::getInstance()->absoluteUrl(sprintf("%s/%s", $path, $safe_filename), null, URL::PATH_TO_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full path of the cached file
|
||||
*
|
||||
* @param string $subdir the subdirectory related to cache base
|
||||
* @param string $filename the filename
|
||||
* @param boolean $forceOriginalFile if true, the original file path in the cache dir is returned.
|
||||
* @param string $hashed_options a hash of transformation options, or null if no transformations have been applied
|
||||
* @return string the cache directory path relative to Web Root
|
||||
*/
|
||||
protected function getCacheFilePath($subdir, $filename, $forceOriginalFile = false, $hashed_options = null)
|
||||
{
|
||||
$path = $this->getCachePath($subdir);
|
||||
|
||||
$safe_filename = preg_replace("[^:alnum:\-\._]", "-", strtolower(basename($filename)));
|
||||
|
||||
// Keep original safe name if no tranformations are applied
|
||||
if ($forceOriginalFile || $hashed_options == null) {
|
||||
return sprintf("%s/%s", $path, $safe_filename);
|
||||
} else {
|
||||
return sprintf("%s/%s-%s", $path, $hashed_options, $safe_filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache directory path relative to Web Root
|
||||
*
|
||||
* @param string $subdir the subdirectory related to cache base, or null to get the cache directory only.
|
||||
* @return string the cache directory path relative to Web Root
|
||||
*/
|
||||
protected function getCachePathFromWebRoot($subdir = null)
|
||||
{
|
||||
$cache_dir_from_web_root = $this->getCacheDirFromWebRoot();
|
||||
|
||||
if ($subdir != null) {
|
||||
$safe_subdir = basename($subdir);
|
||||
|
||||
$path = sprintf("%s/%s", $cache_dir_from_web_root, $safe_subdir);
|
||||
} else {
|
||||
$path = $cache_dir_from_web_root;
|
||||
}
|
||||
|
||||
// Check if path is valid, e.g. in the cache dir
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute cache directory path
|
||||
*
|
||||
* @param string $subdir the subdirectory related to cache base, or null to get the cache base directory.
|
||||
* @param bool $create_if_not_exists create the directory if it is not found
|
||||
*
|
||||
* @throws \RuntimeException if cache directory cannot be created
|
||||
* @throws \InvalidArgumentException ii path is invalid, e.g. not in the cache dir
|
||||
*
|
||||
* @return string the absolute cache directory path
|
||||
*/
|
||||
protected function getCachePath($subdir = null, $create_if_not_exists = true)
|
||||
{
|
||||
$cache_base = $this->getCachePathFromWebRoot($subdir);
|
||||
|
||||
$web_root = rtrim(THELIA_WEB_DIR, '/');
|
||||
|
||||
$path = sprintf("%s/%s", $web_root, $cache_base);
|
||||
|
||||
// Create directory (recursively) if it does not exists.
|
||||
if ($create_if_not_exists && !is_dir($path)) {
|
||||
if (!@mkdir($path, 0777, true)) {
|
||||
throw new \RuntimeException(sprintf("Failed to create %s file in cache directory", $path));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if path is valid, e.g. in the cache dir
|
||||
$cache_base = realpath(sprintf("%s/%s", $web_root, $this->getCachePathFromWebRoot()));
|
||||
|
||||
if (strpos(realpath($path), $cache_base) !== 0) {
|
||||
throw new \InvalidArgumentException(sprintf("Invalid cache path %s, with subdirectory %s", $path, $subdir));
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care of saving a file in the database and file storage
|
||||
*
|
||||
* @param FileCreateOrUpdateEvent $event Image event
|
||||
*
|
||||
* @throws \Thelia\Exception\FileException|\Exception
|
||||
*
|
||||
*/
|
||||
public function saveFile(FileCreateOrUpdateEvent $event)
|
||||
{
|
||||
$model = $event->getModel();
|
||||
$model->setFile(sprintf("tmp/%s", $event->getUploadedFile()->getFilename()));
|
||||
$con = Propel::getWriteConnection(ProductImageTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$nbModifiedLines = $model->save($con);
|
||||
$event->setModel($model);
|
||||
|
||||
if (!$nbModifiedLines) {
|
||||
throw new FileException(
|
||||
sprintf(
|
||||
'File "%s" (type %s) with parent id %s failed to be saved',
|
||||
$event->getParentName(),
|
||||
get_class($model),
|
||||
$event->getParentId()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$newUploadedFile = $this->fileManager->copyUploadedFile($event->getModel(), $event->getUploadedFile());
|
||||
|
||||
$event->setUploadedFile($newUploadedFile);
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care of updating file in the database and file storage
|
||||
*
|
||||
* @param FileCreateOrUpdateEvent $event Image event
|
||||
*
|
||||
* @throws \Thelia\Exception\FileException
|
||||
*/
|
||||
public function updateFile(FileCreateOrUpdateEvent $event)
|
||||
{
|
||||
// Copy and save file
|
||||
if ($event->getUploadedFile()) {
|
||||
// Remove old picture file from file storage
|
||||
$url = $event->getModel()->getUploadDir() . '/' . $event->getOldModel()->getFile();
|
||||
unlink(str_replace('..', '', $url));
|
||||
|
||||
$newUploadedFile = $this->fileManager->copyUploadedFile($event->getModel(), $event->getUploadedFile());
|
||||
$event->setUploadedFile($newUploadedFile);
|
||||
}
|
||||
|
||||
// Update image modifications
|
||||
$event->getModel()->save();
|
||||
|
||||
$event->setModel($event->getModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleting file in the database and in storage
|
||||
*
|
||||
* @param FileDeleteEvent $event Image event
|
||||
*/
|
||||
public function deleteFile(FileDeleteEvent $event)
|
||||
{
|
||||
$this->fileManager->deleteFile($event->getFileToDelete());
|
||||
}
|
||||
|
||||
public function updatePosition(UpdateFilePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition($event->getQuery(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function toggleVisibility(FileToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericToggleVisibility($event->getQuery(), $event, $dispatcher);
|
||||
}
|
||||
}
|
||||
140
core/lib/Thelia/Action/Brand.php
Normal file
140
core/lib/Thelia/Action/Brand.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Brand\BrandCreateEvent;
|
||||
use Thelia\Core\Event\Brand\BrandDeleteEvent;
|
||||
use Thelia\Core\Event\Brand\BrandToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Brand\BrandUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Model\Brand as BrandModel;
|
||||
use Thelia\Model\BrandQuery;
|
||||
|
||||
/**
|
||||
* Class Brand
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class Brand extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(BrandCreateEvent $event)
|
||||
{
|
||||
$brand = new BrandModel();
|
||||
|
||||
$brand
|
||||
->setVisible($event->getVisible())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setBrand($brand);
|
||||
}
|
||||
|
||||
/**
|
||||
* process update brand
|
||||
*
|
||||
* @param BrandUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(BrandUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $brand = BrandQuery::create()->findPk($event->getBrandId())) {
|
||||
$brand->setDispatcher($dispatcher);
|
||||
|
||||
$brand
|
||||
->setVisible($event->getVisible())
|
||||
->setLogoImageId(intval($event->getLogoImageId()) == 0 ? null : $event->getLogoImageId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setBrand($brand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Brand visibility
|
||||
*
|
||||
* @param BrandToggleVisibilityEvent $event
|
||||
* @param string $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function toggleVisibility(BrandToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$brand = $event->getBrand();
|
||||
|
||||
$brand
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible(!$brand->getVisible())
|
||||
->save();
|
||||
|
||||
$event->setBrand($brand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Brand SEO
|
||||
*
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdateSeo(BrandQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function delete(BrandDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $brand = BrandQuery::create()->findPk($event->getBrandId())) {
|
||||
$brand->setDispatcher($dispatcher)->delete();
|
||||
|
||||
$event->setBrand($brand);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(BrandQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::BRAND_CREATE => array('create', 128),
|
||||
TheliaEvents::BRAND_UPDATE => array('update', 128),
|
||||
TheliaEvents::BRAND_DELETE => array('delete', 128),
|
||||
|
||||
TheliaEvents::BRAND_UPDATE_SEO => array('updateSeo', 128),
|
||||
|
||||
TheliaEvents::BRAND_UPDATE_POSITION => array('updatePosition', 128),
|
||||
TheliaEvents::BRAND_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
44
core/lib/Thelia/Action/Cache.php
Normal file
44
core/lib/Thelia/Action/Cache.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
/**
|
||||
* Class Cache
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Cache extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function cacheClear(CacheEvent $event)
|
||||
{
|
||||
$dir = $event->getDir();
|
||||
|
||||
$fs = new Filesystem();
|
||||
$fs->remove($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CACHE_CLEAR => array('cacheClear', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
538
core/lib/Thelia/Action/Cart.php
Normal file
538
core/lib/Thelia/Action/Cart.php
Normal file
@@ -0,0 +1,538 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Thelia\Core\Event\Cart\CartCreateEvent;
|
||||
use Thelia\Core\Event\Cart\CartDuplicationEvent;
|
||||
use Thelia\Core\Event\Cart\CartPersistEvent;
|
||||
use Thelia\Core\Event\Cart\CartRestoreEvent;
|
||||
use Thelia\Core\Event\Cart\CartEvent;
|
||||
use Thelia\Core\Event\Currency\CurrencyChangeEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Base\CustomerQuery;
|
||||
use Thelia\Model\Base\ProductSaleElementsQuery;
|
||||
use Thelia\Model\Currency as CurrencyModel;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\Cart as CartModel;
|
||||
use Thelia\Model\CartItemQuery;
|
||||
use Thelia\Model\CartQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Customer as CustomerModel;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
use Thelia\Model\Tools\ProductPriceTools;
|
||||
use Thelia\Tools\TokenProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class Cart where all actions are manage like adding, modifying or delete items.
|
||||
*
|
||||
* Class Cart
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Cart extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var RequestStack */
|
||||
protected $requestStack;
|
||||
|
||||
/** @var TokenProvider */
|
||||
protected $tokenProvider;
|
||||
|
||||
public function __construct(RequestStack $requestStack, TokenProvider $tokenProvider)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
|
||||
$this->tokenProvider = $tokenProvider;
|
||||
}
|
||||
|
||||
public function persistCart(CartPersistEvent $event)
|
||||
{
|
||||
$cart = $event->getCart();
|
||||
|
||||
if ($cart->isNew()) {
|
||||
$cart
|
||||
->setToken($this->generateCartCookieIdentifier())
|
||||
->save();
|
||||
$this->getSession()->setSessionCart($cart);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add an article in the current cart
|
||||
*
|
||||
* @param \Thelia\Core\Event\Cart\CartEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function addItem(CartEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cart = $event->getCart();
|
||||
$newness = $event->getNewness();
|
||||
$append = $event->getAppend();
|
||||
$quantity = $event->getQuantity();
|
||||
$currency = $cart->getCurrency();
|
||||
$customer = $cart->getCustomer();
|
||||
$discount = 0;
|
||||
|
||||
if ($cart->isNew()) {
|
||||
$persistEvent = new CartPersistEvent($cart);
|
||||
$dispatcher->dispatch(TheliaEvents::CART_PERSIST, $persistEvent);
|
||||
}
|
||||
|
||||
if (null !== $customer && $customer->getDiscount() > 0) {
|
||||
$discount = $customer->getDiscount();
|
||||
}
|
||||
|
||||
$productSaleElementsId = $event->getProductSaleElementsId();
|
||||
$productId = $event->getProduct();
|
||||
|
||||
// Search for an identical item in the cart
|
||||
$dispatcher->dispatch(TheliaEvents::CART_FINDITEM, $event);
|
||||
|
||||
$cartItem = $event->getCartItem();
|
||||
|
||||
if ($cartItem === null || $newness) {
|
||||
$productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId);
|
||||
|
||||
if (null !== $productSaleElements) {
|
||||
$productPrices = $productSaleElements->getPricesByCurrency($currency, $discount);
|
||||
|
||||
$cartItem = $this->doAddItem($dispatcher, $cart, $productId, $productSaleElements, $quantity, $productPrices);
|
||||
}
|
||||
} elseif ($append && $cartItem !== null) {
|
||||
$cartItem->addQuantity($quantity)->save();
|
||||
}
|
||||
|
||||
$event->setCartItem($cartItem);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Delete specify article present into cart
|
||||
*
|
||||
* @param \Thelia\Core\Event\Cart\CartEvent $event
|
||||
*/
|
||||
public function deleteItem(CartEvent $event)
|
||||
{
|
||||
if (null !== $cartItemId = $event->getCartItemId()) {
|
||||
$cart = $event->getCart();
|
||||
CartItemQuery::create()
|
||||
->filterByCartId($cart->getId())
|
||||
->filterById($cartItemId)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cart
|
||||
* @param CartEvent $event
|
||||
*/
|
||||
public function clear(CartEvent $event)
|
||||
{
|
||||
if (null !== $cart = $event->getCart()) {
|
||||
$cart->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Modify article's quantity
|
||||
*
|
||||
* don't use Form here just test the Request.
|
||||
*
|
||||
* @param \Thelia\Core\Event\Cart\CartEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function changeItem(CartEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if ((null !== $cartItemId = $event->getCartItemId()) && (null !== $quantity = $event->getQuantity())) {
|
||||
$cart = $event->getCart();
|
||||
|
||||
$cartItem = CartItemQuery::create()
|
||||
->filterByCartId($cart->getId())
|
||||
->filterById($cartItemId)
|
||||
->findOne();
|
||||
|
||||
if ($cartItem) {
|
||||
$event->setCartItem(
|
||||
$this->updateQuantity($dispatcher, $cartItem, $quantity)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updateCart(CurrencyChangeEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cart = $event->getRequest()->getSession()->getSessionCart($dispatcher);
|
||||
|
||||
if (null !== $cart) {
|
||||
$this->updateCartPrices($cart, $event->getCurrency());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Refresh article's price
|
||||
*
|
||||
* @param \Thelia\Model\Cart $cart
|
||||
* @param \Thelia\Model\Currency $currency
|
||||
*/
|
||||
public function updateCartPrices(CartModel $cart, CurrencyModel $currency)
|
||||
{
|
||||
$customer = $cart->getCustomer();
|
||||
$discount = 0;
|
||||
|
||||
if (null !== $customer && $customer->getDiscount() > 0) {
|
||||
$discount = $customer->getDiscount();
|
||||
}
|
||||
|
||||
// cart item
|
||||
foreach ($cart->getCartItems() as $cartItem) {
|
||||
$productSaleElements = $cartItem->getProductSaleElements();
|
||||
|
||||
$productPrice = $productSaleElements->getPricesByCurrency($currency, $discount);
|
||||
|
||||
$cartItem
|
||||
->setPrice($productPrice->getPrice())
|
||||
->setPromoPrice($productPrice->getPromoPrice());
|
||||
|
||||
$cartItem->save();
|
||||
}
|
||||
|
||||
// update the currency cart
|
||||
$cart->setCurrencyId($currency->getId());
|
||||
$cart->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* increase the quantity for an existing cartItem
|
||||
*
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param CartItem $cartItem
|
||||
* @param float $quantity
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
* @return CartItem
|
||||
*/
|
||||
protected function updateQuantity(EventDispatcherInterface $dispatcher, CartItem $cartItem, $quantity)
|
||||
{
|
||||
$cartItem->setDisptacher($dispatcher);
|
||||
$cartItem->updateQuantity($quantity)
|
||||
->save();
|
||||
|
||||
return $cartItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* try to attach a new item to an existing cart
|
||||
*
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param \Thelia\Model\Cart $cart
|
||||
* @param int $productId
|
||||
* @param ProductSaleElements $productSaleElements
|
||||
* @param float $quantity
|
||||
* @param ProductPriceTools $productPrices
|
||||
*
|
||||
* @return CartItem
|
||||
*/
|
||||
protected function doAddItem(
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CartModel $cart,
|
||||
$productId,
|
||||
ProductSaleElements $productSaleElements,
|
||||
$quantity,
|
||||
ProductPriceTools $productPrices
|
||||
) {
|
||||
$cartItem = new CartItem();
|
||||
$cartItem->setDisptacher($dispatcher);
|
||||
$cartItem
|
||||
->setCart($cart)
|
||||
->setProductId($productId)
|
||||
->setProductSaleElementsId($productSaleElements->getId())
|
||||
->setQuantity($quantity)
|
||||
->setPrice($productPrices->getPrice())
|
||||
->setPromoPrice($productPrices->getPromoPrice())
|
||||
->setPromo($productSaleElements->getPromo())
|
||||
->setPriceEndOfLife(time() + ConfigQuery::read("cart.priceEOF", 60*60*24*30))
|
||||
->save();
|
||||
|
||||
return $cartItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* find a specific record in CartItem table using the Cart id, the product id
|
||||
* and the product_sale_elements id
|
||||
*
|
||||
* @param int $cartId
|
||||
* @param int $productId
|
||||
* @param int $productSaleElementsId
|
||||
* @return CartItem
|
||||
*
|
||||
* @deprecated this method is deprecated. Dispatch a TheliaEvents::CART_FINDITEM instead
|
||||
*/
|
||||
protected function findItem($cartId, $productId, $productSaleElementsId)
|
||||
{
|
||||
return CartItemQuery::create()
|
||||
->filterByCartId($cartId)
|
||||
->filterByProductId($productId)
|
||||
->filterByProductSaleElementsId($productSaleElementsId)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a specific record in CartItem table using the current CartEvent
|
||||
*
|
||||
* @param CartEvent $event the cart event
|
||||
*/
|
||||
public function findCartItem(CartEvent $event)
|
||||
{
|
||||
if (null !== $foundItem = CartItemQuery::create()
|
||||
->filterByCartId($event->getCart()->getId())
|
||||
->filterByProductId($event->getProduct())
|
||||
->filterByProductSaleElementsId($event->getProductSaleElementsId())
|
||||
->findOne()) {
|
||||
$event->setCartItem($foundItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search if cart already exists in session. If not try to restore it from the cart cookie,
|
||||
* or duplicate an old one.
|
||||
*
|
||||
* @param CartRestoreEvent $cartRestoreEvent
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function restoreCurrentCart(CartRestoreEvent $cartRestoreEvent, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart');
|
||||
$persistentCookie = ConfigQuery::read("cart.use_persistent_cookie", 1);
|
||||
|
||||
$cart = null;
|
||||
|
||||
if ($this->requestStack->getCurrentRequest()->cookies->has($cookieName) && $persistentCookie) {
|
||||
$cart = $this->managePersistentCart($cartRestoreEvent, $cookieName, $dispatcher);
|
||||
} elseif (!$persistentCookie) {
|
||||
$cart = $this->manageNonPersistentCookie($cartRestoreEvent, $dispatcher);
|
||||
}
|
||||
|
||||
// Still no cart ? Create a new one.
|
||||
if (null === $cart) {
|
||||
$cart = $this->dispatchNewCart($dispatcher);
|
||||
}
|
||||
|
||||
$cartRestoreEvent->setCart($cart);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cart token is not saved in a cookie, if the cart is present in session, we just change the customer id
|
||||
* if needed or create duplicate the current cart if the customer is not the same as customer already present in
|
||||
* the cart.
|
||||
*
|
||||
* @param CartRestoreEvent $cartRestoreEvent
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return CartModel
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function manageNonPersistentCookie(CartRestoreEvent $cartRestoreEvent, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cart = $cartRestoreEvent->getCart();
|
||||
|
||||
if (null === $cart) {
|
||||
$cart = $this->dispatchNewCart($dispatcher);
|
||||
} else {
|
||||
$cart = $this->manageCartDuplicationAtCustomerLogin($cart, $dispatcher);
|
||||
}
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The cart token is saved in a cookie so we try to retrieve it. Then the customer is checked.
|
||||
*
|
||||
* @param CartRestoreEvent $cartRestoreEvent
|
||||
* @param $cookieName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return CartModel
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function managePersistentCart(CartRestoreEvent $cartRestoreEvent, $cookieName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
// The cart cookie exists -> get the cart token
|
||||
$token = $this->requestStack->getCurrentRequest()->cookies->get($cookieName);
|
||||
|
||||
// Check if a cart exists for this token
|
||||
if (null !== $cart = CartQuery::create()->findOneByToken($token)) {
|
||||
$cart = $this->manageCartDuplicationAtCustomerLogin($cart, $dispatcher);
|
||||
}
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
protected function manageCartDuplicationAtCustomerLogin(CartModel $cart, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
/** @var CustomerModel $customer */
|
||||
if (null !== $customer = $this->getSession()->getCustomerUser()) {
|
||||
// Check if we have to duplicate the existing cart.
|
||||
|
||||
$duplicateCart = true;
|
||||
|
||||
// A customer is logged in.
|
||||
if (null === $cart->getCustomerId()) {
|
||||
// If the customer has a discount, whe have to duplicate the cart,
|
||||
// so that the discount will be applied to the products in cart.
|
||||
|
||||
if (0 === $customer->getDiscount() || 0 === $cart->countCartItems()) {
|
||||
// If no discount, or an empty cart, there's no need to duplicate.
|
||||
$duplicateCart = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($duplicateCart) {
|
||||
// Duplicate the cart
|
||||
$cart = $this->duplicateCart($dispatcher, $cart, $customer);
|
||||
} else {
|
||||
// No duplication required, just assign the cart to the customer
|
||||
$cart->setCustomerId($customer->getId())->save();
|
||||
}
|
||||
} elseif ($cart->getCustomerId() != null) {
|
||||
// The cart belongs to another user
|
||||
if (0 === $cart->countCartItems()) {
|
||||
// No items in cart, assign it to nobody.
|
||||
$cart->setCustomerId(null)->save();
|
||||
} else {
|
||||
// Some itemls in cart, duplicate it without assigning a customer ID.
|
||||
$cart = $this->duplicateCart($dispatcher, $cart);
|
||||
}
|
||||
}
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return CartModel
|
||||
*/
|
||||
protected function dispatchNewCart(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cartCreateEvent = new CartCreateEvent();
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CART_CREATE_NEW, $cartCreateEvent);
|
||||
|
||||
return $cartCreateEvent->getCart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new, empty cart object, and assign it to the current customer, if any.
|
||||
*
|
||||
* @param CartCreateEvent $cartCreateEvent
|
||||
*/
|
||||
public function createEmptyCart(CartCreateEvent $cartCreateEvent)
|
||||
{
|
||||
$cart = new CartModel();
|
||||
|
||||
$cart->setCurrency($this->getSession()->getCurrency(true));
|
||||
|
||||
/** @var CustomerModel $customer */
|
||||
if (null !== $customer = $this->getSession()->getCustomerUser()) {
|
||||
$cart->setCustomer(CustomerQuery::create()->findPk($customer->getId()));
|
||||
}
|
||||
|
||||
$this->getSession()->setSessionCart($cart);
|
||||
|
||||
if (ConfigQuery::read("cart.use_persistent_cookie", 1) == 1) {
|
||||
// set cart_use_cookie to "" to remove the cart cookie
|
||||
// see Thelia\Core\EventListener\ResponseListener
|
||||
$this->getSession()->set("cart_use_cookie", "");
|
||||
}
|
||||
|
||||
$cartCreateEvent->setCart($cart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate an existing Cart. If a customer ID is provided the created cart will be attached to this customer.
|
||||
*
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param CartModel $cart
|
||||
* @param CustomerModel $customer
|
||||
* @return CartModel
|
||||
*/
|
||||
protected function duplicateCart(EventDispatcherInterface $dispatcher, CartModel $cart, CustomerModel $customer = null)
|
||||
{
|
||||
$newCart = $cart->duplicate(
|
||||
$this->generateCartCookieIdentifier(),
|
||||
$customer,
|
||||
$this->getSession()->getCurrency(),
|
||||
$dispatcher
|
||||
);
|
||||
|
||||
$cartEvent = new CartDuplicationEvent($newCart, $cart);
|
||||
$dispatcher->dispatch(TheliaEvents::CART_DUPLICATE, $cartEvent);
|
||||
|
||||
return $cartEvent->getDuplicatedCart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the cart cookie identifier, or return null if the cart is only managed in the session object,
|
||||
* not in a client cookie.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateCartCookieIdentifier()
|
||||
{
|
||||
$id = null;
|
||||
|
||||
if (ConfigQuery::read("cart.use_persistent_cookie", 1) == 1) {
|
||||
$id = $this->tokenProvider->getToken();
|
||||
$this->getSession()->set('cart_use_cookie', $id);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CART_PERSIST => array("persistCart", 128),
|
||||
TheliaEvents::CART_RESTORE_CURRENT => array("restoreCurrentCart", 128),
|
||||
TheliaEvents::CART_CREATE_NEW => array("createEmptyCart", 128),
|
||||
TheliaEvents::CART_ADDITEM => array("addItem", 128),
|
||||
TheliaEvents::CART_FINDITEM => array("findCartItem", 128),
|
||||
TheliaEvents::CART_DELETEITEM => array("deleteItem", 128),
|
||||
TheliaEvents::CART_UPDATEITEM => array("changeItem", 128),
|
||||
TheliaEvents::CART_CLEAR => array("clear", 128),
|
||||
TheliaEvents::CHANGE_DEFAULT_CURRENCY => array("updateCart", 128),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session from the current request
|
||||
*
|
||||
* @return \Thelia\Core\HttpFoundation\Session\Session
|
||||
*/
|
||||
protected function getSession()
|
||||
{
|
||||
return $this->requestStack->getCurrentRequest()->getSession();
|
||||
}
|
||||
}
|
||||
234
core/lib/Thelia/Action/Category.php
Normal file
234
core/lib/Thelia/Action/Category.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Model\CategoryDocumentQuery;
|
||||
use Thelia\Model\CategoryImageQuery;
|
||||
use Thelia\Model\CategoryQuery;
|
||||
use Thelia\Model\Category as CategoryModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Category\CategoryUpdateEvent;
|
||||
use Thelia\Core\Event\Category\CategoryCreateEvent;
|
||||
use Thelia\Core\Event\Category\CategoryDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\Category\CategoryToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Category\CategoryAddContentEvent;
|
||||
use Thelia\Core\Event\Category\CategoryDeleteContentEvent;
|
||||
use Thelia\Model\CategoryAssociatedContent;
|
||||
use Thelia\Model\CategoryAssociatedContentQuery;
|
||||
use Thelia\Model\Map\CategoryTableMap;
|
||||
|
||||
class Category extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new category entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Category\CategoryCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(CategoryCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$category = new CategoryModel();
|
||||
|
||||
$category
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
->setTitle($event->getTitle())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setCategory($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a category
|
||||
*
|
||||
* @param \Thelia\Core\Event\Category\CategoryUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(CategoryUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $category = CategoryQuery::create()->findPk($event->getCategoryId())) {
|
||||
$category
|
||||
->setDispatcher($dispatcher)
|
||||
->setDefaultTemplateId($event->getDefaultTemplateId() == 0 ? null : $event->getDefaultTemplateId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setCategory($category);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a Category SEO
|
||||
*
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdateSeo(CategoryQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a category entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Category\CategoryDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(CategoryDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $category = CategoryQuery::create()->findPk($event->getCategoryId())) {
|
||||
$con = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$fileList = ['images' => [], 'documentList' => []];
|
||||
|
||||
// Get category's files to delete after category deletion
|
||||
$fileList['images']['list'] = CategoryImageQuery::create()
|
||||
->findByCategoryId($event->getCategoryId());
|
||||
$fileList['images']['type'] = TheliaEvents::IMAGE_DELETE;
|
||||
|
||||
$fileList['documentList']['list'] = CategoryDocumentQuery::create()
|
||||
->findByCategoryId($event->getCategoryId());
|
||||
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
||||
|
||||
// Delete category
|
||||
$category
|
||||
->setDispatcher($dispatcher)
|
||||
->delete($con);
|
||||
|
||||
$event->setCategory($category);
|
||||
|
||||
// Dispatch delete category's files event
|
||||
foreach ($fileList as $fileTypeList) {
|
||||
foreach ($fileTypeList['list'] as $fileToDelete) {
|
||||
$fileDeleteEvent = new FileDeleteEvent($fileToDelete);
|
||||
$dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle category visibility. No form used here
|
||||
*
|
||||
* @param CategoryToggleVisibilityEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function toggleVisibility(CategoryToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$category = $event->getCategory();
|
||||
|
||||
$category
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible($category->getVisible() ? false : true)
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setCategory($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(CategoryQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function addContent(CategoryAddContentEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (CategoryAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByCategory($event->getCategory())->count() <= 0) {
|
||||
$content = new CategoryAssociatedContent();
|
||||
|
||||
$content
|
||||
->setDispatcher($dispatcher)
|
||||
->setCategory($event->getCategory())
|
||||
->setContentId($event->getContentId())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeContent(CategoryDeleteContentEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$content = CategoryAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByCategory($event->getCategory())->findOne()
|
||||
;
|
||||
|
||||
if ($content !== null) {
|
||||
$content
|
||||
->setDispatcher($dispatcher)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CATEGORY_CREATE => array("create", 128),
|
||||
TheliaEvents::CATEGORY_UPDATE => array("update", 128),
|
||||
TheliaEvents::CATEGORY_DELETE => array("delete", 128),
|
||||
TheliaEvents::CATEGORY_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
|
||||
TheliaEvents::CATEGORY_UPDATE_POSITION => array("updatePosition", 128),
|
||||
TheliaEvents::CATEGORY_UPDATE_SEO => array("updateSeo", 128),
|
||||
|
||||
TheliaEvents::CATEGORY_ADD_CONTENT => array("addContent", 128),
|
||||
TheliaEvents::CATEGORY_REMOVE_CONTENT => array("removeContent", 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
128
core/lib/Thelia/Action/Config.php
Normal file
128
core/lib/Thelia/Action/Config.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Config\ConfigCreateEvent;
|
||||
use Thelia\Core\Event\Config\ConfigDeleteEvent;
|
||||
use Thelia\Core\Event\Config\ConfigUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Config as ConfigModel;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
class Config extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new configuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Config\ConfigCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(ConfigCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$config = new ConfigModel();
|
||||
|
||||
$config->setDispatcher($dispatcher)
|
||||
->setName($event->getEventName())
|
||||
->setValue($event->getValue())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setHidden($event->getHidden())
|
||||
->setSecured($event->getSecured())
|
||||
->save();
|
||||
|
||||
$event->setConfig($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a configuration entry value
|
||||
*
|
||||
* @param \Thelia\Core\Event\Config\ConfigUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function setValue(ConfigUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $config = ConfigQuery::create()->findPk($event->getConfigId())) {
|
||||
if ($event->getValue() !== $config->getValue()) {
|
||||
$config->setDispatcher($dispatcher)->setValue($event->getValue())->save();
|
||||
|
||||
$event->setConfig($config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a configuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Config\ConfigUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function modify(ConfigUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $config = ConfigQuery::create()->findPk($event->getConfigId())) {
|
||||
$config->setDispatcher($dispatcher)
|
||||
->setName($event->getEventName())
|
||||
->setValue($event->getValue())
|
||||
->setHidden($event->getHidden())
|
||||
->setSecured($event->getSecured())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->save();
|
||||
|
||||
$event->setConfig($config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a configuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Config\ConfigDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(ConfigDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($config = ConfigQuery::create()->findPk($event->getConfigId()))) {
|
||||
if (!$config->getSecured()) {
|
||||
$config->setDispatcher($dispatcher)->delete();
|
||||
|
||||
$event->setConfig($config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CONFIG_CREATE => array(
|
||||
"create", 128
|
||||
), TheliaEvents::CONFIG_SETVALUE => array(
|
||||
"setValue", 128
|
||||
), TheliaEvents::CONFIG_UPDATE => array(
|
||||
"modify", 128
|
||||
), TheliaEvents::CONFIG_DELETE => array(
|
||||
"delete", 128
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
228
core/lib/Thelia/Action/Content.php
Normal file
228
core/lib/Thelia/Action/Content.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Content\ContentAddFolderEvent;
|
||||
use Thelia\Core\Event\Content\ContentCreateEvent;
|
||||
use Thelia\Core\Event\Content\ContentDeleteEvent;
|
||||
use Thelia\Core\Event\Content\ContentRemoveFolderEvent;
|
||||
use Thelia\Core\Event\Content\ContentToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Content\ContentUpdateEvent;
|
||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Model\ContentDocumentQuery;
|
||||
use Thelia\Model\ContentFolder;
|
||||
use Thelia\Model\ContentFolderQuery;
|
||||
use Thelia\Model\ContentImageQuery;
|
||||
use Thelia\Model\ContentQuery;
|
||||
use Thelia\Model\Content as ContentModel;
|
||||
use Thelia\Model\Map\ContentTableMap;
|
||||
|
||||
/**
|
||||
* Class Content
|
||||
* @package Thelia\Action
|
||||
* @author manuel raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Content extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(ContentCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$content = (new ContentModel)
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible($event->getVisible())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->create($event->getDefaultFolder())
|
||||
;
|
||||
|
||||
$event->setContent($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* process update content
|
||||
*
|
||||
* @param ContentUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws PropelException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update(ContentUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $content = ContentQuery::create()->findPk($event->getContentId())) {
|
||||
$con = Propel::getWriteConnection(ContentTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
$content->setDispatcher($dispatcher);
|
||||
try {
|
||||
$content
|
||||
->setVisible($event->getVisible())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->save($con)
|
||||
;
|
||||
|
||||
$content->setDefaultFolder($event->getDefaultFolder());
|
||||
|
||||
$event->setContent($content);
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Content SEO
|
||||
*
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdateSeo(ContentQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdateDelegatePosition(
|
||||
ContentFolderQuery::create()
|
||||
->filterByContentId($event->getObjectId())
|
||||
->filterByFolderId($event->getReferrerId()),
|
||||
$event,
|
||||
$dispatcher
|
||||
);
|
||||
}
|
||||
|
||||
public function toggleVisibility(ContentToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$content = $event->getContent();
|
||||
|
||||
$content
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible(!$content->getVisible())
|
||||
->save();
|
||||
|
||||
$event->setContent($content);
|
||||
}
|
||||
|
||||
public function delete(ContentDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $content = ContentQuery::create()->findPk($event->getContentId())) {
|
||||
$con = Propel::getWriteConnection(ContentTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$fileList = ['images' => [], 'documentList' => []];
|
||||
|
||||
$defaultFolderId = $content->getDefaultFolderId();
|
||||
|
||||
// Get content's files to delete after content deletion
|
||||
$fileList['images']['list'] = ContentImageQuery::create()
|
||||
->findByContentId($event->getContentId());
|
||||
$fileList['images']['type'] = TheliaEvents::IMAGE_DELETE;
|
||||
|
||||
$fileList['documentList']['list'] = ContentDocumentQuery::create()
|
||||
->findByContentId($event->getContentId());
|
||||
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
||||
|
||||
// Delete content
|
||||
$content->setDispatcher($dispatcher)
|
||||
->delete($con);
|
||||
|
||||
$event->setDefaultFolderId($defaultFolderId);
|
||||
$event->setContent($content);
|
||||
|
||||
// Dispatch delete content's files event
|
||||
foreach ($fileList as $fileTypeList) {
|
||||
foreach ($fileTypeList['list'] as $fileToDelete) {
|
||||
$fileDeleteEvent = new FileDeleteEvent($fileToDelete);
|
||||
$dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* associate a folder to a content if the association already does not exists
|
||||
*
|
||||
* @param ContentAddFolderEvent $event
|
||||
*/
|
||||
public function addFolder(ContentAddFolderEvent $event)
|
||||
{
|
||||
if (ContentFolderQuery::create()
|
||||
->filterByContent($event->getContent())
|
||||
->filterByFolderId($event->getFolderId())
|
||||
->count() <= 0
|
||||
) {
|
||||
$contentFolder = (new ContentFolder())
|
||||
->setFolderId($event->getFolderId())
|
||||
->setContent($event->getContent())
|
||||
->setDefaultFolder(false);
|
||||
|
||||
$contentFolder
|
||||
->setPosition($contentFolder->getNextPosition())
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function removeFolder(ContentRemoveFolderEvent $event)
|
||||
{
|
||||
$contentFolder = ContentFolderQuery::create()
|
||||
->filterByContent($event->getContent())
|
||||
->filterByFolderId($event->getFolderId())
|
||||
->findOne();
|
||||
|
||||
if (null !== $contentFolder) {
|
||||
$contentFolder->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CONTENT_CREATE => array('create', 128),
|
||||
TheliaEvents::CONTENT_UPDATE => array('update', 128),
|
||||
TheliaEvents::CONTENT_DELETE => array('delete', 128),
|
||||
TheliaEvents::CONTENT_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
||||
|
||||
TheliaEvents::CONTENT_UPDATE_POSITION => array('updatePosition', 128),
|
||||
TheliaEvents::CONTENT_UPDATE_SEO => array('updateSeo', 128),
|
||||
|
||||
TheliaEvents::CONTENT_ADD_FOLDER => array('addFolder', 128),
|
||||
TheliaEvents::CONTENT_REMOVE_FOLDER => array('removeFolder', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
121
core/lib/Thelia/Action/Country.php
Normal file
121
core/lib/Thelia/Action/Country.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Country\CountryCreateEvent;
|
||||
use Thelia\Core\Event\Country\CountryDeleteEvent;
|
||||
use Thelia\Core\Event\Country\CountryToggleDefaultEvent;
|
||||
use Thelia\Core\Event\Country\CountryToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Country\CountryUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Country as CountryModel;
|
||||
use Thelia\Model\CountryQuery;
|
||||
|
||||
/**
|
||||
* Class Country
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Country extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(CountryCreateEvent $event)
|
||||
{
|
||||
$country = new CountryModel();
|
||||
|
||||
$country
|
||||
->setVisible($event->isVisible())
|
||||
->setIsocode($event->getIsocode())
|
||||
->setIsoalpha2($event->getIsoAlpha2())
|
||||
->setIsoalpha3($event->getIsoAlpha3())
|
||||
->setHasStates($event->isHasStates())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save();
|
||||
|
||||
$event->setCountry($country);
|
||||
}
|
||||
|
||||
public function update(CountryUpdateEvent $event)
|
||||
{
|
||||
if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) {
|
||||
$country
|
||||
->setVisible($event->isVisible())
|
||||
->setIsocode($event->getIsocode())
|
||||
->setIsoalpha2($event->getIsoAlpha2())
|
||||
->setIsoalpha3($event->getIsoAlpha3())
|
||||
->setHasStates($event->isHasStates())
|
||||
->setNeedZipCode($event->isNeedZipCode())
|
||||
->setZipCodeFormat($event->getZipCodeFormat())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->save();
|
||||
|
||||
$event->setCountry($country);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(CountryDeleteEvent $event)
|
||||
{
|
||||
if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) {
|
||||
$country->delete();
|
||||
|
||||
$event->setCountry($country);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleDefault(CountryToggleDefaultEvent $event)
|
||||
{
|
||||
if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) {
|
||||
$country->toggleDefault();
|
||||
|
||||
$event->setCountry($country);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Country visibility
|
||||
*
|
||||
* @param CountryToggleVisibilityEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function toggleVisibility(CountryToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$country = $event->getCountry();
|
||||
|
||||
$country
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible(!$country->getVisible())
|
||||
->save();
|
||||
|
||||
$event->setCountry($country);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::COUNTRY_CREATE => array('create', 128),
|
||||
TheliaEvents::COUNTRY_UPDATE => array('update', 128),
|
||||
TheliaEvents::COUNTRY_DELETE => array('delete', 128),
|
||||
TheliaEvents::COUNTRY_TOGGLE_DEFAULT => array('toggleDefault', 128),
|
||||
TheliaEvents::COUNTRY_TOGGLE_VISIBILITY => array('toggleVisibility', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
410
core/lib/Thelia/Action/Coupon.php
Normal file
410
core/lib/Thelia/Action/Coupon.php
Normal file
@@ -0,0 +1,410 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionFactory;
|
||||
use Thelia\Condition\Implementation\ConditionInterface;
|
||||
use Thelia\Core\Event\Coupon\CouponConsumeEvent;
|
||||
use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\Coupon\CouponDeleteEvent;
|
||||
use Thelia\Core\Event\Order\OrderEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Coupon\CouponFactory;
|
||||
use Thelia\Coupon\CouponManager;
|
||||
use Thelia\Coupon\Type\CouponInterface;
|
||||
use Thelia\Model\Coupon as CouponModel;
|
||||
use Thelia\Model\CouponCountry;
|
||||
use Thelia\Model\CouponCountryQuery;
|
||||
use Thelia\Model\CouponModule;
|
||||
use Thelia\Model\CouponModuleQuery;
|
||||
use Thelia\Model\CouponQuery;
|
||||
use Thelia\Model\Map\OrderCouponTableMap;
|
||||
use Thelia\Model\OrderCoupon;
|
||||
use Thelia\Model\OrderCouponCountry;
|
||||
use Thelia\Model\OrderCouponModule;
|
||||
|
||||
/**
|
||||
* Process Coupon Events
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>, Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class Coupon extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var RequestStack */
|
||||
protected $requestStack;
|
||||
|
||||
/** @var CouponFactory $couponFactory */
|
||||
protected $couponFactory;
|
||||
|
||||
/** @var CouponManager $couponManager */
|
||||
protected $couponManager;
|
||||
|
||||
/** @var ConditionInterface $noConditionRule */
|
||||
protected $noConditionRule;
|
||||
|
||||
/** @var ConditionFactory $conditionFactory */
|
||||
protected $conditionFactory;
|
||||
|
||||
public function __construct(
|
||||
RequestStack $requestStack,
|
||||
CouponFactory $couponFactory,
|
||||
CouponManager $couponManager,
|
||||
ConditionInterface $noConditionRule,
|
||||
ConditionFactory $conditionFactory
|
||||
) {
|
||||
$this->requestStack = $requestStack;
|
||||
$this->couponFactory = $couponFactory;
|
||||
$this->couponManager = $couponManager;
|
||||
$this->noConditionRule = $noConditionRule;
|
||||
$this->conditionFactory = $conditionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurring when a Coupon is about to be created
|
||||
*
|
||||
* @param CouponCreateOrUpdateEvent $event Event creation or update Coupon
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$coupon = new CouponModel();
|
||||
|
||||
$this->createOrUpdate($coupon, $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurring when a Coupon is about to be updated
|
||||
*
|
||||
* @param CouponCreateOrUpdateEvent $event Event creation or update Coupon
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$coupon = $event->getCouponModel();
|
||||
|
||||
$this->createOrUpdate($coupon, $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function delete(CouponDeleteEvent $event)
|
||||
{
|
||||
$coupon = $event->getCoupon();
|
||||
|
||||
if (null === $coupon) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
"The coupon id '%d' doesn't exist",
|
||||
$event->getCouponId()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$coupon->delete();
|
||||
|
||||
$event->setCoupon(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurring when a Coupon condition is about to be updated
|
||||
*
|
||||
* @param CouponCreateOrUpdateEvent $event Event creation or update Coupon condition
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updateCondition(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$modelCoupon = $event->getCouponModel();
|
||||
|
||||
$this->createOrUpdateCondition($modelCoupon, $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all coupons in session.
|
||||
*
|
||||
* @param Event $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function clearAllCoupons(Event $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
// Tell coupons to clear any data they may have stored
|
||||
$this->couponManager->clear();
|
||||
|
||||
$this->getSession()->setConsumedCoupons(array());
|
||||
|
||||
$this->updateOrderDiscount($event, $eventName, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurring when a Coupon condition is about to be consumed
|
||||
*
|
||||
* @param CouponConsumeEvent $event Event consuming Coupon
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function consume(CouponConsumeEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$totalDiscount = 0;
|
||||
$isValid = false;
|
||||
|
||||
/** @var CouponInterface $coupon */
|
||||
$coupon = $this->couponFactory->buildCouponFromCode($event->getCode());
|
||||
|
||||
if ($coupon) {
|
||||
$isValid = $coupon->isMatching();
|
||||
|
||||
if ($isValid) {
|
||||
$this->couponManager->pushCouponInSession($event->getCode());
|
||||
$totalDiscount = $this->couponManager->getDiscount();
|
||||
|
||||
$this->getSession()
|
||||
->getSessionCart($dispatcher)
|
||||
->setDiscount($totalDiscount)
|
||||
->save();
|
||||
|
||||
$this->getSession()
|
||||
->getOrder()
|
||||
->setDiscount($totalDiscount)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
$event->setIsValid($isValid);
|
||||
$event->setDiscount($totalDiscount);
|
||||
}
|
||||
|
||||
public function updateOrderDiscount(Event $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$discount = $this->couponManager->getDiscount();
|
||||
|
||||
$this->getSession()
|
||||
->getSessionCart($dispatcher)
|
||||
->setDiscount($discount)
|
||||
->save();
|
||||
|
||||
$this->getSession()
|
||||
->getOrder()
|
||||
->setDiscount($discount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Model and delegate the create or delete action
|
||||
* Feed the Event with the updated model
|
||||
*
|
||||
* @param CouponModel $coupon Model to save
|
||||
* @param CouponCreateOrUpdateEvent $event Event containing data
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
protected function createOrUpdate(CouponModel $coupon, CouponCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$coupon->setDispatcher($dispatcher);
|
||||
|
||||
// Set default condition if none found
|
||||
/** @var ConditionInterface $noConditionRule */
|
||||
$noConditionRule = $this->noConditionRule;
|
||||
/** @var ConditionFactory $conditionFactory */
|
||||
$conditionFactory = $this->conditionFactory;
|
||||
$couponRuleCollection = new ConditionCollection();
|
||||
$couponRuleCollection[] = $noConditionRule;
|
||||
$defaultSerializedRule = $conditionFactory->serializeConditionCollection(
|
||||
$couponRuleCollection
|
||||
);
|
||||
|
||||
$coupon->createOrUpdate(
|
||||
$event->getCode(),
|
||||
$event->getTitle(),
|
||||
$event->getEffects(),
|
||||
$event->getServiceId(),
|
||||
$event->isRemovingPostage(),
|
||||
$event->getShortDescription(),
|
||||
$event->getDescription(),
|
||||
$event->isEnabled(),
|
||||
$event->getExpirationDate(),
|
||||
$event->isAvailableOnSpecialOffers(),
|
||||
$event->isCumulative(),
|
||||
$event->getMaxUsage(),
|
||||
$defaultSerializedRule,
|
||||
$event->getLocale(),
|
||||
$event->getFreeShippingForCountries(),
|
||||
$event->getFreeShippingForMethods(),
|
||||
$event->getPerCustomerUsageCount(),
|
||||
$event->getStartDate()
|
||||
);
|
||||
|
||||
$event->setCouponModel($coupon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Model and delegate the create or delete action
|
||||
* Feed the Event with the updated model
|
||||
*
|
||||
* @param CouponModel $coupon Model to save
|
||||
* @param CouponCreateOrUpdateEvent $event Event containing data
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
protected function createOrUpdateCondition(CouponModel $coupon, CouponCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$coupon->setDispatcher($dispatcher);
|
||||
|
||||
/** @var ConditionFactory $conditionFactory */
|
||||
$conditionFactory = $this->conditionFactory;
|
||||
|
||||
$coupon->createOrUpdateConditions(
|
||||
$conditionFactory->serializeConditionCollection($event->getConditions()),
|
||||
$event->getLocale()
|
||||
);
|
||||
|
||||
$event->setCouponModel($coupon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function testFreePostage(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
if ($this->couponManager->isCouponRemovingPostage($order)) {
|
||||
$order->setPostage(0);
|
||||
|
||||
$event->setOrder($order);
|
||||
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*
|
||||
* @throws \Exception if something goes wrong.
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function afterOrder(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
/** @var CouponInterface[] $consumedCoupons */
|
||||
$consumedCoupons = $this->couponManager->getCouponsKept();
|
||||
|
||||
if (is_array($consumedCoupons) && count($consumedCoupons) > 0) {
|
||||
$con = Propel::getWriteConnection(OrderCouponTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
foreach ($consumedCoupons as $couponCode) {
|
||||
$couponQuery = CouponQuery::create();
|
||||
$couponModel = $couponQuery->findOneByCode($couponCode->getCode());
|
||||
$couponModel->setLocale($this->getSession()->getLang()->getLocale());
|
||||
|
||||
/* decrease coupon quantity */
|
||||
$this->couponManager->decrementQuantity($couponModel, $event->getOrder()->getCustomerId());
|
||||
|
||||
/* memorize coupon */
|
||||
$orderCoupon = new OrderCoupon();
|
||||
$orderCoupon->setOrder($event->getOrder())
|
||||
->setCode($couponModel->getCode())
|
||||
->setType($couponModel->getType())
|
||||
->setAmount($couponModel->getAmount())
|
||||
|
||||
->setTitle($couponModel->getTitle())
|
||||
->setShortDescription($couponModel->getShortDescription())
|
||||
->setDescription($couponModel->getDescription())
|
||||
|
||||
->setStartDate($couponModel->getStartDate())
|
||||
->setExpirationDate($couponModel->getExpirationDate())
|
||||
->setIsCumulative($couponModel->getIsCumulative())
|
||||
->setIsRemovingPostage($couponModel->getIsRemovingPostage())
|
||||
->setIsAvailableOnSpecialOffers($couponModel->getIsAvailableOnSpecialOffers())
|
||||
->setSerializedConditions($couponModel->getSerializedConditions())
|
||||
->setPerCustomerUsageCount($couponModel->getPerCustomerUsageCount())
|
||||
;
|
||||
$orderCoupon->save();
|
||||
|
||||
// Copy order coupon free shipping data for countries and modules
|
||||
$couponCountries = CouponCountryQuery::create()->filterByCouponId($couponModel->getId())->find();
|
||||
|
||||
/** @var CouponCountry $couponCountry */
|
||||
foreach ($couponCountries as $couponCountry) {
|
||||
$occ = new OrderCouponCountry();
|
||||
|
||||
$occ
|
||||
->setCouponId($orderCoupon->getId())
|
||||
->setCountryId($couponCountry->getCountryId())
|
||||
->save();
|
||||
;
|
||||
}
|
||||
|
||||
$couponModules = CouponModuleQuery::create()->filterByCouponId($couponModel->getId())->find();
|
||||
|
||||
/** @var CouponModule $couponModule */
|
||||
foreach ($couponModules as $couponModule) {
|
||||
$ocm = new OrderCouponModule();
|
||||
|
||||
$ocm
|
||||
->setCouponId($orderCoupon->getId())
|
||||
->setModuleId($couponModule->getModuleId())
|
||||
->save();
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollBack();
|
||||
|
||||
throw($ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all coupons.
|
||||
$dispatcher->dispatch(TheliaEvents::COUPON_CLEAR_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::COUPON_CREATE => array("create", 128),
|
||||
TheliaEvents::COUPON_UPDATE => array("update", 128),
|
||||
TheliaEvents::COUPON_DELETE => array("delete", 128),
|
||||
TheliaEvents::COUPON_CONSUME => array("consume", 128),
|
||||
TheliaEvents::COUPON_CLEAR_ALL => array("clearAllCoupons", 128),
|
||||
TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128),
|
||||
TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132),
|
||||
TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128),
|
||||
TheliaEvents::CART_ADDITEM => array("updateOrderDiscount", 10),
|
||||
TheliaEvents::CART_UPDATEITEM => array("updateOrderDiscount", 10),
|
||||
TheliaEvents::CART_DELETEITEM => array("updateOrderDiscount", 10),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session from the current request
|
||||
*
|
||||
* @return \Thelia\Core\HttpFoundation\Session\Session
|
||||
*/
|
||||
protected function getSession()
|
||||
{
|
||||
return $this->requestStack->getCurrentRequest()->getSession();
|
||||
}
|
||||
}
|
||||
219
core/lib/Thelia/Action/Currency.php
Normal file
219
core/lib/Thelia/Action/Currency.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Currency\CurrencyCreateEvent;
|
||||
use Thelia\Core\Event\Currency\CurrencyDeleteEvent;
|
||||
use Thelia\Core\Event\Currency\CurrencyUpdateEvent;
|
||||
use Thelia\Core\Event\Currency\CurrencyUpdateRateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\CurrencyConverter\CurrencyConverter;
|
||||
use Thelia\CurrencyConverter\Exception\CurrencyNotFoundException;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Math\Number;
|
||||
use Thelia\Model\Currency as CurrencyModel;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
|
||||
class Currency extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var CurrencyConverter */
|
||||
protected $currencyConverter;
|
||||
|
||||
public function __construct(CurrencyConverter $currencyConverter)
|
||||
{
|
||||
$this->currencyConverter = $currencyConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new currencyuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Currency\CurrencyCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(CurrencyCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$currency = new CurrencyModel();
|
||||
|
||||
$isDefault = CurrencyQuery::create()->count() === 0;
|
||||
|
||||
$currency
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setName($event->getCurrencyName())
|
||||
->setSymbol($event->getSymbol())
|
||||
->setFormat($event->getFormat())
|
||||
->setRate($event->getRate())
|
||||
->setCode(strtoupper($event->getCode()))
|
||||
->setByDefault($isDefault)
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setCurrency($currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a currency
|
||||
*
|
||||
* @param \Thelia\Core\Event\Currency\CurrencyUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(CurrencyUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) {
|
||||
$currency
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setName($event->getCurrencyName())
|
||||
->setSymbol($event->getSymbol())
|
||||
->setFormat($event->getFormat())
|
||||
->setRate($event->getRate())
|
||||
->setCode(strtoupper($event->getCode()))
|
||||
|
||||
->save();
|
||||
|
||||
$event->setCurrency($currency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default currency
|
||||
*
|
||||
* @param CurrencyUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function setDefault(CurrencyUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) {
|
||||
// Reset default status
|
||||
CurrencyQuery::create()->filterByByDefault(true)->update(array('ByDefault' => false));
|
||||
|
||||
$currency
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible($event->getVisible())
|
||||
->setByDefault($event->getIsDefault())
|
||||
->save()
|
||||
;
|
||||
|
||||
// Update rates when setting a new default currency
|
||||
if ($event->getIsDefault()) {
|
||||
$updateRateEvent = new CurrencyUpdateRateEvent();
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES, $updateRateEvent);
|
||||
}
|
||||
|
||||
$event->setCurrency($currency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CurrencyUpdateEvent $event
|
||||
*/
|
||||
public function setVisible(CurrencyUpdateEvent $event)
|
||||
{
|
||||
if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) {
|
||||
if (!$currency->getByDefault()) {
|
||||
$currency->setVisible($event->getVisible())->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a currencyuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Currency\CurrencyDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(CurrencyDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($currency = CurrencyQuery::create()->findPk($event->getCurrencyId()))) {
|
||||
if ($currency->getByDefault()) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans('It is not allowed to delete the default currency')
|
||||
);
|
||||
}
|
||||
|
||||
$currency
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setCurrency($currency);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateRates(CurrencyUpdateRateEvent $event)
|
||||
{
|
||||
if (null === $defaultCurrency = CurrencyQuery::create()->findOneByByDefault(true)) {
|
||||
throw new \RuntimeException('Unable to find a default currency, please define a default currency.');
|
||||
}
|
||||
|
||||
$defaultCurrency->setRate(1)->save();
|
||||
|
||||
$currencies = CurrencyQuery::create()->filterByByDefault(false);
|
||||
$baseValue = new Number('1');
|
||||
|
||||
/** @var \Thelia\Model\Currency $currency */
|
||||
foreach ($currencies as $currency) {
|
||||
try {
|
||||
$rate = $this->currencyConverter
|
||||
->from($defaultCurrency->getCode())
|
||||
->to($currency->getCode())
|
||||
->convert($baseValue);
|
||||
|
||||
$currency->setRate($rate->getNumber(-1))->save();
|
||||
} catch (CurrencyNotFoundException $ex) {
|
||||
Tlog::getInstance()->addError(
|
||||
sprintf("Unable to find exchange rate for currency %s, ID %d", $currency->getCode(), $currency->getId())
|
||||
);
|
||||
$event->addUndefinedRate($currency->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param string $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(CurrencyQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CURRENCY_CREATE => array("create", 128),
|
||||
TheliaEvents::CURRENCY_UPDATE => array("update", 128),
|
||||
TheliaEvents::CURRENCY_DELETE => array("delete", 128),
|
||||
TheliaEvents::CURRENCY_SET_DEFAULT => array("setDefault", 128),
|
||||
TheliaEvents::CURRENCY_SET_VISIBLE => array("setVisible", 128),
|
||||
TheliaEvents::CURRENCY_UPDATE_RATES => array("updateRates", 128),
|
||||
TheliaEvents::CURRENCY_UPDATE_POSITION => array("updatePosition", 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
215
core/lib/Thelia/Action/Customer.php
Normal file
215
core/lib/Thelia/Action/Customer.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\ActionEvent;
|
||||
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\Customer\CustomerEvent;
|
||||
use Thelia\Core\Event\Customer\CustomerLoginEvent;
|
||||
use Thelia\Core\Event\LostPasswordEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Security\SecurityContext;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Exception\CustomerException;
|
||||
use Thelia\Mailer\MailerFactory;
|
||||
use Thelia\Model\Customer as CustomerModel;
|
||||
use Thelia\Model\CustomerQuery;
|
||||
use Thelia\Tools\Password;
|
||||
|
||||
/**
|
||||
*
|
||||
* customer class where all actions are managed
|
||||
*
|
||||
* Class Customer
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Customer extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var SecurityContext */
|
||||
protected $securityContext;
|
||||
|
||||
/** @var MailerFactory */
|
||||
protected $mailer;
|
||||
|
||||
public function __construct(SecurityContext $securityContext, MailerFactory $mailer)
|
||||
{
|
||||
$this->securityContext = $securityContext;
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
public function create(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$customer = new CustomerModel();
|
||||
|
||||
$plainPassword = $event->getPassword();
|
||||
|
||||
$this->createOrUpdateCustomer($customer, $event, $dispatcher);
|
||||
|
||||
if ($event->getNotifyCustomerOfAccountCreation()) {
|
||||
$this->mailer->sendEmailToCustomer('customer_account_created', $customer, [ 'password' => $plainPassword ]);
|
||||
}
|
||||
}
|
||||
|
||||
public function modify(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$plainPassword = $event->getPassword();
|
||||
|
||||
$customer = $event->getCustomer();
|
||||
|
||||
$emailChanged = $customer->getEmail() !== $event->getEmail();
|
||||
|
||||
$this->createOrUpdateCustomer($customer, $event, $dispatcher);
|
||||
|
||||
if (! empty($plainPassword) || $emailChanged) {
|
||||
$this->mailer->sendEmailToCustomer('customer_account_changed', $customer, ['password' => $plainPassword]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateProfile(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$customer = $event->getCustomer();
|
||||
|
||||
$customer->setDispatcher($dispatcher);
|
||||
|
||||
if ($event->getTitle() !== null) {
|
||||
$customer->setTitleId($event->getTitle());
|
||||
}
|
||||
|
||||
if ($event->getFirstname() !== null) {
|
||||
$customer->setFirstname($event->getFirstname());
|
||||
}
|
||||
|
||||
if ($event->getLastname() !== null) {
|
||||
$customer->setLastname($event->getLastname());
|
||||
}
|
||||
|
||||
if ($event->getEmail() !== null) {
|
||||
$customer->setEmail($event->getEmail(), $event->getEmailUpdateAllowed());
|
||||
}
|
||||
|
||||
if ($event->getPassword() !== null) {
|
||||
$customer->setPassword($event->getPassword());
|
||||
}
|
||||
|
||||
if ($event->getReseller() !== null) {
|
||||
$customer->setReseller($event->getReseller());
|
||||
}
|
||||
|
||||
if ($event->getSponsor() !== null) {
|
||||
$customer->setSponsor($event->getSponsor());
|
||||
}
|
||||
|
||||
if ($event->getDiscount() !== null) {
|
||||
$customer->setDiscount($event->getDiscount());
|
||||
}
|
||||
|
||||
$customer->save();
|
||||
|
||||
$event->setCustomer($customer);
|
||||
}
|
||||
|
||||
public function delete(CustomerEvent $event)
|
||||
{
|
||||
if (null !== $customer = $event->getCustomer()) {
|
||||
if (true === $customer->hasOrder()) {
|
||||
throw new CustomerException(Translator::getInstance()->trans("Impossible to delete a customer who already have orders"));
|
||||
}
|
||||
|
||||
$customer->delete();
|
||||
}
|
||||
}
|
||||
|
||||
private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$customer->setDispatcher($dispatcher);
|
||||
|
||||
$customer->createOrUpdate(
|
||||
$event->getTitle(),
|
||||
$event->getFirstname(),
|
||||
$event->getLastname(),
|
||||
$event->getAddress1(),
|
||||
$event->getAddress2(),
|
||||
$event->getAddress3(),
|
||||
$event->getPhone(),
|
||||
$event->getCellphone(),
|
||||
$event->getZipcode(),
|
||||
$event->getCity(),
|
||||
$event->getCountry(),
|
||||
$event->getEmail(),
|
||||
$event->getPassword(),
|
||||
$event->getLangId(),
|
||||
$event->getReseller(),
|
||||
$event->getSponsor(),
|
||||
$event->getDiscount(),
|
||||
$event->getCompany(),
|
||||
$event->getRef(),
|
||||
$event->getEmailUpdateAllowed(),
|
||||
$event->getState()
|
||||
);
|
||||
|
||||
$event->setCustomer($customer);
|
||||
}
|
||||
|
||||
public function login(CustomerLoginEvent $event)
|
||||
{
|
||||
$customer = $event->getCustomer();
|
||||
|
||||
if (method_exists($customer, 'clearDispatcher')) {
|
||||
$customer->clearDispatcher();
|
||||
}
|
||||
$this->securityContext->setCustomerUser($event->getCustomer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform user logout. The user is redirected to the provided view, if any.
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
*/
|
||||
public function logout(/** @noinspection PhpUnusedParameterInspection */ ActionEvent $event)
|
||||
{
|
||||
$this->securityContext->clearCustomerUser();
|
||||
}
|
||||
|
||||
public function lostPassword(LostPasswordEvent $event)
|
||||
{
|
||||
if (null !== $customer = CustomerQuery::create()->filterByEmail($event->getEmail())->findOne()) {
|
||||
$password = Password::generateRandom(8);
|
||||
|
||||
$customer
|
||||
->setPassword($password)
|
||||
->save()
|
||||
;
|
||||
|
||||
$this->mailer->sendEmailToCustomer('lost_password', $customer, ['password' => $password]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CUSTOMER_CREATEACCOUNT => array('create', 128),
|
||||
TheliaEvents::CUSTOMER_UPDATEACCOUNT => array('modify', 128),
|
||||
TheliaEvents::CUSTOMER_UPDATEPROFILE => array('updateProfile', 128),
|
||||
TheliaEvents::CUSTOMER_LOGOUT => array('logout', 128),
|
||||
TheliaEvents::CUSTOMER_LOGIN => array('login', 128),
|
||||
TheliaEvents::CUSTOMER_DELETEACCOUNT => array('delete', 128),
|
||||
TheliaEvents::LOST_PASSWORD => array('lostPassword', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
111
core/lib/Thelia/Action/CustomerTitle.php
Normal file
111
core/lib/Thelia/Action/CustomerTitle.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\CustomerTitle\CustomerTitleEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\CustomerTitle as CustomerTitleModel;
|
||||
use Thelia\Model\Map\CustomerTitleTableMap;
|
||||
|
||||
/**
|
||||
* Class CustomerTitle
|
||||
* @package Thelia\Action
|
||||
* @author Benjamin Perche <bperche@openstudio.fr>
|
||||
*/
|
||||
class CustomerTitle extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(CustomerTitleEvent $event)
|
||||
{
|
||||
$this->createOrUpdate($event, new CustomerTitleModel());
|
||||
}
|
||||
|
||||
public function update(CustomerTitleEvent $event)
|
||||
{
|
||||
$this->checkCustomerTitle($event);
|
||||
|
||||
$this->createOrUpdate($event, $event->getCustomerTitle());
|
||||
}
|
||||
|
||||
public function delete(CustomerTitleEvent $event)
|
||||
{
|
||||
$this->checkCustomerTitle($event);
|
||||
|
||||
$con = Propel::getConnection(CustomerTitleTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$event->getCustomerTitle()->delete();
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$event->setCustomerTitle(null);
|
||||
}
|
||||
|
||||
protected function checkCustomerTitle(CustomerTitleEvent $event)
|
||||
{
|
||||
if (null === $event->getCustomerTitle()) {
|
||||
throw new \LogicException(
|
||||
"You must set the customer title before its update"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function createOrUpdate(CustomerTitleEvent $event, CustomerTitleModel $customerTitle)
|
||||
{
|
||||
$con = Propel::getConnection(CustomerTitleTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
$i18n = $customerTitle->getTranslation($event->getLocale(), $con);
|
||||
|
||||
try {
|
||||
$i18n
|
||||
->setShort($event->getShort())
|
||||
->setLong($event->getLong())
|
||||
;
|
||||
|
||||
$customerTitle->save($con);
|
||||
|
||||
if ($event->isDefault()) {
|
||||
$customerTitle->toggleDefault($con);
|
||||
$event->setDefault(false);
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$event->setCustomerTitle($customerTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::CUSTOMER_TITLE_CREATE => array("create"),
|
||||
TheliaEvents::CUSTOMER_TITLE_UPDATE => array("update"),
|
||||
TheliaEvents::CUSTOMER_TITLE_DELETE => array("delete"),
|
||||
);
|
||||
}
|
||||
}
|
||||
66
core/lib/Thelia/Action/Delivery.php
Normal file
66
core/lib/Thelia/Action/Delivery.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Delivery\DeliveryPostageEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
/**
|
||||
* Class Delivery
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class Delivery implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Get postage from module using the classical module functions
|
||||
*
|
||||
* @param DeliveryPostageEvent $event
|
||||
*/
|
||||
public function getPostage(DeliveryPostageEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$module = $event->getModule();
|
||||
|
||||
// dispatch event to target specific module
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::getModuleEvent(
|
||||
TheliaEvents::MODULE_DELIVERY_GET_POSTAGE,
|
||||
$module->getCode()
|
||||
),
|
||||
$event
|
||||
);
|
||||
|
||||
if ($event->isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// call legacy module method
|
||||
$event->setValidModule($module->isValidDelivery($event->getCountry()));
|
||||
if ($event->isValidModule()) {
|
||||
$event->setPostage($module->getPostage($event->getCountry()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::MODULE_DELIVERY_GET_POSTAGE => ['getPostage', 128]
|
||||
];
|
||||
}
|
||||
}
|
||||
125
core/lib/Thelia/Action/Document.php
Normal file
125
core/lib/Thelia/Action/Document.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Document\DocumentEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Exception\DocumentException;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
/**
|
||||
*
|
||||
* Document management actions. This class handles document processing an caching.
|
||||
*
|
||||
* Basically, documents are stored outside the web space (by default in local/media/documents),
|
||||
* and cached in the web space (by default in web/local/documents).
|
||||
*
|
||||
* In the documents caches directory, a subdirectory for documents categories (eg. product, category, folder, etc.) is
|
||||
* automatically created, and the cached document is created here. Plugin may use their own subdirectory as required.
|
||||
*
|
||||
* The cached document name contains a hash of the processing options, and the original (normalized) name of the document.
|
||||
*
|
||||
* A copy (or symbolic link, by default) of the original document is always created in the cache, so that the full
|
||||
* resolution document is always available.
|
||||
*
|
||||
* If a problem occurs, an DocumentException may be thrown.
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class Document extends BaseCachedFile implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var string Config key for document delivery mode
|
||||
*/
|
||||
const CONFIG_DELIVERY_MODE = 'original_document_delivery_mode';
|
||||
|
||||
/**
|
||||
* @return string root of the document cache directory in web space
|
||||
*/
|
||||
protected function getCacheDirFromWebRoot()
|
||||
{
|
||||
return ConfigQuery::read('document_cache_dir_from_web_root', 'cache' . DS . 'documents');
|
||||
}
|
||||
|
||||
/**
|
||||
* Process document and write the result in the document cache.
|
||||
*
|
||||
* When the original document is required, create either a symbolic link with the
|
||||
* original document in the cache dir, or copy it in the cache dir if it's not already done.
|
||||
*
|
||||
* This method updates the cache_file_path and file_url attributes of the event
|
||||
*
|
||||
* @param DocumentEvent $event Event
|
||||
*
|
||||
* @throws \Thelia\Exception\DocumentException
|
||||
* @throws \InvalidArgumentException , DocumentException
|
||||
*/
|
||||
public function processDocument(DocumentEvent $event)
|
||||
{
|
||||
$subdir = $event->getCacheSubdirectory();
|
||||
$sourceFile = $event->getSourceFilepath();
|
||||
|
||||
if (null == $subdir || null == $sourceFile) {
|
||||
throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null");
|
||||
}
|
||||
|
||||
$originalDocumentPathInCache = $this->getCacheFilePath($subdir, $sourceFile, true);
|
||||
|
||||
if (! file_exists($originalDocumentPathInCache)) {
|
||||
if (! file_exists($sourceFile)) {
|
||||
throw new DocumentException(sprintf("Source document file %s does not exists.", $sourceFile));
|
||||
}
|
||||
|
||||
$mode = ConfigQuery::read(self::CONFIG_DELIVERY_MODE, 'symlink');
|
||||
|
||||
if ($mode == 'symlink') {
|
||||
if (false === symlink($sourceFile, $originalDocumentPathInCache)) {
|
||||
throw new DocumentException(sprintf("Failed to create symbolic link for %s in %s document cache directory", basename($sourceFile), $subdir));
|
||||
}
|
||||
} else {
|
||||
// mode = 'copy'
|
||||
if (false === @copy($sourceFile, $originalDocumentPathInCache)) {
|
||||
throw new DocumentException(sprintf("Failed to copy %s in %s document cache directory", basename($sourceFile), $subdir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the document URL
|
||||
$documentUrl = $this->getCacheFileURL($subdir, basename($originalDocumentPathInCache));
|
||||
|
||||
// Update the event with file path and file URL
|
||||
$event->setDocumentPath($documentUrl);
|
||||
$event->setDocumentUrl(URL::getInstance()->absoluteUrl($documentUrl, null, URL::PATH_TO_FILE));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::DOCUMENT_PROCESS => array("processDocument", 128),
|
||||
|
||||
// Implemented in parent class BaseCachedFile
|
||||
TheliaEvents::DOCUMENT_CLEAR_CACHE => array("clearCache", 128),
|
||||
TheliaEvents::DOCUMENT_DELETE => array("deleteFile", 128),
|
||||
TheliaEvents::DOCUMENT_SAVE => array("saveFile", 128),
|
||||
TheliaEvents::DOCUMENT_UPDATE => array("updateFile", 128),
|
||||
TheliaEvents::DOCUMENT_UPDATE_POSITION => array("updatePosition", 128),
|
||||
TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
79
core/lib/Thelia/Action/Export.php
Normal file
79
core/lib/Thelia/Action/Export.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Handler\ExportHandler;
|
||||
use Thelia\Model\ExportCategoryQuery;
|
||||
use Thelia\Model\ExportQuery;
|
||||
|
||||
/**
|
||||
* Class Export
|
||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||
*/
|
||||
class Export extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var \Thelia\Handler\ExportHandler The export handler
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* @param \Thelia\Handler\ExportHandler $exportHandler The export handler
|
||||
*/
|
||||
public function __construct(ExportHandler $exportHandler)
|
||||
{
|
||||
$this->handler = $exportHandler;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::EXPORT_CHANGE_POSITION => [
|
||||
['exportChangePosition', 128]
|
||||
],
|
||||
TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION => [
|
||||
['exportCategoryChangePosition', 128]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle export change position event
|
||||
*
|
||||
* @param UpdatePositionEvent $updatePositionEvent
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function exportChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->handler->getExport($updatePositionEvent->getObjectId(), true);
|
||||
$this->genericUpdatePosition(new ExportQuery, $updatePositionEvent, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle export category change position event
|
||||
*
|
||||
* @param UpdatePositionEvent $updatePositionEvent
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function exportCategoryChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->handler->getCategory($updatePositionEvent->getObjectId(), true);
|
||||
$this->genericUpdatePosition(new ExportCategoryQuery, $updatePositionEvent, $dispatcher);
|
||||
}
|
||||
}
|
||||
159
core/lib/Thelia/Action/Feature.php
Normal file
159
core/lib/Thelia/Action/Feature.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\FeatureQuery;
|
||||
use Thelia\Model\Feature as FeatureModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Feature\FeatureUpdateEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureCreateEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureEvent;
|
||||
use Thelia\Model\FeatureTemplate;
|
||||
use Thelia\Model\FeatureTemplateQuery;
|
||||
use Thelia\Model\TemplateQuery;
|
||||
|
||||
class Feature extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new feature entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Feature\FeatureCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(FeatureCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$feature = new FeatureModel();
|
||||
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setFeature($feature);
|
||||
|
||||
// Add atribute to all product templates if required
|
||||
if ($event->getAddToAllTemplates() != 0) {
|
||||
$this->doAddToAllTemplates($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product feature
|
||||
*
|
||||
* @param \Thelia\Core\Event\Feature\FeatureUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(FeatureUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $feature = FeatureQuery::create()->findPk($event->getFeatureId())) {
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setFeature($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product feature entry
|
||||
*
|
||||
* @param FeatureDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(FeatureDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($feature = FeatureQuery::create()->findPk($event->getFeatureId()))) {
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setFeature($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(FeatureQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
protected function doAddToAllTemplates(FeatureModel $feature)
|
||||
{
|
||||
$templates = TemplateQuery::create()->find();
|
||||
|
||||
foreach ($templates as $template) {
|
||||
$feature_template = new FeatureTemplate();
|
||||
|
||||
if (null === FeatureTemplateQuery::create()->filterByFeature($feature)->filterByTemplate($template)->findOne()) {
|
||||
$feature_template
|
||||
->setFeature($feature)
|
||||
->setTemplate($template)
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addToAllTemplates(FeatureEvent $event)
|
||||
{
|
||||
$this->doAddToAllTemplates($event->getFeature());
|
||||
}
|
||||
|
||||
public function removeFromAllTemplates(FeatureEvent $event)
|
||||
{
|
||||
// Delete this feature from all product templates
|
||||
FeatureTemplateQuery::create()->filterByFeature($event->getFeature())->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::FEATURE_CREATE => array("create", 128),
|
||||
TheliaEvents::FEATURE_UPDATE => array("update", 128),
|
||||
TheliaEvents::FEATURE_DELETE => array("delete", 128),
|
||||
TheliaEvents::FEATURE_UPDATE_POSITION => array("updatePosition", 128),
|
||||
|
||||
TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES => array("removeFromAllTemplates", 128),
|
||||
TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES => array("addToAllTemplates", 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
119
core/lib/Thelia/Action/FeatureAv.php
Normal file
119
core/lib/Thelia/Action/FeatureAv.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\FeatureAvQuery;
|
||||
use Thelia\Model\FeatureAv as FeatureAvModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Feature\FeatureAvUpdateEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
|
||||
class FeatureAv extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new feature entry
|
||||
*
|
||||
* @param FeatureAvCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(FeatureAvCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$feature = new FeatureAvModel();
|
||||
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setFeatureId($event->getFeatureId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setFeatureAv($feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product feature
|
||||
*
|
||||
* @param FeatureAvUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(FeatureAvUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId())) {
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setFeatureAv($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product feature entry
|
||||
*
|
||||
* @param FeatureAvDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(FeatureAvDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId()))) {
|
||||
$feature
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setFeatureAv($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(FeatureAvQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::FEATURE_AV_CREATE => array("create", 128),
|
||||
TheliaEvents::FEATURE_AV_UPDATE => array("update", 128),
|
||||
TheliaEvents::FEATURE_AV_DELETE => array("delete", 128),
|
||||
TheliaEvents::FEATURE_AV_UPDATE_POSITION => array("updatePosition", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
175
core/lib/Thelia/Action/File.php
Normal file
175
core/lib/Thelia/Action/File.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Thelia\Core\Event\File\FileCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\Product\ProductCloneEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\ProductDocument;
|
||||
use Thelia\Model\ProductDocumentI18n;
|
||||
use Thelia\Model\ProductDocumentI18nQuery;
|
||||
use Thelia\Model\ProductDocumentQuery;
|
||||
use Thelia\Model\ProductImage;
|
||||
use Thelia\Model\ProductImageI18nQuery;
|
||||
use Thelia\Model\ProductImageQuery;
|
||||
|
||||
/**
|
||||
* Class File
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Etienne Perriere <eperriere@openstudio.fr>
|
||||
*/
|
||||
class File extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function cloneFile(ProductCloneEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$originalProductId = $event->getOriginalProduct()->getId();
|
||||
$clonedProduct = $event->getClonedProduct();
|
||||
|
||||
foreach ($event->getTypes() as $type) {
|
||||
$originalProductFiles = [];
|
||||
|
||||
switch ($type) {
|
||||
case 'images':
|
||||
$originalProductFiles = ProductImageQuery::create()
|
||||
->findByProductId($originalProductId);
|
||||
break;
|
||||
|
||||
case 'documents':
|
||||
$originalProductFiles = ProductDocumentQuery::create()
|
||||
->findByProductId($originalProductId);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set clone's files
|
||||
/** @var ProductDocument|ProductImage $originalProductFile */
|
||||
foreach ($originalProductFiles as $originalProductFile) {
|
||||
$srcPath = $originalProductFile->getUploadDir() . DS . $originalProductFile->getFile();
|
||||
|
||||
if (file_exists($srcPath)) {
|
||||
$ext = pathinfo($srcPath, PATHINFO_EXTENSION);
|
||||
|
||||
$clonedProductFile = [];
|
||||
|
||||
switch ($type) {
|
||||
case 'images':
|
||||
$fileName = $clonedProduct->getRef().'.'.$ext;
|
||||
$clonedProductFile = new ProductImage();
|
||||
break;
|
||||
|
||||
case 'documents':
|
||||
$fileName = pathinfo($originalProductFile->getFile(), PATHINFO_FILENAME).'-'.$clonedProduct->getRef().'.'.$ext;
|
||||
$clonedProductFile = new ProductDocument();
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy a temporary file of the source file as it will be deleted by IMAGE_SAVE or DOCUMENT_SAVE event
|
||||
$srcTmp = $srcPath.'.tmp';
|
||||
copy($srcPath, $srcTmp);
|
||||
|
||||
// Get file mimeType
|
||||
$finfo = new \finfo();
|
||||
$fileMimeType = $finfo->file($srcPath, FILEINFO_MIME_TYPE);
|
||||
|
||||
// Get file event's parameters
|
||||
$clonedProductFile
|
||||
->setProductId($clonedProduct->getId())
|
||||
->setVisible($originalProductFile->getVisible())
|
||||
->setPosition($originalProductFile->getPosition())
|
||||
->setLocale($clonedProduct->getLocale())
|
||||
->setTitle($clonedProduct->getTitle());
|
||||
|
||||
$clonedProductCopiedFile = new UploadedFile($srcPath, $fileName, $fileMimeType, filesize($srcPath), null, true);
|
||||
|
||||
// Create and dispatch event
|
||||
$clonedProductCreateFileEvent = new FileCreateOrUpdateEvent($clonedProduct->getId());
|
||||
$clonedProductCreateFileEvent
|
||||
->setModel($clonedProductFile)
|
||||
->setUploadedFile($clonedProductCopiedFile)
|
||||
->setParentName($clonedProduct->getTitle());
|
||||
|
||||
$originalProductFileI18ns = [];
|
||||
|
||||
switch ($type) {
|
||||
case 'images':
|
||||
$dispatcher->dispatch(TheliaEvents::IMAGE_SAVE, $clonedProductCreateFileEvent);
|
||||
|
||||
// Get original product image I18n
|
||||
$originalProductFileI18ns = ProductImageI18nQuery::create()
|
||||
->findById($originalProductFile->getId());
|
||||
break;
|
||||
|
||||
case 'documents':
|
||||
$dispatcher->dispatch(TheliaEvents::DOCUMENT_SAVE, $clonedProductCreateFileEvent);
|
||||
|
||||
// Get original product document I18n
|
||||
$originalProductFileI18ns = ProductDocumentI18nQuery::create()
|
||||
->findById($originalProductFile->getId());
|
||||
break;
|
||||
}
|
||||
|
||||
// Set temporary source file as original one
|
||||
rename($srcTmp, $srcPath);
|
||||
|
||||
// Clone file's I18n
|
||||
$this->cloneFileI18n($originalProductFileI18ns, $clonedProductFile, $type, $event, $dispatcher);
|
||||
} else {
|
||||
Tlog::getInstance()->addWarning("Failed to find media file $srcPath");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function cloneFileI18n($originalProductFileI18ns, $clonedProductFile, $type, ProductCloneEvent $event, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
// Set clone files I18n
|
||||
/** @var ProductDocumentI18n $originalProductFileI18n */
|
||||
foreach ($originalProductFileI18ns as $originalProductFileI18n) {
|
||||
// Update file with current I18n info. Update or create I18n according to existing or absent Locale in DB
|
||||
$clonedProductFile
|
||||
->setLocale($originalProductFileI18n->getLocale())
|
||||
->setTitle($originalProductFileI18n->getTitle())
|
||||
->setDescription($originalProductFileI18n->getDescription())
|
||||
->setChapo($originalProductFileI18n->getChapo())
|
||||
->setPostscriptum($originalProductFileI18n->getPostscriptum());
|
||||
|
||||
// Create and dispatch event
|
||||
$clonedProductUpdateFileEvent = new FileCreateOrUpdateEvent($event->getClonedProduct()->getId());
|
||||
$clonedProductUpdateFileEvent->setModel($clonedProductFile);
|
||||
|
||||
switch ($type) {
|
||||
case 'images':
|
||||
$dispatcher->dispatch(TheliaEvents::IMAGE_UPDATE, $clonedProductUpdateFileEvent);
|
||||
break;
|
||||
|
||||
case 'documents':
|
||||
$dispatcher->dispatch(TheliaEvents::DOCUMENT_UPDATE, $clonedProductUpdateFileEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::FILE_CLONE => array("cloneFile", 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
173
core/lib/Thelia/Action/Folder.php
Normal file
173
core/lib/Thelia/Action/Folder.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||
use Thelia\Core\Event\Folder\FolderCreateEvent;
|
||||
use Thelia\Core\Event\Folder\FolderDeleteEvent;
|
||||
use Thelia\Core\Event\Folder\FolderToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Folder\FolderUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Model\FolderDocumentQuery;
|
||||
use Thelia\Model\FolderImageQuery;
|
||||
use Thelia\Model\FolderQuery;
|
||||
use Thelia\Model\Folder as FolderModel;
|
||||
use Thelia\Model\Map\FolderTableMap;
|
||||
|
||||
/**
|
||||
* Class Folder
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Folder extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function update(FolderUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $folder = FolderQuery::create()->findPk($event->getFolderId())) {
|
||||
$folder->setDispatcher($dispatcher);
|
||||
|
||||
$folder
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->save();
|
||||
;
|
||||
|
||||
$event->setFolder($folder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Folder SEO
|
||||
*
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdateSeo(FolderQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function delete(FolderDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $folder = FolderQuery::create()->findPk($event->getFolderId())) {
|
||||
$con = Propel::getWriteConnection(FolderTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$fileList = ['images' => [], 'documentList' => []];
|
||||
|
||||
// Get folder's files to delete after folder deletion
|
||||
$fileList['images']['list'] = FolderImageQuery::create()
|
||||
->findByFolderId($event->getFolderId());
|
||||
$fileList['images']['type'] = TheliaEvents::IMAGE_DELETE;
|
||||
|
||||
$fileList['documentList']['list'] = FolderDocumentQuery::create()
|
||||
->findByFolderId($event->getFolderId());
|
||||
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
||||
|
||||
// Delete folder
|
||||
$folder->setDispatcher($dispatcher)
|
||||
->delete($con);
|
||||
|
||||
$event->setFolder($folder);
|
||||
|
||||
// Dispatch delete folder's files event
|
||||
foreach ($fileList as $fileTypeList) {
|
||||
foreach ($fileTypeList['list'] as $fileToDelete) {
|
||||
$fileDeleteEvent = new FileDeleteEvent($fileToDelete);
|
||||
$dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function create(FolderCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$folder = new FolderModel();
|
||||
$folder->setDispatcher($dispatcher);
|
||||
|
||||
$folder
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save();
|
||||
|
||||
$event->setFolder($folder);
|
||||
}
|
||||
|
||||
public function toggleVisibility(FolderToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
|
||||
$folder
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible(!$folder->getVisible())
|
||||
->save();
|
||||
|
||||
$event->setFolder($folder);
|
||||
}
|
||||
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $folder = FolderQuery::create()->findPk($event->getObjectId())) {
|
||||
$folder->setDispatcher($dispatcher);
|
||||
|
||||
switch ($event->getMode()) {
|
||||
case UpdatePositionEvent::POSITION_ABSOLUTE:
|
||||
$folder->changeAbsolutePosition($event->getPosition());
|
||||
break;
|
||||
case UpdatePositionEvent::POSITION_DOWN:
|
||||
$folder->movePositionDown();
|
||||
break;
|
||||
case UpdatePositionEvent::POSITION_UP:
|
||||
$folder->movePositionUp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::FOLDER_CREATE => array("create", 128),
|
||||
TheliaEvents::FOLDER_UPDATE => array("update", 128),
|
||||
TheliaEvents::FOLDER_DELETE => array("delete", 128),
|
||||
TheliaEvents::FOLDER_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
|
||||
TheliaEvents::FOLDER_UPDATE_POSITION => array("updatePosition", 128),
|
||||
TheliaEvents::FOLDER_UPDATE_SEO => array('updateSeo', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
168
core/lib/Thelia/Action/Hook.php
Normal file
168
core/lib/Thelia/Action/Hook.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\Hook\HookCreateAllEvent;
|
||||
use Thelia\Core\Event\Hook\HookCreateEvent;
|
||||
use Thelia\Core\Event\Hook\HookDeactivationEvent;
|
||||
use Thelia\Core\Event\Hook\HookDeleteEvent;
|
||||
use Thelia\Core\Event\Hook\HookToggleActivationEvent;
|
||||
use Thelia\Core\Event\Hook\HookToggleNativeEvent;
|
||||
use Thelia\Core\Event\Hook\HookUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Hook as HookModel;
|
||||
use Thelia\Model\HookQuery;
|
||||
|
||||
/**
|
||||
* Class HookAction
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class Hook extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $cacheDir;
|
||||
|
||||
public function __construct($cacheDir)
|
||||
{
|
||||
$this->cacheDir = $cacheDir;
|
||||
}
|
||||
|
||||
public function create(HookCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$hook = new HookModel();
|
||||
|
||||
$hook
|
||||
->setLocale($event->getLocale())
|
||||
->setCode($event->getCode())
|
||||
->setType($event->getType())
|
||||
->setNative($event->getNative())
|
||||
->setActivate($event->getActive())
|
||||
->setTitle($event->getTitle())
|
||||
->save();
|
||||
|
||||
$event->setHook($hook);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
|
||||
public function update(HookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) {
|
||||
$hook
|
||||
->setLocale($event->getLocale())
|
||||
->setCode($event->getCode())
|
||||
->setType($event->getType())
|
||||
->setNative($event->getNative())
|
||||
->setActivate($event->getActive())
|
||||
->setBlock($event->getBlock())
|
||||
->setByModule($event->getByModule())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->save();
|
||||
|
||||
$event->setHook($hook);
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(HookDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) {
|
||||
$hook->delete();
|
||||
$event->setHook($hook);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function createAll(HookCreateAllEvent $event)
|
||||
{
|
||||
$hook = new HookModel();
|
||||
|
||||
$hook
|
||||
->setLocale($event->getLocale())
|
||||
->setCode($event->getCode())
|
||||
->setType($event->getType())
|
||||
->setNative($event->getNative())
|
||||
->setActivate($event->getActive())
|
||||
->setBlock($event->getBlock())
|
||||
->setByModule($event->getByModule())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->save();
|
||||
|
||||
$event->setHook($hook);
|
||||
}
|
||||
|
||||
public function deactivation(HookDeactivationEvent $event)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) {
|
||||
$hook
|
||||
->setActivate(false)
|
||||
->save();
|
||||
$event->setHook($hook);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleNative(HookToggleNativeEvent $event)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) {
|
||||
$hook
|
||||
->setNative(!$hook->getNative())
|
||||
->save();
|
||||
$event->setHook($hook);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleActivation(HookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) {
|
||||
$hook
|
||||
->setActivate(!$hook->getActivate())
|
||||
->save();
|
||||
$event->setHook($hook);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
protected function cacheClear(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cacheEvent = new CacheEvent($this->cacheDir);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::HOOK_CREATE => array('create', 128),
|
||||
TheliaEvents::HOOK_UPDATE => array('update', 128),
|
||||
TheliaEvents::HOOK_DELETE => array('delete', 128),
|
||||
TheliaEvents::HOOK_TOGGLE_ACTIVATION => array('toggleActivation', 128),
|
||||
TheliaEvents::HOOK_TOGGLE_NATIVE => array('toggleNative', 128),
|
||||
TheliaEvents::HOOK_CREATE_ALL => array('createAll', 128),
|
||||
TheliaEvents::HOOK_DEACTIVATION => array('deactivation', 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
114
core/lib/Thelia/Action/HttpException.php
Normal file
114
core/lib/Thelia/Action/HttpException.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException as BaseHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Thelia\Core\HttpFoundation\Response;
|
||||
use Thelia\Core\Template\ParserInterface;
|
||||
use Thelia\Exception\AdminAccessDenied;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class HttpException
|
||||
* @package Thelia\Action
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class HttpException extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var ParserInterface */
|
||||
protected $parser;
|
||||
|
||||
public function __construct(ParserInterface $parser)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
public function checkHttpException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
$exception = $event->getException();
|
||||
if ($exception instanceof NotFoundHttpException) {
|
||||
$this->display404($event);
|
||||
}
|
||||
|
||||
if ($exception instanceof AdminAccessDenied) {
|
||||
$this->displayAdminGeneralError($event);
|
||||
}
|
||||
|
||||
if ($exception instanceof BaseHttpException && null === $event->getResponse()) {
|
||||
$this->displayException($event);
|
||||
}
|
||||
}
|
||||
|
||||
protected function displayAdminGeneralError(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
// Define the template thant shoud be used
|
||||
$this->parser->setTemplateDefinition(
|
||||
$this->parser->getTemplateHelper()->getActiveAdminTemplate()
|
||||
);
|
||||
|
||||
$message = $event->getException()->getMessage();
|
||||
|
||||
$response = Response::create(
|
||||
$this->parser->render(
|
||||
'general_error.html',
|
||||
array(
|
||||
"error_message" => $message
|
||||
)
|
||||
),
|
||||
403
|
||||
);
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
||||
protected function display404(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
// Define the template thant shoud be used
|
||||
$this->parser->setTemplateDefinition(
|
||||
$this->parser->getTemplateHelper()->getActiveFrontTemplate()
|
||||
);
|
||||
|
||||
$response = new Response($this->parser->render(ConfigQuery::getPageNotFoundView()), 404);
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
||||
protected function displayException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
/** @var \Symfony\Component\HttpKernel\Exception\HttpException $exception */
|
||||
$exception = $event->getException();
|
||||
$event->setResponse(
|
||||
new Response(
|
||||
$exception->getMessage(),
|
||||
$exception->getStatusCode(),
|
||||
$exception->getHeaders()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::EXCEPTION => ["checkHttpException", 128],
|
||||
);
|
||||
}
|
||||
}
|
||||
416
core/lib/Thelia/Action/Image.php
Normal file
416
core/lib/Thelia/Action/Image.php
Normal file
@@ -0,0 +1,416 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Imagine\Image\Box;
|
||||
use Imagine\Image\ImageInterface;
|
||||
use Imagine\Image\ImagineInterface;
|
||||
use Imagine\Image\Palette\RGB;
|
||||
use Imagine\Image\Point;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Image\ImageEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Exception\ImageException;
|
||||
use Thelia\Files\FileManager;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Tools\URL;
|
||||
use Imagine\Imagick\Imagine as ImagickImagine;
|
||||
use Imagine\Gmagick\Imagine as GmagickImagine;
|
||||
use Imagine\Gd\Imagine;
|
||||
|
||||
/**
|
||||
*
|
||||
* Image management actions. This class handles image processing and caching.
|
||||
*
|
||||
* Basically, images are stored outside of the web space (by default in local/media/images),
|
||||
* and cached inside the web space (by default in web/local/images).
|
||||
*
|
||||
* In the images caches directory, a subdirectory for images categories (eg. product, category, folder, etc.) is
|
||||
* automatically created, and the cached image is created here. Plugin may use their own subdirectory as required.
|
||||
*
|
||||
* The cached image name contains a hash of the processing options, and the original (normalized) name of the image.
|
||||
*
|
||||
* A copy (or symbolic link, by default) of the original image is always created in the cache, so that the full
|
||||
* resolution image is always available.
|
||||
*
|
||||
* Various image processing options are available :
|
||||
*
|
||||
* - resizing, with border, crop, or by keeping image aspect ratio
|
||||
* - rotation, in degrees, positive or negative
|
||||
* - background color, applyed to empty background when creating borders or rotating
|
||||
* - effects. The effects are applied in the specified order. The following effects are available:
|
||||
* - gamma:value : change the image Gamma to the specified value. Example: gamma:0.7
|
||||
* - grayscale or greyscale: switch image to grayscale
|
||||
* - colorize:color : apply a color mask to the image. Exemple: colorize:#ff2244
|
||||
* - negative : transform the image in its negative equivalent
|
||||
* - vflip or vertical_flip : vertical flip
|
||||
* - hflip or horizontal_flip : horizontal flip
|
||||
*
|
||||
* If a problem occurs, an ImageException may be thrown.
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class Image extends BaseCachedFile implements EventSubscriberInterface
|
||||
{
|
||||
// Resize mode constants
|
||||
const EXACT_RATIO_WITH_BORDERS = 1;
|
||||
const EXACT_RATIO_WITH_CROP = 2;
|
||||
const KEEP_IMAGE_RATIO = 3;
|
||||
|
||||
/**
|
||||
* @return string root of the image cache directory in web space
|
||||
*/
|
||||
protected function getCacheDirFromWebRoot()
|
||||
{
|
||||
return ConfigQuery::read('image_cache_dir_from_web_root', 'cache' . DS . 'images');
|
||||
}
|
||||
|
||||
/**
|
||||
* Process image and write the result in the image cache.
|
||||
*
|
||||
* If the image already exists in cache, the cache file is immediately returned, without any processing
|
||||
* If the original (full resolution) image is required, create either a symbolic link with the
|
||||
* original image in the cache dir, or copy it in the cache dir.
|
||||
*
|
||||
* This method updates the cache_file_path and file_url attributes of the event
|
||||
*
|
||||
* @param ImageEvent $event
|
||||
* @param string $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @throws \Thelia\Exception\ImageException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function processImage(ImageEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$subdir = $event->getCacheSubdirectory();
|
||||
$source_file = $event->getSourceFilepath();
|
||||
|
||||
if (null == $subdir || null == $source_file) {
|
||||
throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null");
|
||||
}
|
||||
|
||||
// Find cached file path
|
||||
$cacheFilePath = $this->getCacheFilePath($subdir, $source_file, $event->isOriginalImage(), $event->getOptionsHash());
|
||||
|
||||
$originalImagePathInCache = $this->getCacheFilePath($subdir, $source_file, true);
|
||||
|
||||
if (! file_exists($cacheFilePath)) {
|
||||
if (! file_exists($source_file)) {
|
||||
throw new ImageException(sprintf("Source image file %s does not exists.", $source_file));
|
||||
}
|
||||
|
||||
// Create a cached version of the original image in the web space, if not exists
|
||||
|
||||
if (! file_exists($originalImagePathInCache)) {
|
||||
$mode = ConfigQuery::read('original_image_delivery_mode', 'symlink');
|
||||
|
||||
if ($mode == 'symlink') {
|
||||
if (false === symlink($source_file, $originalImagePathInCache)) {
|
||||
throw new ImageException(sprintf("Failed to create symbolic link for %s in %s image cache directory", basename($source_file), $subdir));
|
||||
}
|
||||
} else {
|
||||
// mode = 'copy'
|
||||
if (false === @copy($source_file, $originalImagePathInCache)) {
|
||||
throw new ImageException(sprintf("Failed to copy %s in %s image cache directory", basename($source_file), $subdir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process image only if we have some transformations to do.
|
||||
if (! $event->isOriginalImage()) {
|
||||
// We have to process the image.
|
||||
$imagine = $this->createImagineInstance();
|
||||
|
||||
$image = $imagine->open($source_file);
|
||||
|
||||
if ($image) {
|
||||
// Allow image pre-processing (watermarging, or other stuff...)
|
||||
$event->setImageObject($image);
|
||||
$dispatcher->dispatch(TheliaEvents::IMAGE_PREPROCESSING, $event);
|
||||
$image = $event->getImageObject();
|
||||
|
||||
$background_color = $event->getBackgroundColor();
|
||||
|
||||
$palette = new RGB();
|
||||
|
||||
if ($background_color != null) {
|
||||
$bg_color = $palette->color($background_color);
|
||||
} else {
|
||||
// Define a fully transparent white background color
|
||||
$bg_color = $palette->color('fff', 0);
|
||||
}
|
||||
|
||||
// Apply resize
|
||||
$image = $this->applyResize(
|
||||
$imagine,
|
||||
$image,
|
||||
$event->getWidth(),
|
||||
$event->getHeight(),
|
||||
$event->getResizeMode(),
|
||||
$bg_color,
|
||||
$event->getAllowZoom()
|
||||
);
|
||||
|
||||
// Rotate if required
|
||||
$rotation = intval($event->getRotation());
|
||||
|
||||
if ($rotation != 0) {
|
||||
$image->rotate($rotation, $bg_color);
|
||||
}
|
||||
|
||||
// Flip
|
||||
// Process each effects
|
||||
foreach ($event->getEffects() as $effect) {
|
||||
$effect = trim(strtolower($effect));
|
||||
|
||||
$params = explode(':', $effect);
|
||||
|
||||
switch ($params[0]) {
|
||||
|
||||
case 'greyscale':
|
||||
case 'grayscale':
|
||||
$image->effects()->grayscale();
|
||||
break;
|
||||
|
||||
case 'negative':
|
||||
$image->effects()->negative();
|
||||
break;
|
||||
|
||||
case 'horizontal_flip':
|
||||
case 'hflip':
|
||||
$image->flipHorizontally();
|
||||
break;
|
||||
|
||||
case 'vertical_flip':
|
||||
case 'vflip':
|
||||
$image->flipVertically();
|
||||
break;
|
||||
|
||||
case 'gamma':
|
||||
// Syntax: gamma:value. Exemple: gamma:0.7
|
||||
if (isset($params[1])) {
|
||||
$gamma = floatval($params[1]);
|
||||
|
||||
$image->effects()->gamma($gamma);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'colorize':
|
||||
// Syntax: colorize:couleur. Exemple: colorize:#ff00cc
|
||||
if (isset($params[1])) {
|
||||
$the_color = $palette->color($params[1]);
|
||||
|
||||
$image->effects()->colorize($the_color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$quality = $event->getQuality();
|
||||
|
||||
if (is_null($quality)) {
|
||||
$quality = ConfigQuery::read('default_images_quality_percent', 75);
|
||||
}
|
||||
|
||||
// Allow image post-processing (watermarging, or other stuff...)
|
||||
$event->setImageObject($image);
|
||||
$dispatcher->dispatch(TheliaEvents::IMAGE_POSTPROCESSING, $event);
|
||||
$image = $event->getImageObject();
|
||||
|
||||
$image->save(
|
||||
$cacheFilePath,
|
||||
array('quality' => $quality)
|
||||
);
|
||||
} else {
|
||||
throw new ImageException(sprintf("Source file %s cannot be opened.", basename($source_file)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the image URL
|
||||
$processed_image_url = $this->getCacheFileURL($subdir, basename($cacheFilePath));
|
||||
|
||||
// compute the full resolution image path in cache
|
||||
$original_image_url = $this->getCacheFileURL($subdir, basename($originalImagePathInCache));
|
||||
|
||||
// Update the event with file path and file URL
|
||||
$event->setCacheFilepath($cacheFilePath);
|
||||
$event->setCacheOriginalFilepath($originalImagePathInCache);
|
||||
|
||||
$event->setFileUrl(URL::getInstance()->absoluteUrl($processed_image_url, null, URL::PATH_TO_FILE));
|
||||
$event->setOriginalFileUrl(URL::getInstance()->absoluteUrl($original_image_url, null, URL::PATH_TO_FILE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process image resizing, with borders or cropping. If $dest_width and $dest_height
|
||||
* are both null, no resize is performed.
|
||||
*
|
||||
* @param ImagineInterface $imagine the Imagine instance
|
||||
* @param ImageInterface $image the image to process
|
||||
* @param int $dest_width the required width
|
||||
* @param int $dest_height the required height
|
||||
* @param int $resize_mode the resize mode (crop / bands / keep image ratio)p
|
||||
* @param string $bg_color the bg_color used for bands
|
||||
* @param bool $allow_zoom if true, image may be zoomed to matchrequired size. If false, image is not zoomed.
|
||||
* @return ImageInterface the resized image.
|
||||
*/
|
||||
protected function applyResize(
|
||||
ImagineInterface $imagine,
|
||||
ImageInterface $image,
|
||||
$dest_width,
|
||||
$dest_height,
|
||||
$resize_mode,
|
||||
$bg_color,
|
||||
$allow_zoom = false
|
||||
) {
|
||||
if (! (is_null($dest_width) && is_null($dest_height))) {
|
||||
$width_orig = $image->getSize()->getWidth();
|
||||
$height_orig = $image->getSize()->getHeight();
|
||||
|
||||
$ratio = $width_orig / $height_orig;
|
||||
|
||||
if (is_null($dest_width)) {
|
||||
$dest_width = $dest_height * $ratio;
|
||||
}
|
||||
|
||||
if (is_null($dest_height)) {
|
||||
$dest_height = $dest_width / $ratio;
|
||||
}
|
||||
|
||||
if (is_null($resize_mode)) {
|
||||
$resize_mode = self::KEEP_IMAGE_RATIO;
|
||||
}
|
||||
|
||||
$width_diff = $dest_width / $width_orig;
|
||||
$height_diff = $dest_height / $height_orig;
|
||||
|
||||
$delta_x = $delta_y = $border_width = $border_height = 0;
|
||||
|
||||
if ($width_diff > 1 && $height_diff > 1) {
|
||||
$resize_width = $width_orig;
|
||||
$resize_height = $height_orig;
|
||||
|
||||
// When cropping, be sure to always generate an image which is
|
||||
// no smaller than the required size, zooming it if required.
|
||||
if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
||||
if ($allow_zoom) {
|
||||
if ($width_diff > $height_diff) {
|
||||
$resize_width = $dest_width;
|
||||
$resize_height = intval($height_orig * $dest_width / $width_orig);
|
||||
$delta_y = ($resize_height - $dest_height) / 2;
|
||||
} else {
|
||||
$resize_height = $dest_height;
|
||||
$resize_width = intval(($width_orig * $resize_height) / $height_orig);
|
||||
$delta_x = ($resize_width - $dest_width) / 2;
|
||||
}
|
||||
} else {
|
||||
// No zoom : final image may be smaller than the required size.
|
||||
$dest_width = $resize_width;
|
||||
$dest_height = $resize_height;
|
||||
}
|
||||
}
|
||||
} elseif ($width_diff > $height_diff) {
|
||||
// Image height > image width
|
||||
$resize_height = $dest_height;
|
||||
$resize_width = intval(($width_orig * $resize_height) / $height_orig);
|
||||
|
||||
if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
||||
$resize_width = $dest_width;
|
||||
$resize_height = intval($height_orig * $dest_width / $width_orig);
|
||||
$delta_y = ($resize_height - $dest_height) / 2;
|
||||
} elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
|
||||
$dest_width = $resize_width;
|
||||
}
|
||||
} else {
|
||||
// Image width > image height
|
||||
$resize_width = $dest_width;
|
||||
$resize_height = intval($height_orig * $dest_width / $width_orig);
|
||||
|
||||
if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
||||
$resize_height = $dest_height;
|
||||
$resize_width = intval(($width_orig * $resize_height) / $height_orig);
|
||||
$delta_x = ($resize_width - $dest_width) / 2;
|
||||
} elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
|
||||
$dest_height = $resize_height;
|
||||
}
|
||||
}
|
||||
|
||||
$image->resize(new Box($resize_width, $resize_height));
|
||||
|
||||
if ($resize_mode == self::EXACT_RATIO_WITH_BORDERS) {
|
||||
$border_width = intval(($dest_width - $resize_width) / 2);
|
||||
$border_height = intval(($dest_height - $resize_height) / 2);
|
||||
|
||||
$canvas = new Box($dest_width, $dest_height);
|
||||
|
||||
return $imagine->create($canvas, $bg_color)
|
||||
->paste($image, new Point($border_width, $border_height));
|
||||
} elseif ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
||||
$image->crop(
|
||||
new Point($delta_x, $delta_y),
|
||||
new Box($dest_width, $dest_height)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Imagine object using current driver configuration
|
||||
*
|
||||
* @return ImagineInterface
|
||||
*/
|
||||
protected function createImagineInstance()
|
||||
{
|
||||
$driver = ConfigQuery::read("imagine_graphic_driver", "gd");
|
||||
|
||||
switch ($driver) {
|
||||
case 'imagick':
|
||||
$image = new ImagickImagine();
|
||||
break;
|
||||
|
||||
case 'gmagick':
|
||||
$image = new GmagickImagine();
|
||||
break;
|
||||
|
||||
case 'gd':
|
||||
default:
|
||||
$image = new Imagine();
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::IMAGE_PROCESS => array("processImage", 128),
|
||||
|
||||
// Implemented in parent class BaseCachedFile
|
||||
TheliaEvents::IMAGE_CLEAR_CACHE => array("clearCache", 128),
|
||||
TheliaEvents::IMAGE_DELETE => array("deleteFile", 128),
|
||||
TheliaEvents::IMAGE_SAVE => array("saveFile", 128),
|
||||
TheliaEvents::IMAGE_UPDATE => array("updateFile", 128),
|
||||
TheliaEvents::IMAGE_UPDATE_POSITION => array("updatePosition", 128),
|
||||
TheliaEvents::IMAGE_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
79
core/lib/Thelia/Action/Import.php
Normal file
79
core/lib/Thelia/Action/Import.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Handler\ImportHandler;
|
||||
use Thelia\Model\ImportCategoryQuery;
|
||||
use Thelia\Model\ImportQuery;
|
||||
|
||||
/**
|
||||
* Class Import
|
||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||
*/
|
||||
class Import extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var \Thelia\Handler\ImportHandler The import handler
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* @param \Thelia\Handler\ImportHandler $importHandler The import handler
|
||||
*/
|
||||
public function __construct(ImportHandler $importHandler)
|
||||
{
|
||||
$this->handler = $importHandler;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::IMPORT_CHANGE_POSITION => [
|
||||
['importChangePosition', 128]
|
||||
],
|
||||
TheliaEvents::IMPORT_CATEGORY_CHANGE_POSITION => [
|
||||
['importCategoryChangePosition', 128]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle import change position event
|
||||
*
|
||||
* @param UpdatePositionEvent $updatePositionEvent
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function importChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->handler->getImport($updatePositionEvent->getObjectId(), true);
|
||||
$this->genericUpdatePosition(new ImportQuery, $updatePositionEvent, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle import category change position event
|
||||
*
|
||||
* @param UpdatePositionEvent $updatePositionEvent
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function importCategoryChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->handler->getCategory($updatePositionEvent->getObjectId(), true);
|
||||
$this->genericUpdatePosition(new ImportCategoryQuery, $updatePositionEvent, $dispatcher);
|
||||
}
|
||||
}
|
||||
238
core/lib/Thelia/Action/Lang.php
Normal file
238
core/lib/Thelia/Action/Lang.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Thelia\Core\Event\Lang\LangCreateEvent;
|
||||
use Thelia\Core\Event\Lang\LangDefaultBehaviorEvent;
|
||||
use Thelia\Core\Event\Lang\LangDeleteEvent;
|
||||
use Thelia\Core\Event\Lang\LangEvent;
|
||||
use Thelia\Core\Event\Lang\LangToggleActiveEvent;
|
||||
use Thelia\Core\Event\Lang\LangToggleDefaultEvent;
|
||||
use Thelia\Core\Event\Lang\LangToggleVisibleEvent;
|
||||
use Thelia\Core\Event\Lang\LangUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\HttpFoundation\Session\Session;
|
||||
use Thelia\Core\Template\TemplateHelperInterface;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Form\Lang\LangUrlEvent;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\LangQuery;
|
||||
use Thelia\Model\Lang as LangModel;
|
||||
|
||||
/**
|
||||
* Class Lang
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Lang extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var TemplateHelperInterface */
|
||||
protected $templateHelper;
|
||||
|
||||
/** @var RequestStack */
|
||||
protected $requestStack;
|
||||
|
||||
public function __construct(TemplateHelperInterface $templateHelper, RequestStack $requestStack)
|
||||
{
|
||||
$this->templateHelper = $templateHelper;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function update(LangUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $lang = LangQuery::create()->findPk($event->getId())) {
|
||||
$lang->setDispatcher($dispatcher);
|
||||
|
||||
$lang->setTitle($event->getTitle())
|
||||
->setLocale($event->getLocale())
|
||||
->setCode($event->getCode())
|
||||
->setDateTimeFormat($event->getDateTimeFormat())
|
||||
->setDateFormat($event->getDateFormat())
|
||||
->setTimeFormat($event->getTimeFormat())
|
||||
->setDecimalSeparator($event->getDecimalSeparator())
|
||||
->setThousandsSeparator($event->getThousandsSeparator())
|
||||
->setDecimals($event->getDecimals())
|
||||
->save();
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleDefault(LangToggleDefaultEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) {
|
||||
$lang->setDispatcher($dispatcher);
|
||||
|
||||
$lang->toggleDefault();
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleActive(LangToggleActiveEvent $event)
|
||||
{
|
||||
if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) {
|
||||
if ($lang->getByDefault()) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans('Cannot disable the default language')
|
||||
);
|
||||
}
|
||||
|
||||
$lang->setActive($lang->getActive() ? 0 : 1);
|
||||
|
||||
if (!$lang->getActive()) {
|
||||
$lang->setVisible(0);
|
||||
}
|
||||
|
||||
$lang->save();
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleVisible(LangToggleVisibleEvent $event)
|
||||
{
|
||||
if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) {
|
||||
if ($lang->getByDefault()) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans('Cannot hide the default language')
|
||||
);
|
||||
}
|
||||
|
||||
$lang->setVisible($lang->getVisible() ? 0 : 1);
|
||||
|
||||
if (!$lang->getActive() && $lang->getVisible()) {
|
||||
$lang->setActive(1);
|
||||
}
|
||||
|
||||
$lang->save();
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
}
|
||||
|
||||
public function create(LangCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$lang = new LangModel();
|
||||
|
||||
$lang
|
||||
->setDispatcher($dispatcher)
|
||||
->setTitle($event->getTitle())
|
||||
->setCode($event->getCode())
|
||||
->setLocale($event->getLocale())
|
||||
->setDateTimeFormat($event->getDateTimeFormat())
|
||||
->setDateFormat($event->getDateFormat())
|
||||
->setTimeFormat($event->getTimeFormat())
|
||||
->setDecimalSeparator($event->getDecimalSeparator())
|
||||
->setThousandsSeparator($event->getThousandsSeparator())
|
||||
->setDecimals($event->getDecimals())
|
||||
->save();
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
|
||||
public function delete(LangDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) {
|
||||
if ($lang->getByDefault()) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans('It is not allowed to delete the default language')
|
||||
);
|
||||
}
|
||||
|
||||
$lang->setDispatcher($dispatcher)
|
||||
->delete();
|
||||
|
||||
/** @var Session $session */
|
||||
$session = $this->requestStack->getCurrentRequest()->getSession();
|
||||
|
||||
// If we've just deleted the current admin edition language, set it to the default one.
|
||||
if ($lang->getId() == $session->getAdminEditionLang()->getId()) {
|
||||
$session->setAdminEditionLang(LangModel::getDefaultLanguage());
|
||||
}
|
||||
|
||||
// If we've just deleted the current admin language, set it to the default one.
|
||||
if ($lang->getId() == $session->getLang()->getId()) {
|
||||
$session->setLang(LangModel::getDefaultLanguage());
|
||||
}
|
||||
|
||||
$event->setLang($lang);
|
||||
}
|
||||
}
|
||||
|
||||
public function defaultBehavior(LangDefaultBehaviorEvent $event)
|
||||
{
|
||||
ConfigQuery::create()
|
||||
->filterByName('default_lang_without_translation')
|
||||
->update(array('Value' => $event->getDefaultBehavior()));
|
||||
}
|
||||
|
||||
public function langUrl(LangUrlEvent $event)
|
||||
{
|
||||
foreach ($event->getUrl() as $id => $url) {
|
||||
LangQuery::create()
|
||||
->filterById($id)
|
||||
->update(array('Url' => $url));
|
||||
}
|
||||
}
|
||||
|
||||
public function fixMissingFlag(LangEvent $event)
|
||||
{
|
||||
// Be sure that a lang have a flag, otherwise copy the
|
||||
// "unknown" flag
|
||||
$adminTemplate = $this->templateHelper->getActiveAdminTemplate();
|
||||
$unknownFlag = ConfigQuery::getUnknownFlagPath();
|
||||
|
||||
$unknownFlagPath = $adminTemplate->getAbsolutePath().DS.$unknownFlag;
|
||||
|
||||
if (! file_exists($unknownFlagPath)) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans(
|
||||
"The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.",
|
||||
array("%file" => $unknownFlag)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the country flag exists
|
||||
$countryFlag = rtrim(dirname($unknownFlagPath), DS).DS.$event->getLang()->getCode().'.png';
|
||||
|
||||
if (! file_exists($countryFlag)) {
|
||||
$fs = new Filesystem();
|
||||
|
||||
$fs->copy($unknownFlagPath, $countryFlag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::LANG_UPDATE => array('update', 128),
|
||||
TheliaEvents::LANG_TOGGLEDEFAULT => array('toggleDefault', 128),
|
||||
TheliaEvents::LANG_TOGGLEACTIVE => array('toggleActive', 128),
|
||||
TheliaEvents::LANG_TOGGLEVISIBLE => array('toggleVisible', 128),
|
||||
TheliaEvents::LANG_CREATE => array('create', 128),
|
||||
TheliaEvents::LANG_DELETE => array('delete', 128),
|
||||
TheliaEvents::LANG_DEFAULTBEHAVIOR => array('defaultBehavior', 128),
|
||||
TheliaEvents::LANG_URL => array('langUrl', 128),
|
||||
TheliaEvents::LANG_FIX_MISSING_FLAG => array('fixMissingFlag', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
51
core/lib/Thelia/Action/MailingSystem.php
Normal file
51
core/lib/Thelia/Action/MailingSystem.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\MailingSystem\MailingSystemEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
class MailingSystem extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @param MailingSystemEvent $event
|
||||
*/
|
||||
public function update(MailingSystemEvent $event)
|
||||
{
|
||||
if ($event->getEnabled()) {
|
||||
ConfigQuery::enableSmtp();
|
||||
} else {
|
||||
ConfigQuery::disableSmtp();
|
||||
}
|
||||
ConfigQuery::setSmtpHost($event->getHost());
|
||||
ConfigQuery::setSmtpPort($event->getPort());
|
||||
ConfigQuery::setSmtpEncryption($event->getEncryption());
|
||||
ConfigQuery::setSmtpUsername($event->getUsername());
|
||||
ConfigQuery::setSmtpPassword($event->getPassword());
|
||||
ConfigQuery::setSmtpAuthMode($event->getAuthMode());
|
||||
ConfigQuery::setSmtpTimeout($event->getTimeout());
|
||||
ConfigQuery::setSmtpSourceIp($event->getSourceIp());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::MAILING_SYSTEM_UPDATE => array("update", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
116
core/lib/Thelia/Action/Message.php
Normal file
116
core/lib/Thelia/Action/Message.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\MessageQuery;
|
||||
use Thelia\Model\Message as MessageModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Message\MessageUpdateEvent;
|
||||
use Thelia\Core\Event\Message\MessageCreateEvent;
|
||||
use Thelia\Core\Event\Message\MessageDeleteEvent;
|
||||
|
||||
class Message extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new messageuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Message\MessageCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(MessageCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$message = new MessageModel();
|
||||
|
||||
$message
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setName($event->getMessageName())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setSecured($event->getSecured())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setMessage($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a message
|
||||
*
|
||||
* @param \Thelia\Core\Event\Message\MessageUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function modify(MessageUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $message = MessageQuery::create()->findPk($event->getMessageId())) {
|
||||
$message
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setName($event->getMessageName())
|
||||
->setSecured($event->getSecured())
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
|
||||
->setTitle($event->getTitle())
|
||||
->setSubject($event->getSubject())
|
||||
|
||||
->setHtmlMessage($event->getHtmlMessage())
|
||||
->setTextMessage($event->getTextMessage())
|
||||
|
||||
->setHtmlLayoutFileName($event->getHtmlLayoutFileName())
|
||||
->setHtmlTemplateFileName($event->getHtmlTemplateFileName())
|
||||
->setTextLayoutFileName($event->getTextLayoutFileName())
|
||||
->setTextTemplateFileName($event->getTextTemplateFileName())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setMessage($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a messageuration entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Message\MessageDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function delete(MessageDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($message = MessageQuery::create()->findPk($event->getMessageId()))) {
|
||||
$message
|
||||
->setDispatcher($dispatcher)
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setMessage($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::MESSAGE_CREATE => array("create", 128),
|
||||
TheliaEvents::MESSAGE_UPDATE => array("modify", 128),
|
||||
TheliaEvents::MESSAGE_DELETE => array("delete", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
75
core/lib/Thelia/Action/MetaData.php
Normal file
75
core/lib/Thelia/Action/MetaData.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\MetaData\MetaDataCreateOrUpdateEvent;
|
||||
use Thelia\Core\Event\MetaData\MetaDataDeleteEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\MetaData as MetaDataModel;
|
||||
use Thelia\Model\MetaDataQuery;
|
||||
|
||||
/**
|
||||
* Class MetaData
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class MetaData extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function createOrUpdate(MetaDataCreateOrUpdateEvent $event)
|
||||
{
|
||||
$metaData = MetaDataQuery::create()
|
||||
->filterByMetaKey($event->getMetaKey())
|
||||
->filterByElementKey($event->getElementKey())
|
||||
->filterByElementId($event->getElementId())
|
||||
->findOne();
|
||||
|
||||
if (null === $metaData) {
|
||||
$metaData = new MetaDataModel();
|
||||
$metaData
|
||||
->setMetaKey($event->getMetaKey())
|
||||
->setElementKey($event->getElementkey())
|
||||
->setElementId($event->getElementId());
|
||||
}
|
||||
$metaData->
|
||||
setValue($event->getValue());
|
||||
$metaData->save();
|
||||
|
||||
$event->setMetaData($metaData);
|
||||
}
|
||||
|
||||
public function delete(MetaDataDeleteEvent $event)
|
||||
{
|
||||
$metaData = MetaDataQuery::create()
|
||||
->filterByMetaKey($event->getMetaKey())
|
||||
->filterByElementKey($event->getElementKey())
|
||||
->filterByElementId($event->getElementId())
|
||||
->findOne();
|
||||
$event->setMetaData($metaData);
|
||||
if (null !== $metaData) {
|
||||
$metaData->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::META_DATA_CREATE => array('createOrUpdate', 128),
|
||||
TheliaEvents::META_DATA_UPDATE => array('createOrUpdate', 128),
|
||||
TheliaEvents::META_DATA_DELETE => array('delete', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
456
core/lib/Thelia/Action/Module.php
Normal file
456
core/lib/Thelia/Action/Module.php
Normal file
@@ -0,0 +1,456 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Exception;
|
||||
use Propel\Runtime\Propel;
|
||||
use SplFileInfo;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\Module\ModuleDeleteEvent;
|
||||
use Thelia\Core\Event\Module\ModuleEvent;
|
||||
use Thelia\Core\Event\Module\ModuleInstallEvent;
|
||||
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
||||
use Thelia\Core\Event\Order\OrderPaymentEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Exception\FileNotFoundException;
|
||||
use Thelia\Exception\ModuleException;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\Base\OrderQuery;
|
||||
use Thelia\Model\Map\ModuleTableMap;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
use Thelia\Module\ModuleManagement;
|
||||
use Thelia\Module\Validator\ModuleValidator;
|
||||
|
||||
/**
|
||||
* Class Module
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Module extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var ContainerInterface */
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function toggleActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||
$moduleInstance = $module->createInstance();
|
||||
|
||||
if (method_exists($moduleInstance, 'setContainer')) {
|
||||
$moduleInstance->setContainer($this->container);
|
||||
if ($module->getActivate() == BaseModule::IS_ACTIVATED) {
|
||||
$moduleInstance->deActivate($module);
|
||||
} else {
|
||||
$moduleInstance->activate($module);
|
||||
}
|
||||
}
|
||||
|
||||
$event->setModule($module);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkToggleActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (true === $event->isNoCheck()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||
try {
|
||||
if ($module->getActivate() == BaseModule::IS_ACTIVATED) {
|
||||
if ($event->isRecursive()) {
|
||||
$this->recursiveDeactivation($event, $eventName, $dispatcher);
|
||||
}
|
||||
$this->checkDeactivation($module);
|
||||
} else {
|
||||
if ($event->isRecursive()) {
|
||||
$this->recursiveActivation($event, $eventName, $dispatcher);
|
||||
}
|
||||
$this->checkActivation($module);
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$event->stopPropagation();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if module can be activated : supported version of Thelia, module dependencies.
|
||||
*
|
||||
* @param \Thelia\Model\Module $module
|
||||
* @throws Exception if activation fails.
|
||||
* @return bool true if the module can be activated, otherwise false
|
||||
*/
|
||||
private function checkActivation($module)
|
||||
{
|
||||
try {
|
||||
$moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir());
|
||||
$moduleValidator->validate(false);
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if module can be deactivated safely because other modules
|
||||
* could have dependencies to this module
|
||||
*
|
||||
* @param \Thelia\Model\Module $module
|
||||
* @return bool true if the module can be deactivated, otherwise false
|
||||
*/
|
||||
private function checkDeactivation($module)
|
||||
{
|
||||
$moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir());
|
||||
|
||||
$modules = $moduleValidator->getModulesDependOf();
|
||||
|
||||
if (count($modules) > 0) {
|
||||
$moduleList = implode(', ', array_column($modules, 'code'));
|
||||
|
||||
$message = (count($modules) == 1)
|
||||
? Translator::getInstance()->trans(
|
||||
'%s has dependency to module %s. You have to deactivate this module before.'
|
||||
)
|
||||
: Translator::getInstance()->trans(
|
||||
'%s have dependencies to module %s. You have to deactivate these modules before.'
|
||||
);
|
||||
|
||||
throw new ModuleException(
|
||||
sprintf($message, $moduleList, $moduleValidator->getModuleDefinition()->getCode())
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get dependencies of the current module and activate it if needed
|
||||
*
|
||||
* @param ModuleToggleActivationEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function recursiveActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||
$moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir());
|
||||
$dependencies = $moduleValidator->getCurrentModuleDependencies();
|
||||
foreach ($dependencies as $defMod) {
|
||||
$submodule = ModuleQuery::create()
|
||||
->findOneByCode($defMod["code"]);
|
||||
if ($submodule && $submodule->getActivate() != BaseModule::IS_ACTIVATED) {
|
||||
$subevent = new ModuleToggleActivationEvent($submodule->getId());
|
||||
$subevent->setRecursive(true);
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $subevent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get modules having current module in dependence and deactivate it if needed
|
||||
*
|
||||
* @param ModuleToggleActivationEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function recursiveDeactivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||
$moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir());
|
||||
$dependencies = $moduleValidator->getModulesDependOf(true);
|
||||
foreach ($dependencies as $defMod) {
|
||||
$submodule = ModuleQuery::create()
|
||||
->findOneByCode($defMod["code"]);
|
||||
if ($submodule && $submodule->getActivate() == BaseModule::IS_ACTIVATED) {
|
||||
$subevent = new ModuleToggleActivationEvent($submodule->getId());
|
||||
$subevent->setRecursive(true);
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $subevent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(ModuleDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$con = Propel::getWriteConnection(ModuleTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId(), $con)) {
|
||||
try {
|
||||
if (null === $module->getFullNamespace()) {
|
||||
throw new \LogicException(
|
||||
Translator::getInstance()->trans(
|
||||
'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?',
|
||||
['%name%' => $module->getCode()]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// If the module is referenced by an order, display a meaningful error
|
||||
// instead of 'delete cannot delete' caused by a constraint violation.
|
||||
// FIXME: we hav to find a way to delete modules used by order.
|
||||
if (OrderQuery::create()->filterByDeliveryModuleId($module->getId())->count() > 0
|
||||
||
|
||||
OrderQuery::create()->filterByPaymentModuleId($module->getId())->count() > 0
|
||||
) {
|
||||
throw new \LogicException(
|
||||
Translator::getInstance()->trans(
|
||||
'The module "%name%" is currently in use by at least one order, and can\'t be deleted.',
|
||||
['%name%' => $module->getCode()]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// First, try to create an instance
|
||||
$instance = $module->createInstance();
|
||||
|
||||
// Then, if module is activated, check if we can deactivate it
|
||||
if ($module->getActivate()) {
|
||||
// check for modules that depend of this one
|
||||
$this->checkDeactivation($module);
|
||||
}
|
||||
|
||||
$instance->setContainer($this->container);
|
||||
|
||||
$path = $module->getAbsoluteBaseDir();
|
||||
|
||||
$instance->destroy($con, $event->getDeleteData());
|
||||
|
||||
$fs = new Filesystem();
|
||||
$fs->remove($path);
|
||||
} catch (\ReflectionException $ex) {
|
||||
// Happens probably because the module directory has been deleted.
|
||||
// Log a warning, and delete the database entry.
|
||||
Tlog::getInstance()->addWarning(
|
||||
Translator::getInstance()->trans(
|
||||
'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted',
|
||||
['%name%' => $module->getCode()]
|
||||
)
|
||||
);
|
||||
} catch (FileNotFoundException $fnfe) {
|
||||
// The module directory has been deleted.
|
||||
// Log a warning, and delete the database entry.
|
||||
Tlog::getInstance()->addWarning(
|
||||
Translator::getInstance()->trans(
|
||||
'Module "%name%" directory was not found',
|
||||
['%name%' => $module->getCode()]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$module->delete($con);
|
||||
|
||||
$con->commit();
|
||||
|
||||
$event->setModule($module);
|
||||
$this->cacheClear($dispatcher);
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModuleEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(ModuleEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getId())) {
|
||||
$module
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->setPostscriptum($event->getPostscriptum());
|
||||
|
||||
$module->save();
|
||||
|
||||
$event->setModule($module);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Module\ModuleInstallEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Symfony\Component\Filesystem\Exception\IOException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function install(ModuleInstallEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$moduleDefinition = $event->getModuleDefinition();
|
||||
|
||||
$oldModule = ModuleQuery::create()->findOneByFullNamespace($moduleDefinition->getNamespace());
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
$activated = false;
|
||||
|
||||
// check existing module
|
||||
if (null !== $oldModule) {
|
||||
$activated = $oldModule->getActivate();
|
||||
|
||||
if ($activated) {
|
||||
// deactivate
|
||||
$toggleEvent = new ModuleToggleActivationEvent($oldModule->getId());
|
||||
// disable the check of the module because it's already done
|
||||
$toggleEvent->setNoCheck(true);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $toggleEvent);
|
||||
}
|
||||
|
||||
// delete
|
||||
$modulePath = $oldModule->getAbsoluteBaseDir();
|
||||
|
||||
$deleteEvent = new ModuleDeleteEvent($oldModule);
|
||||
|
||||
try {
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_DELETE, $deleteEvent);
|
||||
} catch (Exception $ex) {
|
||||
// if module has not been deleted
|
||||
if ($fs->exists($modulePath)) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move new module
|
||||
$modulePath = sprintf('%s%s', THELIA_MODULE_DIR, $event->getModuleDefinition()->getCode());
|
||||
|
||||
try {
|
||||
$fs->mirror($event->getModulePath(), $modulePath);
|
||||
} catch (IOException $ex) {
|
||||
if (!$fs->exists($modulePath)) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the module
|
||||
$moduleDescriptorFile = sprintf('%s%s%s%s%s', $modulePath, DS, 'Config', DS, 'module.xml');
|
||||
$moduleManagement = new ModuleManagement();
|
||||
$file = new SplFileInfo($moduleDescriptorFile);
|
||||
$module = $moduleManagement->updateModule($file, $this->container);
|
||||
|
||||
// activate if old was activated
|
||||
if ($activated) {
|
||||
$toggleEvent = new ModuleToggleActivationEvent($module->getId());
|
||||
$toggleEvent->setNoCheck(true);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $toggleEvent);
|
||||
}
|
||||
|
||||
$event->setModule($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the payment method of the payment module of the given order
|
||||
*
|
||||
* @param OrderPaymentEvent $event
|
||||
*
|
||||
* @throws \RuntimeException if no payment module can be found.
|
||||
*/
|
||||
public function pay(OrderPaymentEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
/* call pay method */
|
||||
if (null === $paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId())) {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans(
|
||||
"Failed to find a payment Module with ID=%mid for order ID=%oid",
|
||||
[
|
||||
"%mid" => $order->getPaymentModuleId(),
|
||||
"%oid" => $order->getId()
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$paymentModuleInstance = $paymentModule->getPaymentModuleInstance($this->container);
|
||||
|
||||
$response = $paymentModuleInstance->pay($order);
|
||||
|
||||
if (null !== $response && $response instanceof Response) {
|
||||
$event->setResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(ModuleQuery::create(), $event, $dispatcher);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
|
||||
protected function cacheClear(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cacheEvent = new CacheEvent(
|
||||
$this->container->getParameter('kernel.cache_dir')
|
||||
);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::MODULE_TOGGLE_ACTIVATION => [
|
||||
['checkToggleActivation', 255],
|
||||
['toggleActivation', 128],
|
||||
],
|
||||
TheliaEvents::MODULE_UPDATE_POSITION => ['updatePosition', 128],
|
||||
TheliaEvents::MODULE_DELETE => ['delete', 128],
|
||||
TheliaEvents::MODULE_UPDATE => ['update', 128],
|
||||
TheliaEvents::MODULE_INSTALL => ['install', 128],
|
||||
TheliaEvents::MODULE_PAY => ['pay', 128],
|
||||
];
|
||||
}
|
||||
}
|
||||
252
core/lib/Thelia/Action/ModuleHook.php
Normal file
252
core/lib/Thelia/Action/ModuleHook.php
Normal file
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\Hook\HookToggleActivationEvent;
|
||||
use Thelia\Core\Event\Hook\HookUpdateEvent;
|
||||
use Thelia\Core\Event\Hook\ModuleHookCreateEvent;
|
||||
use Thelia\Core\Event\Hook\ModuleHookDeleteEvent;
|
||||
use Thelia\Core\Event\Hook\ModuleHookToggleActivationEvent;
|
||||
use Thelia\Core\Event\Hook\ModuleHookUpdateEvent;
|
||||
use Thelia\Core\Event\Module\ModuleDeleteEvent;
|
||||
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Model\Base\IgnoredModuleHookQuery;
|
||||
use Thelia\Model\HookQuery;
|
||||
use Thelia\Model\IgnoredModuleHook;
|
||||
use Thelia\Model\ModuleHook as ModuleHookModel;
|
||||
use Thelia\Model\ModuleHookQuery;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
/**
|
||||
* Class ModuleHook
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class ModuleHook extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $cacheDir;
|
||||
|
||||
public function __construct($cacheDir)
|
||||
{
|
||||
$this->cacheDir = $cacheDir;
|
||||
}
|
||||
|
||||
public function toggleModuleActivation(ModuleToggleActivationEvent $event)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||
ModuleHookQuery::create()
|
||||
->filterByModuleId($module->getId())
|
||||
->update(array('ModuleActive' => ($module->getActivate() == BaseModule::IS_ACTIVATED)));
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function deleteModule(ModuleDeleteEvent $event)
|
||||
{
|
||||
if ($event->getModuleId()) {
|
||||
ModuleHookQuery::create()
|
||||
->filterByModuleId($event->getModuleId())
|
||||
->delete();
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
protected function isModuleActive($module_id)
|
||||
{
|
||||
if (null !== $module = ModuleQuery::create()->findPk($module_id)) {
|
||||
return $module->getActivate();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function isHookActive($hook_id)
|
||||
{
|
||||
if (null !== $hook = HookQuery::create()->findPk($hook_id)) {
|
||||
return $hook->getActivate();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getLastPositionInHook($hook_id)
|
||||
{
|
||||
$result = ModuleHookQuery::create()
|
||||
->filterByHookId($hook_id)
|
||||
->withColumn('MAX(ModuleHook.position)', 'maxPos')
|
||||
->groupBy('ModuleHook.hook_id')
|
||||
->select(array('maxPos'))
|
||||
->findOne();
|
||||
|
||||
return intval($result) + 1;
|
||||
}
|
||||
|
||||
public function createModuleHook(ModuleHookCreateEvent $event)
|
||||
{
|
||||
$moduleHook = new ModuleHookModel();
|
||||
|
||||
// todo: test if classname and method exists
|
||||
$moduleHook
|
||||
->setModuleId($event->getModuleId())
|
||||
->setHookId($event->getHookId())
|
||||
->setActive(false)
|
||||
->setClassname($event->getClassname())
|
||||
->setMethod($event->getMethod())
|
||||
->setModuleActive($this->isModuleActive($event->getModuleId()))
|
||||
->setHookActive($this->isHookActive($event->getHookId()))
|
||||
->setPosition($this->getLastPositionInHook($event->getHookId()))
|
||||
->setTemplates($event->getTemplates())
|
||||
->save();
|
||||
|
||||
// Be sure to delete this module hook from the ignored module hook table
|
||||
IgnoredModuleHookQuery::create()
|
||||
->filterByHookId($event->getHookId())
|
||||
->filterByModuleId($event->getModuleId())
|
||||
->delete();
|
||||
|
||||
$event->setModuleHook($moduleHook);
|
||||
}
|
||||
|
||||
public function updateModuleHook(ModuleHookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $moduleHook = ModuleHookQuery::create()->findPk($event->getModuleHookId())) {
|
||||
// todo: test if classname and method exists
|
||||
$moduleHook
|
||||
->setHookId($event->getHookId())
|
||||
->setModuleId($event->getModuleId())
|
||||
->setClassname($event->getClassname())
|
||||
->setMethod($event->getMethod())
|
||||
->setActive($event->getActive())
|
||||
->setHookActive($this->isHookActive($event->getHookId()))
|
||||
->setTemplates($event->getTemplates())
|
||||
->save();
|
||||
|
||||
$event->setModuleHook($moduleHook);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteModuleHook(ModuleHookDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $moduleHook = ModuleHookQuery::create()->findPk($event->getModuleHookId())) {
|
||||
$moduleHook->delete();
|
||||
$event->setModuleHook($moduleHook);
|
||||
|
||||
// Prevent hook recreation by RegisterListenersPass::registerHook()
|
||||
// We store the method here to be able to retreive it when
|
||||
// we need to get all hook declared by a module
|
||||
$imh = new IgnoredModuleHook();
|
||||
$imh
|
||||
->setModuleId($moduleHook->getModuleId())
|
||||
->setHookId($moduleHook->getHookId())
|
||||
->setMethod($moduleHook->getMethod())
|
||||
->setClassname($moduleHook->getClassname())
|
||||
->save();
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleModuleHookActivation(ModuleHookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $moduleHook = $event->getModuleHook()) {
|
||||
if ($moduleHook->getModuleActive()) {
|
||||
$moduleHook->setActive(!$moduleHook->getActive());
|
||||
$moduleHook->save();
|
||||
} else {
|
||||
throw new \LogicException(Translator::getInstance()->trans("The module has to be activated."));
|
||||
}
|
||||
}
|
||||
$this->cacheClear($dispatcher);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*
|
||||
* @return UpdatePositionEvent $event
|
||||
*/
|
||||
public function updateModuleHookPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(ModuleHookQuery::create(), $event, $dispatcher);
|
||||
$this->cacheClear($dispatcher);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function updateHook(HookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if ($event->hasHook()) {
|
||||
$hook = $event->getHook();
|
||||
ModuleHookQuery::create()
|
||||
->filterByHookId($hook->getId())
|
||||
->update(array('HookActive' => $hook->getActivate()));
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleHookActivation(HookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if ($event->hasHook()) {
|
||||
$hook = $event->getHook();
|
||||
ModuleHookQuery::create()
|
||||
->filterByHookId($hook->getId())
|
||||
->update(array('HookActive' => $hook->getActivate()));
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
protected function cacheClear(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cacheEvent = new CacheEvent($this->cacheDir);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::MODULE_HOOK_CREATE => array('createModuleHook', 128),
|
||||
TheliaEvents::MODULE_HOOK_UPDATE => array('updateModuleHook', 128),
|
||||
TheliaEvents::MODULE_HOOK_DELETE => array('deleteModuleHook', 128),
|
||||
TheliaEvents::MODULE_HOOK_UPDATE_POSITION => array('updateModuleHookPosition', 128),
|
||||
TheliaEvents::MODULE_HOOK_TOGGLE_ACTIVATION => array('toggleModuleHookActivation', 128),
|
||||
|
||||
TheliaEvents::MODULE_TOGGLE_ACTIVATION => array('toggleModuleActivation', 64),
|
||||
TheliaEvents::MODULE_DELETE => array('deleteModule', 64),
|
||||
|
||||
TheliaEvents::HOOK_TOGGLE_ACTIVATION => array('toggleHookActivation', 64),
|
||||
TheliaEvents::HOOK_UPDATE => array('updateHook', 64),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
119
core/lib/Thelia/Action/Newsletter.php
Normal file
119
core/lib/Thelia/Action/Newsletter.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Newsletter\NewsletterEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Mailer\MailerFactory;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\NewsletterQuery;
|
||||
use Thelia\Model\Newsletter as NewsletterModel;
|
||||
|
||||
/**
|
||||
* Class Newsletter
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Newsletter extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var MailerFactory */
|
||||
protected $mailer;
|
||||
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $dispatcher;
|
||||
|
||||
public function __construct(MailerFactory $mailer, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function subscribe(NewsletterEvent $event)
|
||||
{
|
||||
// test if the email is already registered and unsubscribed
|
||||
if (null === $newsletter = NewsletterQuery::create()->findOneByEmail($event->getEmail())) {
|
||||
$newsletter = new NewsletterModel();
|
||||
}
|
||||
|
||||
$newsletter
|
||||
->setEmail($event->getEmail())
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setLocale($event->getLocale())
|
||||
->setUnsubscribed(false)
|
||||
->save();
|
||||
|
||||
$event->setNewsletter($newsletter);
|
||||
|
||||
if (ConfigQuery::getNotifyNewsletterSubscription()) {
|
||||
$this->dispatcher->dispatch(TheliaEvents::NEWSLETTER_CONFIRM_SUBSCRIPTION, $event);
|
||||
}
|
||||
}
|
||||
|
||||
public function unsubscribe(NewsletterEvent $event)
|
||||
{
|
||||
if (null !== $nl = NewsletterQuery::create()->findPk($event->getId())) {
|
||||
$nl
|
||||
->setUnsubscribed(true)
|
||||
->save();
|
||||
|
||||
$event->setNewsletter($nl);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(NewsletterEvent $event)
|
||||
{
|
||||
if (null !== $nl = NewsletterQuery::create()->findPk($event->getId())) {
|
||||
$nl->setEmail($event->getEmail())
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setLocale($event->getLocale())
|
||||
->save();
|
||||
|
||||
$event->setNewsletter($nl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0-alpha2
|
||||
*/
|
||||
public function confirmSubscription(NewsletterEvent $event)
|
||||
{
|
||||
$this->mailer->sendEmailMessage(
|
||||
'newsletter_subscription_confirmation',
|
||||
[ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ],
|
||||
[ $event->getEmail() => $event->getFirstname()." ".$event->getLastname() ],
|
||||
[
|
||||
'email' => $event->getEmail(),
|
||||
'firstname' => $event->getFirstname(),
|
||||
'lastname' => $event->getLastname()
|
||||
],
|
||||
$event->getLocale()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::NEWSLETTER_SUBSCRIBE => array('subscribe', 128),
|
||||
TheliaEvents::NEWSLETTER_UPDATE => array('update', 128),
|
||||
TheliaEvents::NEWSLETTER_UNSUBSCRIBE => array('unsubscribe', 128),
|
||||
TheliaEvents::NEWSLETTER_CONFIRM_SUBSCRIPTION => array('confirmSubscription', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
727
core/lib/Thelia/Action/Order.php
Normal file
727
core/lib/Thelia/Action/Order.php
Normal file
@@ -0,0 +1,727 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Thelia\Core\Event\Order\OrderAddressEvent;
|
||||
use Thelia\Core\Event\Order\OrderEvent;
|
||||
use Thelia\Core\Event\Order\OrderManualEvent;
|
||||
use Thelia\Core\Event\Order\OrderPaymentEvent;
|
||||
use Thelia\Core\Event\Payment\ManageStockOnCreationEvent;
|
||||
use Thelia\Core\Event\Product\VirtualProductOrderHandleEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Security\SecurityContext;
|
||||
use Thelia\Core\Security\User\UserInterface;
|
||||
use Thelia\Exception\TheliaProcessException;
|
||||
use Thelia\Mailer\MailerFactory;
|
||||
use Thelia\Model\AddressQuery;
|
||||
use Thelia\Model\Cart as CartModel;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Currency as CurrencyModel;
|
||||
use Thelia\Model\Lang as LangModel;
|
||||
use Thelia\Model\Map\OrderTableMap;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Model\Order as ModelOrder;
|
||||
use Thelia\Model\Order as OrderModel;
|
||||
use Thelia\Model\OrderAddress;
|
||||
use Thelia\Model\OrderAddressQuery;
|
||||
use Thelia\Model\OrderProduct;
|
||||
use Thelia\Model\OrderProductAttributeCombination;
|
||||
use Thelia\Model\OrderProductTax;
|
||||
use Thelia\Model\OrderStatusQuery;
|
||||
use Thelia\Model\ProductI18n;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Model\TaxRuleI18n;
|
||||
use Thelia\Module\PaymentModuleInterface;
|
||||
use Thelia\Tools\I18n;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class Order
|
||||
* @package Thelia\Action
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
*/
|
||||
class Order extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var RequestStack */
|
||||
protected $requestStack;
|
||||
|
||||
/** @var MailerFactory */
|
||||
protected $mailer;
|
||||
|
||||
/** @var SecurityContext */
|
||||
protected $securityContext;
|
||||
|
||||
public function __construct(RequestStack $requestStack, MailerFactory $mailer, SecurityContext $securityContext)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->mailer = $mailer;
|
||||
$this->securityContext = $securityContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function setDeliveryAddress(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$order->setChoosenDeliveryAddress($event->getDeliveryAddress());
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function setDeliveryModule(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$deliveryModuleId = $event->getDeliveryModule();
|
||||
|
||||
$order->setDeliveryModuleId($deliveryModuleId);
|
||||
|
||||
// Reset postage cost if the delivery module had been removed
|
||||
if ($deliveryModuleId <= 0) {
|
||||
$order->setPostage(0);
|
||||
$order->setPostageTax(0);
|
||||
$order->setPostageTaxRuleTitle(null);
|
||||
}
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function setPostage(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$order->setPostage($event->getPostage());
|
||||
$order->setPostageTax($event->getPostageTax());
|
||||
$order->setPostageTaxRuleTitle($event->getPostageTaxRuleTitle());
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function setInvoiceAddress(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$order->setChoosenInvoiceAddress($event->getInvoiceAddress());
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Thelia\Core\Event\Order\OrderEvent $event
|
||||
*/
|
||||
public function setPaymentModule(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$order->setPaymentModuleId($event->getPaymentModule());
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param ModelOrder $sessionOrder
|
||||
* @param CurrencyModel $currency
|
||||
* @param LangModel $lang
|
||||
* @param CartModel $cart
|
||||
* @param UserInterface $customer
|
||||
* @param bool $manageStock decrement stock when order is created if true
|
||||
* @param bool $useOrderDefinedAddresses if true, the delivery and invoice OrderAddresses will be used instead of creating new OrderAdresses using Order::getChoosenXXXAddress()
|
||||
* @return ModelOrder
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function createOrder(
|
||||
EventDispatcherInterface $dispatcher,
|
||||
ModelOrder $sessionOrder,
|
||||
CurrencyModel $currency,
|
||||
LangModel $lang,
|
||||
CartModel $cart,
|
||||
UserInterface $customer,
|
||||
$manageStock,
|
||||
$useOrderDefinedAddresses = false
|
||||
) {
|
||||
$con = Propel::getConnection(
|
||||
OrderTableMap::DATABASE_NAME
|
||||
);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
$placedOrder = $sessionOrder->copy();
|
||||
|
||||
// Be sure to create a brand new order, as copy raises the modified flag for all fields
|
||||
// and will also copy order reference and id.
|
||||
$placedOrder->setId(null)->setRef(null)->setNew(true);
|
||||
|
||||
// Dates should be marked as not updated so that Propel will update them.
|
||||
$placedOrder->resetModified(OrderTableMap::CREATED_AT);
|
||||
$placedOrder->resetModified(OrderTableMap::UPDATED_AT);
|
||||
$placedOrder->resetModified(OrderTableMap::VERSION_CREATED_AT);
|
||||
|
||||
$placedOrder->setDispatcher($dispatcher);
|
||||
|
||||
$cartItems = $cart->getCartItems();
|
||||
|
||||
/* fulfill order */
|
||||
$placedOrder->setCustomerId($customer->getId());
|
||||
$placedOrder->setCurrencyId($currency->getId());
|
||||
$placedOrder->setCurrencyRate($currency->getRate());
|
||||
$placedOrder->setLangId($lang->getId());
|
||||
|
||||
if ($useOrderDefinedAddresses) {
|
||||
$taxCountry =
|
||||
OrderAddressQuery::create()
|
||||
->findPk($placedOrder->getDeliveryOrderAddressId())
|
||||
->getCountry()
|
||||
;
|
||||
} else {
|
||||
$deliveryAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenDeliveryAddress());
|
||||
$invoiceAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenInvoiceAddress());
|
||||
|
||||
/* hard save the delivery and invoice addresses */
|
||||
$deliveryOrderAddress = new OrderAddress();
|
||||
$deliveryOrderAddress
|
||||
->setCustomerTitleId($deliveryAddress->getTitleId())
|
||||
->setCompany($deliveryAddress->getCompany())
|
||||
->setFirstname($deliveryAddress->getFirstname())
|
||||
->setLastname($deliveryAddress->getLastname())
|
||||
->setAddress1($deliveryAddress->getAddress1())
|
||||
->setAddress2($deliveryAddress->getAddress2())
|
||||
->setAddress3($deliveryAddress->getAddress3())
|
||||
->setZipcode($deliveryAddress->getZipcode())
|
||||
->setCity($deliveryAddress->getCity())
|
||||
->setPhone($deliveryAddress->getPhone())
|
||||
->setCellphone($deliveryAddress->getCellphone())
|
||||
->setCountryId($deliveryAddress->getCountryId())
|
||||
->setStateId($deliveryAddress->getStateId())
|
||||
->save($con);
|
||||
|
||||
$invoiceOrderAddress = new OrderAddress();
|
||||
$invoiceOrderAddress
|
||||
->setCustomerTitleId($invoiceAddress->getTitleId())
|
||||
->setCompany($invoiceAddress->getCompany())
|
||||
->setFirstname($invoiceAddress->getFirstname())
|
||||
->setLastname($invoiceAddress->getLastname())
|
||||
->setAddress1($invoiceAddress->getAddress1())
|
||||
->setAddress2($invoiceAddress->getAddress2())
|
||||
->setAddress3($invoiceAddress->getAddress3())
|
||||
->setZipcode($invoiceAddress->getZipcode())
|
||||
->setCity($invoiceAddress->getCity())
|
||||
->setPhone($invoiceAddress->getPhone())
|
||||
->setCellphone($invoiceAddress->getCellphone())
|
||||
->setCountryId($invoiceAddress->getCountryId())
|
||||
->setStateId($deliveryAddress->getStateId())
|
||||
->save($con);
|
||||
|
||||
$placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId());
|
||||
$placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId());
|
||||
|
||||
$taxCountry = $deliveryAddress->getCountry();
|
||||
}
|
||||
|
||||
$placedOrder->setStatusId(
|
||||
OrderStatusQuery::getNotPaidStatus()->getId()
|
||||
);
|
||||
|
||||
$placedOrder->setCartId($cart->getId());
|
||||
|
||||
/* memorize discount */
|
||||
$placedOrder->setDiscount(
|
||||
$cart->getDiscount()
|
||||
);
|
||||
|
||||
$placedOrder->save($con);
|
||||
|
||||
/* fulfill order_products and decrease stock */
|
||||
|
||||
foreach ($cartItems as $cartItem) {
|
||||
$product = $cartItem->getProduct();
|
||||
|
||||
/* get translation */
|
||||
/** @var ProductI18n $productI18n */
|
||||
$productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId());
|
||||
|
||||
$pse = $cartItem->getProductSaleElements();
|
||||
|
||||
// get the virtual document path
|
||||
$virtualDocumentEvent = new VirtualProductOrderHandleEvent($placedOrder, $pse->getId());
|
||||
// essentially used for virtual product. modules that handles virtual product can
|
||||
// allow the use of stock even for virtual products
|
||||
$useStock = true;
|
||||
$virtual = 0;
|
||||
|
||||
// if the product is virtual, dispatch an event to collect information
|
||||
if ($product->getVirtual() === 1) {
|
||||
$dispatcher->dispatch(TheliaEvents::VIRTUAL_PRODUCT_ORDER_HANDLE, $virtualDocumentEvent);
|
||||
$useStock = $virtualDocumentEvent->isUseStock();
|
||||
$virtual = $virtualDocumentEvent->isVirtual() ? 1 : 0;
|
||||
}
|
||||
|
||||
/* check still in stock */
|
||||
if ($cartItem->getQuantity() > $pse->getQuantity()
|
||||
&& true === ConfigQuery::checkAvailableStock()
|
||||
&& $useStock) {
|
||||
throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem);
|
||||
}
|
||||
|
||||
if ($useStock && $manageStock) {
|
||||
/* decrease stock for non virtual product */
|
||||
$allowNegativeStock = intval(ConfigQuery::read('allow_negative_stock', 0));
|
||||
$newStock = $pse->getQuantity() - $cartItem->getQuantity();
|
||||
//Forbid negative stock
|
||||
if ($newStock < 0 && 0 === $allowNegativeStock) {
|
||||
$newStock = 0;
|
||||
}
|
||||
$pse->setQuantity(
|
||||
$newStock
|
||||
);
|
||||
|
||||
$pse->save($con);
|
||||
}
|
||||
|
||||
/* get tax */
|
||||
/** @var TaxRuleI18n $taxRuleI18n */
|
||||
$taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId());
|
||||
|
||||
$taxDetail = $product->getTaxRule()->getTaxDetail(
|
||||
$product,
|
||||
$taxCountry,
|
||||
$cartItem->getPrice(),
|
||||
$cartItem->getPromoPrice(),
|
||||
$lang->getLocale()
|
||||
);
|
||||
|
||||
$orderProduct = new OrderProduct();
|
||||
$orderProduct
|
||||
->setOrderId($placedOrder->getId())
|
||||
->setProductRef($product->getRef())
|
||||
->setProductSaleElementsRef($pse->getRef())
|
||||
->setProductSaleElementsId($pse->getId())
|
||||
->setTitle($productI18n->getTitle())
|
||||
->setChapo($productI18n->getChapo())
|
||||
->setDescription($productI18n->getDescription())
|
||||
->setPostscriptum($productI18n->getPostscriptum())
|
||||
->setVirtual($virtual)
|
||||
->setVirtualDocument($virtualDocumentEvent->getPath())
|
||||
->setQuantity($cartItem->getQuantity())
|
||||
->setPrice($cartItem->getPrice())
|
||||
->setPromoPrice($cartItem->getPromoPrice())
|
||||
->setWasNew($pse->getNewness())
|
||||
->setWasInPromo($cartItem->getPromo())
|
||||
->setWeight($pse->getWeight())
|
||||
->setTaxRuleTitle($taxRuleI18n->getTitle())
|
||||
->setTaxRuleDescription($taxRuleI18n->getDescription())
|
||||
->setEanCode($pse->getEanCode())
|
||||
->setCartItemId($cartItem->getId())
|
||||
->setDispatcher($dispatcher)
|
||||
->save($con)
|
||||
;
|
||||
|
||||
/* fulfill order_product_tax */
|
||||
/** @var OrderProductTax $tax */
|
||||
foreach ($taxDetail as $tax) {
|
||||
$tax->setOrderProductId($orderProduct->getId());
|
||||
$tax->save($con);
|
||||
}
|
||||
|
||||
/* fulfill order_attribute_combination and decrease stock */
|
||||
foreach ($pse->getAttributeCombinations() as $attributeCombination) {
|
||||
/** @var \Thelia\Model\Attribute $attribute */
|
||||
$attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId());
|
||||
|
||||
/** @var \Thelia\Model\AttributeAv $attributeAv */
|
||||
$attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId());
|
||||
|
||||
$orderAttributeCombination = new OrderProductAttributeCombination();
|
||||
$orderAttributeCombination
|
||||
->setOrderProductId($orderProduct->getId())
|
||||
->setAttributeTitle($attribute->getTitle())
|
||||
->setAttributeChapo($attribute->getChapo())
|
||||
->setAttributeDescription($attribute->getDescription())
|
||||
->setAttributePostscriptum($attribute->getPostscriptum())
|
||||
->setAttributeAvTitle($attributeAv->getTitle())
|
||||
->setAttributeAvChapo($attributeAv->getChapo())
|
||||
->setAttributeAvDescription($attributeAv->getDescription())
|
||||
->setAttributeAvPostscriptum($attributeAv->getPostscriptum())
|
||||
->save($con);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
|
||||
return $placedOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an order outside of the front-office context, e.g. manually from the back-office.
|
||||
* @param OrderManualEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function createManual(OrderManualEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$paymentModule = ModuleQuery::create()->findPk($event->getOrder()->getPaymentModuleId());
|
||||
|
||||
/** @var \Thelia\Module\PaymentModuleInterface $paymentModuleInstance */
|
||||
$paymentModuleInstance = $paymentModule->createInstance();
|
||||
|
||||
$event->setPlacedOrder(
|
||||
$this->createOrder(
|
||||
$dispatcher,
|
||||
$event->getOrder(),
|
||||
$event->getCurrency(),
|
||||
$event->getLang(),
|
||||
$event->getCart(),
|
||||
$event->getCustomer(),
|
||||
$this->isModuleManageStockOnCreation(
|
||||
$dispatcher,
|
||||
$paymentModuleInstance
|
||||
),
|
||||
$event->getUseOrderDefinedAddresses()
|
||||
)
|
||||
);
|
||||
|
||||
$event->setOrder(new OrderModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
*
|
||||
* @throws \Thelia\Exception\TheliaProcessException
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$session = $this->getSession();
|
||||
|
||||
$order = $event->getOrder();
|
||||
$paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId());
|
||||
|
||||
/** @var \Thelia\Module\PaymentModuleInterface $paymentModuleInstance */
|
||||
$paymentModuleInstance = $paymentModule->createInstance();
|
||||
|
||||
$placedOrder = $this->createOrder(
|
||||
$dispatcher,
|
||||
$event->getOrder(),
|
||||
$session->getCurrency(),
|
||||
$session->getLang(),
|
||||
$session->getSessionCart($dispatcher),
|
||||
$this->securityContext->getCustomerUser(),
|
||||
$this->isModuleManageStockOnCreation(
|
||||
$dispatcher,
|
||||
$paymentModuleInstance
|
||||
)
|
||||
);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder));
|
||||
|
||||
/* but memorize placed order */
|
||||
$event->setOrder(new OrderModel());
|
||||
$event->setPlacedOrder($placedOrder);
|
||||
|
||||
/* call pay method */
|
||||
$payEvent = new OrderPaymentEvent($placedOrder);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent);
|
||||
|
||||
if ($payEvent->hasResponse()) {
|
||||
$event->setResponse($payEvent->getResponse());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function orderBeforePayment(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$dispatcher ->dispatch(TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL, clone $event);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL, clone $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cart and the order in the customer session once the order is placed,
|
||||
* and the payment performed.
|
||||
*
|
||||
* @param OrderEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function orderCartClear(/** @noinspection PhpUnusedParameterInspection */ OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
// Empty cart and clear current order
|
||||
$session = $this->getSession();
|
||||
|
||||
$session->clearSessionCart($dispatcher);
|
||||
|
||||
$session->setOrder(new OrderModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
*
|
||||
* @throws \Exception if the message cannot be loaded.
|
||||
*/
|
||||
public function sendConfirmationEmail(OrderEvent $event)
|
||||
{
|
||||
$this->mailer->sendEmailToCustomer(
|
||||
'order_confirmation',
|
||||
$event->getOrder()->getCustomer(),
|
||||
[
|
||||
'order_id' => $event->getOrder()->getId(),
|
||||
'order_ref' => $event->getOrder()->getRef()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
*
|
||||
* @throws \Exception if the message cannot be loaded.
|
||||
*/
|
||||
public function sendNotificationEmail(OrderEvent $event)
|
||||
{
|
||||
$this->mailer->sendEmailToShopManagers(
|
||||
'order_notification',
|
||||
[
|
||||
'order_id' => $event->getOrder()->getId(),
|
||||
'order_ref' => $event->getOrder()->getRef()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
*/
|
||||
public function updateStatus(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
$newStatus = $event->getStatus();
|
||||
$paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId());
|
||||
/** @var PaymentModuleInterface $paymentModuleInstance */
|
||||
$paymentModuleInstance = $paymentModule->createInstance();
|
||||
|
||||
$manageStockOnCreation = $this->isModuleManageStockOnCreation(
|
||||
$dispatcher,
|
||||
$paymentModuleInstance
|
||||
);
|
||||
|
||||
$this->updateQuantity($order, $newStatus, $manageStockOnCreation);
|
||||
|
||||
$order->setStatusId($newStatus);
|
||||
$order->save();
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModelOrder $order
|
||||
* @param $newStatus $newStatus the new status ID
|
||||
* @throws \Thelia\Exception\TheliaProcessException
|
||||
*/
|
||||
public function updateQuantity(ModelOrder $order, $newStatus, $manageStockOnCreation = true)
|
||||
{
|
||||
$canceledStatus = OrderStatusQuery::getCancelledStatus()->getId();
|
||||
$paidStatus = OrderStatusQuery::getPaidStatus()->getId();
|
||||
if ($newStatus == $canceledStatus || $order->isCancelled()) {
|
||||
$this->updateQuantityForCanceledOrder($order, $newStatus, $canceledStatus);
|
||||
} elseif ($paidStatus == $newStatus && $order->isNotPaid() && $order->getVersion() == 1) {
|
||||
$this->updateQuantityForPaidOrder($order, $manageStockOnCreation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModelOrder $order
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function updateQuantityForPaidOrder(ModelOrder $order, $manageStockOnCreation)
|
||||
{
|
||||
$paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId());
|
||||
|
||||
/** @var \Thelia\Module\PaymentModuleInterface $paymentModuleInstance */
|
||||
$paymentModuleInstance = $paymentModule->createInstance();
|
||||
|
||||
if (false === $manageStockOnCreation) {
|
||||
$orderProductList = $order->getOrderProducts();
|
||||
|
||||
/** @var OrderProduct $orderProduct */
|
||||
foreach ($orderProductList as $orderProduct) {
|
||||
$productSaleElementsId = $orderProduct->getProductSaleElementsId();
|
||||
|
||||
/** @var ProductSaleElements $productSaleElements */
|
||||
if (null !== $productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId)) {
|
||||
/* check still in stock */
|
||||
if ($orderProduct->getQuantity() > $productSaleElements->getQuantity() && true === ConfigQuery::checkAvailableStock()) {
|
||||
throw new TheliaProcessException($productSaleElements->getRef() . " : Not enough stock");
|
||||
}
|
||||
|
||||
$productSaleElements->setQuantity($productSaleElements->getQuantity() - $orderProduct->getQuantity());
|
||||
|
||||
$productSaleElements->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update product quantity if new status is canceled or if old status is canceled.
|
||||
*
|
||||
* @param ModelOrder $order
|
||||
* @param $newStatus
|
||||
* @param $canceledStatus
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function updateQuantityForCanceledOrder(ModelOrder $order, $newStatus, $canceledStatus)
|
||||
{
|
||||
$orderProductList = $order->getOrderProducts();
|
||||
|
||||
/** @var OrderProduct $orderProduct */
|
||||
foreach ($orderProductList as $orderProduct) {
|
||||
$productSaleElementsId = $orderProduct->getProductSaleElementsId();
|
||||
|
||||
/** @var ProductSaleElements $productSaleElements */
|
||||
if (null !== $productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId)) {
|
||||
if ($newStatus == $canceledStatus) {
|
||||
$productSaleElements->setQuantity($productSaleElements->getQuantity() + $orderProduct->getQuantity());
|
||||
} else {
|
||||
/* check still in stock */
|
||||
if ($orderProduct->getQuantity() > $productSaleElements->getQuantity() && true === ConfigQuery::checkAvailableStock()) {
|
||||
throw new TheliaProcessException($productSaleElements->getRef() . " : Not enough stock");
|
||||
}
|
||||
|
||||
$productSaleElements->setQuantity($productSaleElements->getQuantity() - $orderProduct->getQuantity());
|
||||
}
|
||||
|
||||
$productSaleElements->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderEvent $event
|
||||
*/
|
||||
public function updateDeliveryRef(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$order->setDeliveryRef($event->getDeliveryRef());
|
||||
$order->save();
|
||||
|
||||
$event->setOrder($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderAddressEvent $event
|
||||
*/
|
||||
public function updateAddress(OrderAddressEvent $event)
|
||||
{
|
||||
$orderAddress = $event->getOrderAddress();
|
||||
|
||||
$orderAddress
|
||||
->setCustomerTitleId($event->getTitle())
|
||||
->setCompany($event->getCompany())
|
||||
->setFirstname($event->getFirstname())
|
||||
->setLastname($event->getLastname())
|
||||
->setAddress1($event->getAddress1())
|
||||
->setAddress2($event->getAddress2())
|
||||
->setAddress3($event->getAddress3())
|
||||
->setZipcode($event->getZipcode())
|
||||
->setCity($event->getCity())
|
||||
->setCountryId($event->getCountry())
|
||||
->setStateId($event->getState())
|
||||
->setPhone($event->getPhone())
|
||||
->setCellphone($event->getCellphone())
|
||||
;
|
||||
$orderAddress->save();
|
||||
|
||||
$event->setOrderAddress($orderAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a payment module manage stock on creation
|
||||
*
|
||||
* @param EventDispatcher $dispatcher
|
||||
* @param PaymentModuleInterface $module
|
||||
* @return bool if the module manage stock on creation, false otherwise
|
||||
*/
|
||||
protected function isModuleManageStockOnCreation(EventDispatcherInterface $dispatcher, PaymentModuleInterface $module)
|
||||
{
|
||||
$event = new ManageStockOnCreationEvent($module);
|
||||
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::getModuleEvent(
|
||||
TheliaEvents::MODULE_PAYMENT_MANAGE_STOCK,
|
||||
$module->getCode()
|
||||
)
|
||||
);
|
||||
|
||||
return (null !== $event->getManageStock())
|
||||
? $event->getManageStock()
|
||||
: $module->manageStockOnCreation();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => array("setDeliveryAddress", 128),
|
||||
TheliaEvents::ORDER_SET_DELIVERY_MODULE => array("setDeliveryModule", 128),
|
||||
TheliaEvents::ORDER_SET_POSTAGE => array("setPostage", 128),
|
||||
TheliaEvents::ORDER_SET_INVOICE_ADDRESS => array("setInvoiceAddress", 128),
|
||||
TheliaEvents::ORDER_SET_PAYMENT_MODULE => array("setPaymentModule", 128),
|
||||
TheliaEvents::ORDER_PAY => array("create", 128),
|
||||
TheliaEvents::ORDER_CART_CLEAR => array("orderCartClear", 128),
|
||||
TheliaEvents::ORDER_BEFORE_PAYMENT => array("orderBeforePayment", 128),
|
||||
TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL => array("sendConfirmationEmail", 128),
|
||||
TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL => array("sendNotificationEmail", 128),
|
||||
TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128),
|
||||
TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128),
|
||||
TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128),
|
||||
TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session from the current request
|
||||
*
|
||||
* @return \Thelia\Core\HttpFoundation\Session\Session
|
||||
*/
|
||||
protected function getSession()
|
||||
{
|
||||
return $this->requestStack->getCurrentRequest()->getSession();
|
||||
}
|
||||
}
|
||||
63
core/lib/Thelia/Action/Payment.php
Normal file
63
core/lib/Thelia/Action/Payment.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Payment\IsValidPaymentEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
/**
|
||||
* Class Payment
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class Payment implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Check if a module is valid
|
||||
*
|
||||
* @param IsValidPaymentEvent $event
|
||||
*/
|
||||
public function isValid(IsValidPaymentEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$module = $event->getModule();
|
||||
|
||||
// dispatch event to target specific module
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::getModuleEvent(
|
||||
TheliaEvents::MODULE_PAYMENT_IS_VALID,
|
||||
$module->getCode()
|
||||
),
|
||||
$event
|
||||
);
|
||||
|
||||
if ($event->isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// call legacy module method
|
||||
$event->setValidModule($module->isValidPayment());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
TheliaEvents::MODULE_PAYMENT_IS_VALID => ['isValid', 128],
|
||||
];
|
||||
}
|
||||
}
|
||||
54
core/lib/Thelia/Action/Pdf.php
Normal file
54
core/lib/Thelia/Action/Pdf.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\PdfEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
/**
|
||||
* Class Pdf
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Pdf extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function generatePdf(PdfEvent $event)
|
||||
{
|
||||
$html2pdf = new \HTML2PDF(
|
||||
$event->getOrientation(),
|
||||
$event->getFormat(),
|
||||
$event->getLang(),
|
||||
$event->getUnicode(),
|
||||
$event->getEncoding(),
|
||||
$event->getMarges()
|
||||
);
|
||||
|
||||
$html2pdf->setDefaultFont($event->getFontName());
|
||||
|
||||
$html2pdf->pdf->SetDisplayMode('real');
|
||||
|
||||
$html2pdf->writeHTML($event->getContent());
|
||||
$event->setPdf($html2pdf->output(null, 'S'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::GENERATE_PDF => array("generatePdf", 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
821
core/lib/Thelia/Action/Product.php
Normal file
821
core/lib/Thelia/Action/Product.php
Normal file
@@ -0,0 +1,821 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
|
||||
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
|
||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||
use Thelia\Core\Event\Product\ProductCloneEvent;
|
||||
use Thelia\Model\AttributeCombinationQuery;
|
||||
use Thelia\Model\FeatureAvI18n;
|
||||
use Thelia\Model\FeatureAvI18nQuery;
|
||||
use Thelia\Model\FeatureAvQuery;
|
||||
use Thelia\Model\Map\ProductTableMap;
|
||||
use Thelia\Model\ProductDocument;
|
||||
use Thelia\Model\ProductDocumentQuery;
|
||||
use Thelia\Model\ProductI18n;
|
||||
use Thelia\Model\ProductI18nQuery;
|
||||
use Thelia\Model\ProductImage;
|
||||
use Thelia\Model\ProductImageQuery;
|
||||
use Thelia\Model\ProductPrice;
|
||||
use Thelia\Model\ProductPriceQuery;
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Model\Product as ProductModel;
|
||||
use Thelia\Model\ProductAssociatedContent;
|
||||
use Thelia\Model\ProductAssociatedContentQuery;
|
||||
use Thelia\Model\ProductCategory;
|
||||
use Thelia\Model\TaxRuleQuery;
|
||||
use Thelia\Model\AccessoryQuery;
|
||||
use Thelia\Model\Accessory;
|
||||
use Thelia\Model\FeatureProduct;
|
||||
use Thelia\Model\FeatureProductQuery;
|
||||
use Thelia\Model\ProductCategoryQuery;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Product\ProductUpdateEvent;
|
||||
use Thelia\Core\Event\Product\ProductCreateEvent;
|
||||
use Thelia\Core\Event\Product\ProductDeleteEvent;
|
||||
use Thelia\Core\Event\Product\ProductToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\Product\ProductAddContentEvent;
|
||||
use Thelia\Core\Event\Product\ProductDeleteContentEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\UpdateSeoEvent;
|
||||
use Thelia\Core\Event\FeatureProduct\FeatureProductUpdateEvent;
|
||||
use Thelia\Core\Event\FeatureProduct\FeatureProductDeleteEvent;
|
||||
use Thelia\Core\Event\Product\ProductSetTemplateEvent;
|
||||
use Thelia\Core\Event\Product\ProductDeleteCategoryEvent;
|
||||
use Thelia\Core\Event\Product\ProductAddCategoryEvent;
|
||||
use Thelia\Core\Event\Product\ProductAddAccessoryEvent;
|
||||
use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent;
|
||||
use Propel\Runtime\Propel;
|
||||
|
||||
class Product extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new product entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Product\ProductCreateEvent $event
|
||||
*/
|
||||
public function create(ProductCreateEvent $event)
|
||||
{
|
||||
$product = new ProductModel();
|
||||
|
||||
$product
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
|
||||
->setRef($event->getRef())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setVisible($event->getVisible() ? 1 : 0)
|
||||
->setVirtual($event->getVirtual() ? 1 : 0)
|
||||
|
||||
// Set the default tax rule to this product
|
||||
->setTaxRule(TaxRuleQuery::create()->findOneByIsDefault(true))
|
||||
|
||||
->setTemplateId($event->getTemplateId())
|
||||
|
||||
->create(
|
||||
$event->getDefaultCategory(),
|
||||
$event->getBasePrice(),
|
||||
$event->getCurrencyId(),
|
||||
$event->getTaxRuleId(),
|
||||
$event->getBaseWeight(),
|
||||
$event->getBaseQuantity()
|
||||
)
|
||||
;
|
||||
|
||||
$event->setProduct($product);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* CLONING PROCESS *
|
||||
*******************/
|
||||
|
||||
/**
|
||||
* @param ProductCloneEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function cloneProduct(ProductCloneEvent $event)
|
||||
{
|
||||
$con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Get important datas
|
||||
$lang = $event->getLang();
|
||||
$originalProduct = $event->getOriginalProduct();
|
||||
|
||||
if (null === $originalProductDefaultI18n = ProductI18nQuery::create()
|
||||
->findPk([$originalProduct->getId(), $lang])) {
|
||||
// No i18n entry for the current language. Try to find one for creating the product.
|
||||
// It will be updated later by updateClone()
|
||||
$originalProductDefaultI18n = ProductI18nQuery::create()
|
||||
->findOneById($originalProduct->getId())
|
||||
;
|
||||
}
|
||||
|
||||
$originalProductDefaultPrice = ProductPriceQuery::create()
|
||||
->findOneByProductSaleElementsId($originalProduct->getDefaultSaleElements()->getId());
|
||||
|
||||
// Cloning process
|
||||
|
||||
$this->createClone($event, $originalProductDefaultI18n, $originalProductDefaultPrice);
|
||||
|
||||
$this->updateClone($event, $originalProductDefaultPrice);
|
||||
|
||||
$this->cloneFeatureCombination($event);
|
||||
|
||||
$this->cloneAssociatedContent($event);
|
||||
|
||||
$this->cloneAccessories($event);
|
||||
|
||||
// Dispatch event for file cloning
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::FILE_CLONE, $event);
|
||||
|
||||
// Dispatch event for PSE cloning
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PSE_CLONE, $event);
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function createClone(ProductCloneEvent $event, ProductI18n $originalProductDefaultI18n, ProductPrice $originalProductDefaultPrice)
|
||||
{
|
||||
// Build event and dispatch creation of the clone product
|
||||
$createCloneEvent = new ProductCreateEvent();
|
||||
$createCloneEvent
|
||||
->setTitle($originalProductDefaultI18n->getTitle())
|
||||
->setRef($event->getRef())
|
||||
->setLocale($event->getLang())
|
||||
->setVisible(0)
|
||||
->setVirtual($event->getOriginalProduct()->getVirtual())
|
||||
->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId())
|
||||
->setDefaultCategory($event->getOriginalProduct()->getDefaultCategoryId())
|
||||
->setBasePrice($originalProductDefaultPrice->getPrice())
|
||||
->setCurrencyId($originalProductDefaultPrice->getCurrencyId())
|
||||
->setBaseWeight($event->getOriginalProduct()->getDefaultSaleElements()->getWeight());
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_CREATE, $createCloneEvent);
|
||||
|
||||
$event->setClonedProduct($createCloneEvent->getProduct());
|
||||
}
|
||||
|
||||
public function updateClone(ProductCloneEvent $event, ProductPrice $originalProductDefaultPrice)
|
||||
{
|
||||
// Get original product's I18ns
|
||||
$originalProductI18ns = ProductI18nQuery::create()
|
||||
->findById($event->getOriginalProduct()->getId());
|
||||
|
||||
/** @var ProductI18n $originalProductI18n */
|
||||
foreach ($originalProductI18ns as $originalProductI18n) {
|
||||
$clonedProductUpdateEvent = new ProductUpdateEvent($event->getClonedProduct()->getId());
|
||||
$clonedProductUpdateEvent
|
||||
->setRef($event->getClonedProduct()->getRef())
|
||||
->setVisible($event->getClonedProduct()->getVisible())
|
||||
->setVirtual($event->getClonedProduct()->getVirtual())
|
||||
|
||||
->setLocale($originalProductI18n->getLocale())
|
||||
->setTitle($originalProductI18n->getTitle())
|
||||
->setChapo($originalProductI18n->getChapo())
|
||||
->setDescription($originalProductI18n->getDescription())
|
||||
->setPostscriptum($originalProductI18n->getPostscriptum())
|
||||
|
||||
->setBasePrice($originalProductDefaultPrice->getPrice())
|
||||
->setCurrencyId($originalProductDefaultPrice->getCurrencyId())
|
||||
->setBaseWeight($event->getOriginalProduct()->getDefaultSaleElements()->getWeight())
|
||||
->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId())
|
||||
->setBrandId($event->getOriginalProduct()->getBrandId())
|
||||
->setDefaultCategory($event->getOriginalProduct()->getDefaultCategoryId());
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE, $clonedProductUpdateEvent);
|
||||
|
||||
// SEO info
|
||||
$clonedProductUpdateSeoEvent = new UpdateSeoEvent($event->getClonedProduct()->getId());
|
||||
$clonedProductUpdateSeoEvent
|
||||
->setLocale($originalProductI18n->getLocale())
|
||||
->setMetaTitle($originalProductI18n->getMetaTitle())
|
||||
->setMetaDescription($originalProductI18n->getMetaDescription())
|
||||
->setMetaKeywords($originalProductI18n->getMetaKeywords())
|
||||
->setUrl(null);
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE_SEO, $clonedProductUpdateSeoEvent);
|
||||
}
|
||||
|
||||
$event->setClonedProduct($clonedProductUpdateEvent->getProduct());
|
||||
|
||||
// Set clone's template
|
||||
$clonedProductUpdateTemplateEvent = new ProductSetTemplateEvent(
|
||||
$event->getClonedProduct(),
|
||||
$event->getOriginalProduct()->getTemplateId(),
|
||||
$originalProductDefaultPrice->getCurrencyId()
|
||||
);
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_SET_TEMPLATE, $clonedProductUpdateTemplateEvent);
|
||||
}
|
||||
|
||||
public function cloneFeatureCombination(ProductCloneEvent $event)
|
||||
{
|
||||
// Get original product FeatureProduct list
|
||||
$originalProductFeatureList = FeatureProductQuery::create()
|
||||
->findByProductId($event->getOriginalProduct()->getId());
|
||||
|
||||
// Set clone product FeatureProducts
|
||||
/** @var FeatureProduct $originalProductFeature */
|
||||
foreach ($originalProductFeatureList as $originalProductFeature) {
|
||||
// Get original FeatureAvI18n list
|
||||
$originalProductFeatureAvI18nList = FeatureAvI18nQuery::create()
|
||||
->findById($originalProductFeature->getFeatureAvId());
|
||||
|
||||
/** @var FeatureAvI18n $originalProductFeatureAvI18n */
|
||||
foreach ($originalProductFeatureAvI18nList as $originalProductFeatureAvI18n) {
|
||||
// Create a FeatureProduct for each FeatureAv (not for each FeatureAvI18n)
|
||||
$clonedProductCreateFeatureEvent = new FeatureProductUpdateEvent(
|
||||
$event->getClonedProduct()->getId(),
|
||||
$originalProductFeature->getFeatureId(),
|
||||
$originalProductFeature->getFeatureAvId()
|
||||
);
|
||||
$clonedProductCreateFeatureEvent->setLocale($originalProductFeatureAvI18n->getLocale());
|
||||
|
||||
// If it's a free text value, pass the FeatureAvI18n's title as featureValue to the event
|
||||
if ($originalProductFeature->getFreeTextValue() !== null) {
|
||||
$clonedProductCreateFeatureEvent->setFeatureValue($originalProductFeatureAvI18n->getTitle());
|
||||
$clonedProductCreateFeatureEvent->setIsTextValue(true);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE, $clonedProductCreateFeatureEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function cloneAssociatedContent(ProductCloneEvent $event)
|
||||
{
|
||||
// Get original product associated contents
|
||||
$originalProductAssocConts = ProductAssociatedContentQuery::create()
|
||||
->findByProductId($event->getOriginalProduct()->getId());
|
||||
|
||||
// Set clone product associated contents
|
||||
foreach ($originalProductAssocConts as $originalProductAssocCont) {
|
||||
$clonedProductCreatePAC = new ProductAddContentEvent($event->getClonedProduct(), $originalProductAssocCont->getContentId());
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $clonedProductCreatePAC);
|
||||
}
|
||||
}
|
||||
|
||||
public function cloneAccessories(ProductCloneEvent $event)
|
||||
{
|
||||
// Get original product accessories
|
||||
$originalProductAccessoryList = AccessoryQuery::create()
|
||||
->findByProductId($event->getOriginalProduct()->getId());
|
||||
|
||||
// Set clone product accessories
|
||||
foreach ($originalProductAccessoryList as $originalProductAccessory) {
|
||||
$clonedProductAddAccessoryEvent = new ProductAddAccessoryEvent($event->getClonedProduct(), $originalProductAccessory->getAccessory());
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_ACCESSORY, $clonedProductAddAccessoryEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/***************
|
||||
* END CLONING *
|
||||
***************/
|
||||
|
||||
/**
|
||||
* Change a product
|
||||
*
|
||||
* @param \Thelia\Core\Event\Product\ProductUpdateEvent $event
|
||||
* @throws PropelException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update(ProductUpdateEvent $event)
|
||||
{
|
||||
if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) {
|
||||
$con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$prevRef = $product->getRef();
|
||||
|
||||
$product
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->setRef($event->getRef())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->setVisible($event->getVisible() ? 1 : 0)
|
||||
->setVirtual($event->getVirtual() ? 1 : 0)
|
||||
->setBrandId($event->getBrandId() <= 0 ? null : $event->getBrandId())
|
||||
|
||||
->save($con)
|
||||
;
|
||||
|
||||
// Update default PSE (if product has no attributes and the product's ref change)
|
||||
$defaultPseRefChange = $prevRef !== $product->getRef()
|
||||
&& 0 === $product->getDefaultSaleElements()->countAttributeCombinations();
|
||||
if ($defaultPseRefChange) {
|
||||
$defaultPse = $product->getDefaultSaleElements();
|
||||
$defaultPse->setRef($product->getRef())->save();
|
||||
}
|
||||
|
||||
// Update default category (if required)
|
||||
$product->setDefaultCategory($event->getDefaultCategory());
|
||||
|
||||
$event->setProduct($product);
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UpdateSeoEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdateSeo(ProductQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Product\ProductDeleteEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(ProductDeleteEvent $event)
|
||||
{
|
||||
if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) {
|
||||
$con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$fileList = ['images' => [], 'documentList' => []];
|
||||
|
||||
// Get product's files to delete after product deletion
|
||||
$fileList['images']['list'] = ProductImageQuery::create()
|
||||
->findByProductId($event->getProductId());
|
||||
$fileList['images']['type'] = TheliaEvents::IMAGE_DELETE;
|
||||
|
||||
$fileList['documentList']['list'] = ProductDocumentQuery::create()
|
||||
->findByProductId($event->getProductId());
|
||||
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
||||
|
||||
// Delete free_text_feature AV (see issue #2061)
|
||||
$featureAvs = FeatureAvQuery::create()
|
||||
->useFeatureProductQuery()
|
||||
->filterByFreeTextValue(true)
|
||||
->filterByProductId($event->getProductId())
|
||||
->endUse()
|
||||
->find($con)
|
||||
;
|
||||
|
||||
foreach ($featureAvs as $featureAv) {
|
||||
$featureAv
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->delete($con)
|
||||
;
|
||||
}
|
||||
|
||||
// Delete product
|
||||
$product
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->delete($con)
|
||||
;
|
||||
|
||||
$event->setProduct($product);
|
||||
|
||||
// Dispatch delete product's files event
|
||||
foreach ($fileList as $fileTypeList) {
|
||||
foreach ($fileTypeList['list'] as $fileToDelete) {
|
||||
$fileDeleteEvent = new FileDeleteEvent($fileToDelete);
|
||||
$this->eventDispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle product visibility. No form used here
|
||||
*
|
||||
* @param ProductToggleVisibilityEvent $event
|
||||
*/
|
||||
public function toggleVisibility(ProductToggleVisibilityEvent $event)
|
||||
{
|
||||
$product = $event->getProduct();
|
||||
|
||||
$product
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->setVisible($product->getVisible() ? false : true)
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setProduct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdateDelegatePosition(
|
||||
ProductCategoryQuery::create()
|
||||
->filterByProductId($event->getObjectId())
|
||||
->filterByCategoryId($event->getReferrerId()),
|
||||
$event,
|
||||
$dispatcher
|
||||
);
|
||||
}
|
||||
|
||||
public function addContent(ProductAddContentEvent $event)
|
||||
{
|
||||
if (ProductAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByProduct($event->getProduct())->count() <= 0) {
|
||||
$content = new ProductAssociatedContent();
|
||||
|
||||
$content
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->setProduct($event->getProduct())
|
||||
->setContentId($event->getContentId())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeContent(ProductDeleteContentEvent $event)
|
||||
{
|
||||
$content = ProductAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByProduct($event->getProduct())->findOne()
|
||||
;
|
||||
|
||||
if ($content !== null) {
|
||||
$content
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->delete()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function addCategory(ProductAddCategoryEvent $event)
|
||||
{
|
||||
if (ProductCategoryQuery::create()
|
||||
->filterByProduct($event->getProduct())
|
||||
->filterByCategoryId($event->getCategoryId())
|
||||
->count() <= 0) {
|
||||
$productCategory = (new ProductCategory())
|
||||
->setProduct($event->getProduct())
|
||||
->setCategoryId($event->getCategoryId())
|
||||
->setDefaultCategory(false);
|
||||
|
||||
$productCategory
|
||||
->setPosition($productCategory->getNextPosition())
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function removeCategory(ProductDeleteCategoryEvent $event)
|
||||
{
|
||||
$productCategory = ProductCategoryQuery::create()
|
||||
->filterByProduct($event->getProduct())
|
||||
->filterByCategoryId($event->getCategoryId())
|
||||
->findOne();
|
||||
|
||||
if ($productCategory != null) {
|
||||
$productCategory->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function addAccessory(ProductAddAccessoryEvent $event)
|
||||
{
|
||||
if (AccessoryQuery::create()
|
||||
->filterByAccessory($event->getAccessoryId())
|
||||
->filterByProductId($event->getProduct()->getId())->count() <= 0) {
|
||||
$accessory = new Accessory();
|
||||
|
||||
$accessory
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->setProductId($event->getProduct()->getId())
|
||||
->setAccessory($event->getAccessoryId())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeAccessory(ProductDeleteAccessoryEvent $event)
|
||||
{
|
||||
$accessory = AccessoryQuery::create()
|
||||
->filterByAccessory($event->getAccessoryId())
|
||||
->filterByProductId($event->getProduct()->getId())->findOne()
|
||||
;
|
||||
|
||||
if ($accessory !== null) {
|
||||
$accessory
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->delete()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function setProductTemplate(ProductSetTemplateEvent $event)
|
||||
{
|
||||
$con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$product = $event->getProduct();
|
||||
|
||||
// Delete all product feature relations
|
||||
if (null !== $featureProducts = FeatureProductQuery::create()->findByProductId($product->getId())) {
|
||||
/** @var \Thelia\Model\FeatureProduct $featureProduct */
|
||||
foreach ($featureProducts as $featureProduct) {
|
||||
$eventDelete = new FeatureProductDeleteEvent($product->getId(), $featureProduct->getFeatureId());
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $eventDelete);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all product attributes sale elements
|
||||
AttributeCombinationQuery::create()
|
||||
->filterByProductSaleElements($product->getProductSaleElementss())
|
||||
->delete($con)
|
||||
;
|
||||
|
||||
//Delete all productSaleElements except the default one (to keep price, weight, ean, etc...)
|
||||
ProductSaleElementsQuery::create()
|
||||
->filterByProduct($product)
|
||||
->filterByIsDefault(1, Criteria::NOT_EQUAL)
|
||||
->delete($con)
|
||||
;
|
||||
|
||||
// Update the product template
|
||||
$template_id = $event->getTemplateId();
|
||||
|
||||
// Set it to null if it's zero.
|
||||
if ($template_id <= 0) {
|
||||
$template_id = null;
|
||||
}
|
||||
|
||||
$product->setTemplateId($template_id)->save($con);
|
||||
|
||||
//Be sure that the product has a default productSaleElements
|
||||
/** @var \Thelia\Model\ProductSaleElements $defaultPse */
|
||||
if (null == $defaultPse = ProductSaleElementsQuery::create()
|
||||
->filterByProduct($product)
|
||||
->filterByIsDefault(1)
|
||||
->findOne()) {
|
||||
// Create a new default product sale element
|
||||
$product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true);
|
||||
}
|
||||
|
||||
$product->clearProductSaleElementss();
|
||||
|
||||
$event->setProduct($product);
|
||||
|
||||
// Store all the stuff !
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollBack();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes accessry position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateAccessoryPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdatePosition(AccessoryQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return Object
|
||||
*/
|
||||
public function updateContentPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
return $this->genericUpdatePosition(ProductAssociatedContentQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value of a product feature.
|
||||
*
|
||||
* @param FeatureProductUpdateEvent $event
|
||||
*/
|
||||
public function updateFeatureProductValue(FeatureProductUpdateEvent $event)
|
||||
{
|
||||
// Prepare the FeatureAv's ID
|
||||
$featureAvId = $event->getFeatureValue();
|
||||
|
||||
// Search for existing FeatureProduct
|
||||
$featureProductQuery = FeatureProductQuery::create()
|
||||
->filterByProductId($event->getProductId())
|
||||
->filterByFeatureId($event->getFeatureId())
|
||||
;
|
||||
|
||||
// If it's not a free text value, we can filter by the event's featureValue (which is an ID)
|
||||
if ($event->getFeatureValue() !== null && $event->getIsTextValue() === false) {
|
||||
$featureProductQuery->filterByFeatureAvId($featureAvId);
|
||||
}
|
||||
|
||||
$featureProduct = $featureProductQuery->findOne();
|
||||
|
||||
// If the FeatureProduct does not exist, create it
|
||||
if ($featureProduct === null) {
|
||||
$featureProduct = new FeatureProduct();
|
||||
|
||||
$featureProduct
|
||||
->setDispatcher($this->eventDispatcher)
|
||||
->setProductId($event->getProductId())
|
||||
->setFeatureId($event->getFeatureId())
|
||||
;
|
||||
|
||||
// If it's a free text value, create a FeatureAv to handle i18n
|
||||
if ($event->getIsTextValue() === true) {
|
||||
$featureProduct->setFreeTextValue(true);
|
||||
|
||||
$createFeatureAvEvent = new FeatureAvCreateEvent();
|
||||
$createFeatureAvEvent
|
||||
->setFeatureId($event->getFeatureId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getFeatureValue());
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::FEATURE_AV_CREATE, $createFeatureAvEvent);
|
||||
|
||||
$featureAvId = $createFeatureAvEvent->getFeatureAv()->getId();
|
||||
}
|
||||
} // Else if the FeatureProduct exists and is a free text value
|
||||
elseif ($featureProduct !== null && $event->getIsTextValue() === true) {
|
||||
// Get the FeatureAv
|
||||
$freeTextFeatureAv = FeatureAvQuery::create()
|
||||
->filterByFeatureProduct($featureProduct)
|
||||
->findOneByFeatureId($event->getFeatureId());
|
||||
|
||||
// Get the FeatureAvI18n by locale
|
||||
$freeTextFeatureAvI18n = FeatureAvI18nQuery::create()
|
||||
->filterById($freeTextFeatureAv->getId())
|
||||
->findOneByLocale($event->getLocale());
|
||||
|
||||
// Nothing found for this lang and the new value is not empty : create FeatureAvI18n
|
||||
if ($freeTextFeatureAvI18n === null && !empty($featureAvId)) {
|
||||
$featureAvI18n = new FeatureAvI18n();
|
||||
$featureAvI18n
|
||||
->setId($freeTextFeatureAv->getId())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getFeatureValue())
|
||||
->save();
|
||||
|
||||
$featureAvId = $featureAvI18n->getId();
|
||||
} // Else if i18n exists but new value is empty : delete FeatureAvI18n
|
||||
elseif ($freeTextFeatureAvI18n !== null && empty($featureAvId)) {
|
||||
$freeTextFeatureAvI18n->delete();
|
||||
|
||||
// Check if there are still some FeatureAvI18n for this FeatureAv
|
||||
$freeTextFeatureAvI18ns = FeatureAvI18nQuery::create()
|
||||
->findById($freeTextFeatureAv->getId());
|
||||
|
||||
// If there are no more FeatureAvI18ns for this FeatureAv, remove the corresponding FeatureProduct & FeatureAv
|
||||
if (count($freeTextFeatureAvI18ns) == 0) {
|
||||
$deleteFeatureProductEvent = new FeatureProductDeleteEvent($event->getProductId(), $event->getFeatureId());
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $deleteFeatureProductEvent);
|
||||
|
||||
$deleteFeatureAvEvent = new FeatureAvDeleteEvent($freeTextFeatureAv->getId());
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::FEATURE_AV_DELETE, $deleteFeatureAvEvent);
|
||||
|
||||
return;
|
||||
}
|
||||
} // Else if a FeatureAvI18n is found and the new value is not empty : update existing FeatureAvI18n
|
||||
elseif ($freeTextFeatureAvI18n !== null && !empty($featureAvId)) {
|
||||
$freeTextFeatureAvI18n->setTitle($featureAvId);
|
||||
$freeTextFeatureAvI18n->save();
|
||||
|
||||
$featureAvId = $freeTextFeatureAvI18n->getId();
|
||||
}
|
||||
} // Else the FeatureProduct exists and is not a free text value
|
||||
else {
|
||||
$featureAvId = $event->getFeatureValue();
|
||||
}
|
||||
|
||||
$featureProduct->setFeatureAvId($featureAvId);
|
||||
|
||||
$featureProduct->save();
|
||||
|
||||
$event->setFeatureProduct($featureProduct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product feature value
|
||||
*
|
||||
* @param FeatureProductDeleteEvent $event
|
||||
*/
|
||||
public function deleteFeatureProductValue(FeatureProductDeleteEvent $event)
|
||||
{
|
||||
FeatureProductQuery::create()
|
||||
->filterByProductId($event->getProductId())
|
||||
->filterByFeatureId($event->getFeatureId())
|
||||
->delete()
|
||||
;
|
||||
}
|
||||
|
||||
public function deleteImagePSEAssociations(FileDeleteEvent $event)
|
||||
{
|
||||
$model = $event->getFileToDelete();
|
||||
|
||||
if ($model instanceof ProductImage) {
|
||||
$model->getProductSaleElementsProductImages()->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteDocumentPSEAssociations(FileDeleteEvent $event)
|
||||
{
|
||||
$model = $event->getFileToDelete();
|
||||
|
||||
if ($model instanceof ProductDocument) {
|
||||
$model->getProductSaleElementsProductDocuments()->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::PRODUCT_CREATE => array("create", 128),
|
||||
TheliaEvents::PRODUCT_CLONE => array("cloneProduct", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE => array("update", 128),
|
||||
TheliaEvents::PRODUCT_DELETE => array("delete", 128),
|
||||
TheliaEvents::PRODUCT_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_UPDATE_POSITION => array("updatePosition", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE_SEO => array("updateSeo", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_ADD_CONTENT => array("addContent", 128),
|
||||
TheliaEvents::PRODUCT_REMOVE_CONTENT => array("removeContent", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE_CONTENT_POSITION => array("updateContentPosition", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_ADD_ACCESSORY => array("addAccessory", 128),
|
||||
TheliaEvents::PRODUCT_REMOVE_ACCESSORY => array("removeAccessory", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE_ACCESSORY_POSITION => array("updateAccessoryPosition", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_ADD_CATEGORY => array("addCategory", 128),
|
||||
TheliaEvents::PRODUCT_REMOVE_CATEGORY => array("removeCategory", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_SET_TEMPLATE => array("setProductTemplate", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 128),
|
||||
TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE => array("deleteFeatureProductValue", 128),
|
||||
|
||||
// Those two have to be executed before
|
||||
TheliaEvents::IMAGE_DELETE => array("deleteImagePSEAssociations", 192),
|
||||
TheliaEvents::DOCUMENT_DELETE => array("deleteDocumentPSEAssociations", 192),
|
||||
);
|
||||
}
|
||||
}
|
||||
484
core/lib/Thelia/Action/ProductSaleElement.php
Normal file
484
core/lib/Thelia/Action/ProductSaleElement.php
Normal file
@@ -0,0 +1,484 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Product\ProductCloneEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementCreateEvent;
|
||||
use Thelia\Core\Template\Loop\ProductSaleElementsDocument;
|
||||
use Thelia\Core\Template\Loop\ProductSaleElementsImage;
|
||||
use Thelia\Model\AttributeCombinationQuery;
|
||||
use Thelia\Model\Map\ProductSaleElementsTableMap;
|
||||
use Thelia\Model\ProductDocumentQuery;
|
||||
use Thelia\Model\ProductImageQuery;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
use Thelia\Model\ProductPrice;
|
||||
use Thelia\Model\AttributeCombination;
|
||||
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementDeleteEvent;
|
||||
use Thelia\Model\ProductSaleElementsProductDocument;
|
||||
use Thelia\Model\ProductSaleElementsProductDocumentQuery;
|
||||
use Thelia\Model\ProductSaleElementsProductImage;
|
||||
use Thelia\Model\ProductSaleElementsProductImageQuery;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementUpdateEvent;
|
||||
use Thelia\Model\ProductPriceQuery;
|
||||
use Propel\Runtime\Propel;
|
||||
use Thelia\Model\AttributeAvQuery;
|
||||
use Thelia\Model\Map\AttributeCombinationTableMap;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Thelia\Core\Event\Product\ProductCombinationGenerationEvent;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
|
||||
class ProductSaleElement extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new product sale element, with or without combination
|
||||
*
|
||||
* @param ProductSaleElementCreateEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(ProductSaleElementCreateEvent $event)
|
||||
{
|
||||
$con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Check if we have a PSE without combination, this is the "default" PSE. Attach the combination to this PSE
|
||||
$salesElement = ProductSaleElementsQuery::create()
|
||||
->filterByProductId($event->getProduct()->getId())
|
||||
->joinAttributeCombination(null, Criteria::LEFT_JOIN)
|
||||
->add(AttributeCombinationTableMap::PRODUCT_SALE_ELEMENTS_ID, null, Criteria::ISNULL)
|
||||
->findOne($con);
|
||||
|
||||
if ($salesElement == null) {
|
||||
// Create a new default product sale element
|
||||
$salesElement = $event->getProduct()->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), false);
|
||||
} else {
|
||||
// This (new) one is the default
|
||||
$salesElement->setIsDefault(true)->save($con);
|
||||
}
|
||||
|
||||
// Attach combination, if defined.
|
||||
$combinationAttributes = $event->getAttributeAvList();
|
||||
|
||||
if (count($combinationAttributes) > 0) {
|
||||
foreach ($combinationAttributes as $attributeAvId) {
|
||||
$attributeAv = AttributeAvQuery::create()->findPk($attributeAvId);
|
||||
|
||||
if ($attributeAv !== null) {
|
||||
$attributeCombination = new AttributeCombination();
|
||||
|
||||
$attributeCombination
|
||||
->setAttributeAvId($attributeAvId)
|
||||
->setAttribute($attributeAv->getAttribute())
|
||||
->setProductSaleElements($salesElement)
|
||||
->save($con);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$event->setProductSaleElement($salesElement);
|
||||
|
||||
// Store all the stuff !
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollback();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing product sale element
|
||||
*
|
||||
* @param ProductSaleElementUpdateEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update(ProductSaleElementUpdateEvent $event)
|
||||
{
|
||||
$salesElement = ProductSaleElementsQuery::create()->findPk($event->getProductSaleElementId());
|
||||
|
||||
$con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Update the product's tax rule
|
||||
$event->getProduct()->setTaxRuleId($event->getTaxRuleId())->save($con);
|
||||
|
||||
// If product sale element is not defined, create it.
|
||||
if ($salesElement == null) {
|
||||
$salesElement = new ProductSaleElements();
|
||||
|
||||
$salesElement->setProduct($event->getProduct());
|
||||
}
|
||||
|
||||
// If this PSE is the default one, be sure to have *only one* default for this product
|
||||
if ($event->getIsDefault()) {
|
||||
ProductSaleElementsQuery::create()
|
||||
->filterByProduct($event->getProduct())
|
||||
->filterByIsDefault(true)
|
||||
->filterById($event->getProductSaleElementId(), Criteria::NOT_EQUAL)
|
||||
->update(['IsDefault' => false], $con)
|
||||
;
|
||||
}
|
||||
|
||||
// Update sale element
|
||||
$salesElement
|
||||
->setRef($event->getReference())
|
||||
->setQuantity($event->getQuantity())
|
||||
->setPromo($event->getOnsale())
|
||||
->setNewness($event->getIsnew())
|
||||
->setWeight($event->getWeight())
|
||||
->setIsDefault($event->getIsDefault())
|
||||
->setEanCode($event->getEanCode())
|
||||
->save()
|
||||
;
|
||||
|
||||
// Update/create price for current currency
|
||||
$productPrice = ProductPriceQuery::create()
|
||||
->filterByCurrencyId($event->getCurrencyId())
|
||||
->filterByProductSaleElementsId($salesElement->getId())
|
||||
->findOne($con);
|
||||
|
||||
// If price is not defined, create it.
|
||||
if ($productPrice == null) {
|
||||
$productPrice = new ProductPrice();
|
||||
|
||||
$productPrice
|
||||
->setProductSaleElements($salesElement)
|
||||
->setCurrencyId($event->getCurrencyId())
|
||||
;
|
||||
}
|
||||
|
||||
// Check if we have to store the price
|
||||
$productPrice->setFromDefaultCurrency($event->getFromDefaultCurrency());
|
||||
|
||||
if ($event->getFromDefaultCurrency() == 0) {
|
||||
// Store the price
|
||||
$productPrice
|
||||
->setPromoPrice($event->getSalePrice())
|
||||
->setPrice($event->getPrice())
|
||||
;
|
||||
} else {
|
||||
// Do not store the price.
|
||||
$productPrice
|
||||
->setPromoPrice(0)
|
||||
->setPrice(0)
|
||||
;
|
||||
}
|
||||
|
||||
$productPrice->save($con);
|
||||
|
||||
// Store all the stuff !
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollback();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product sale element
|
||||
*
|
||||
* @param ProductSaleElementDeleteEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(ProductSaleElementDeleteEvent $event)
|
||||
{
|
||||
if (null !== $pse = ProductSaleElementsQuery::create()->findPk($event->getProductSaleElementId())) {
|
||||
$product = $pse->getProduct();
|
||||
|
||||
$con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$pse->delete($con);
|
||||
|
||||
if ($product->countSaleElements($con) <= 0) {
|
||||
// If we just deleted the last PSE, create a default one
|
||||
$product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true);
|
||||
} elseif ($pse->getIsDefault()) {
|
||||
// If we deleted the default PSE, make the last created one the default
|
||||
$newDefaultPse = ProductSaleElementsQuery::create()
|
||||
->filterByProductId($product->getId())
|
||||
->filterById($pse->getId(), Criteria::NOT_EQUAL)
|
||||
->orderByCreatedAt(Criteria::DESC)
|
||||
->findOne($con)
|
||||
;
|
||||
|
||||
if (null !== $newDefaultPse) {
|
||||
$newDefaultPse->setIsDefault(true)->save($con);
|
||||
}
|
||||
}
|
||||
|
||||
// Store all the stuff !
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollback();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate combinations. All existing combinations for the product are deleted.
|
||||
*
|
||||
* @param ProductCombinationGenerationEvent $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function generateCombinations(ProductCombinationGenerationEvent $event)
|
||||
{
|
||||
$con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Delete all product's productSaleElement
|
||||
ProductSaleElementsQuery::create()->filterByProductId($event->product->getId())->delete();
|
||||
|
||||
$isDefault = true;
|
||||
|
||||
// Create all combinations
|
||||
foreach ($event->getCombinations() as $combinationAttributesAvIds) {
|
||||
// Create the PSE
|
||||
$saleElement = $event->getProduct()->createProductSaleElement(
|
||||
$con,
|
||||
$event->getWeight(),
|
||||
$event->getPrice(),
|
||||
$event->getSalePrice(),
|
||||
$event->getCurrencyId(),
|
||||
$isDefault,
|
||||
$event->getOnsale(),
|
||||
$event->getIsnew(),
|
||||
$event->getQuantity(),
|
||||
$event->getEanCode(),
|
||||
$event->getReference()
|
||||
);
|
||||
|
||||
$isDefault = false;
|
||||
|
||||
$this->createCombination($con, $saleElement, $combinationAttributesAvIds);
|
||||
}
|
||||
|
||||
// Store all the stuff !
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollback();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a combination for a given product sale element
|
||||
*
|
||||
* @param ConnectionInterface $con the Propel connection
|
||||
* @param ProductSaleElements $salesElement the product sale element
|
||||
* @param array $combinationAttributes an array oif attributes av IDs
|
||||
*/
|
||||
protected function createCombination(ConnectionInterface $con, ProductSaleElements $salesElement, $combinationAttributes)
|
||||
{
|
||||
foreach ($combinationAttributes as $attributeAvId) {
|
||||
$attributeAv = AttributeAvQuery::create()->findPk($attributeAvId);
|
||||
|
||||
if ($attributeAv !== null) {
|
||||
$attributeCombination = new AttributeCombination();
|
||||
|
||||
$attributeCombination
|
||||
->setAttributeAvId($attributeAvId)
|
||||
->setAttribute($attributeAv->getAttribute())
|
||||
->setProductSaleElements($salesElement)
|
||||
->save($con);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************
|
||||
* CLONING PROCESS *
|
||||
*******************/
|
||||
|
||||
/**
|
||||
* Clone product's PSEs and associated datas
|
||||
*
|
||||
* @param ProductCloneEvent $event
|
||||
*/
|
||||
public function clonePSE(ProductCloneEvent $event)
|
||||
{
|
||||
$clonedProduct = $event->getClonedProduct();
|
||||
|
||||
// Get original product's PSEs
|
||||
$originalProductPSEs = ProductSaleElementsQuery::create()
|
||||
->orderByIsDefault(Criteria::DESC)
|
||||
->findByProductId($event->getOriginalProduct()->getId());
|
||||
|
||||
/**
|
||||
* Handle PSEs
|
||||
*
|
||||
* @var int $key
|
||||
* @var ProductSaleElements $originalProductPSE
|
||||
*/
|
||||
foreach ($originalProductPSEs as $key => $originalProductPSE) {
|
||||
$currencyId = ProductPriceQuery::create()
|
||||
->filterByProductSaleElementsId($originalProductPSE->getId())
|
||||
->select('CURRENCY_ID')
|
||||
->findOne();
|
||||
|
||||
// The default PSE, created at the same time as the clone product, is overwritten
|
||||
$clonedProductPSEId = $this->createClonePSE($event, $originalProductPSE, $currencyId);
|
||||
|
||||
$this->updateClonePSE($event, $clonedProductPSEId, $originalProductPSE, $key);
|
||||
|
||||
// PSE associated images
|
||||
$originalProductPSEImages = ProductSaleElementsProductImageQuery::create()
|
||||
->findByProductSaleElementsId($originalProductPSE->getId());
|
||||
|
||||
if (null !== $originalProductPSEImages) {
|
||||
$this->clonePSEAssociatedFiles($clonedProduct->getId(), $clonedProductPSEId, $originalProductPSEImages, $type = 'image');
|
||||
}
|
||||
|
||||
// PSE associated documents
|
||||
$originalProductPSEDocuments = ProductSaleElementsProductDocumentQuery::create()
|
||||
->findByProductSaleElementsId($originalProductPSE->getId());
|
||||
|
||||
if (null !== $originalProductPSEDocuments) {
|
||||
$this->clonePSEAssociatedFiles($clonedProduct->getId(), $clonedProductPSEId, $originalProductPSEDocuments, $type = 'document');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createClonePSE(ProductCloneEvent $event, ProductSaleElements $originalProductPSE, $currencyId)
|
||||
{
|
||||
$attributeCombinationList = AttributeCombinationQuery::create()
|
||||
->filterByProductSaleElementsId($originalProductPSE->getId())
|
||||
->select(['ATTRIBUTE_AV_ID'])
|
||||
->find();
|
||||
|
||||
$clonedProductCreatePSEEvent = new ProductSaleElementCreateEvent($event->getClonedProduct(), $attributeCombinationList, $currencyId);
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT, $clonedProductCreatePSEEvent);
|
||||
|
||||
return $clonedProductCreatePSEEvent->getProductSaleElement()->getId();
|
||||
}
|
||||
|
||||
public function updateClonePSE(ProductCloneEvent $event, $clonedProductPSEId, ProductSaleElements $originalProductPSE, $key)
|
||||
{
|
||||
$originalProductPSEPrice = ProductPriceQuery::create()
|
||||
->findOneByProductSaleElementsId($originalProductPSE->getId());
|
||||
|
||||
$clonedProductUpdatePSEEvent = new ProductSaleElementUpdateEvent($event->getClonedProduct(), $clonedProductPSEId);
|
||||
$clonedProductUpdatePSEEvent
|
||||
->setReference($event->getClonedProduct()->getRef().'-'.($key + 1))
|
||||
->setIsdefault($originalProductPSE->getIsDefault())
|
||||
->setFromDefaultCurrency(0)
|
||||
|
||||
->setWeight($originalProductPSE->getWeight())
|
||||
->setQuantity($originalProductPSE->getQuantity())
|
||||
->setOnsale($originalProductPSE->getPromo())
|
||||
->setIsnew($originalProductPSE->getNewness())
|
||||
->setEanCode($originalProductPSE->getEanCode())
|
||||
->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId())
|
||||
|
||||
->setPrice($originalProductPSEPrice->getPrice())
|
||||
->setSalePrice($originalProductPSEPrice->getPromoPrice())
|
||||
->setCurrencyId($originalProductPSEPrice->getCurrencyId());
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $clonedProductUpdatePSEEvent);
|
||||
}
|
||||
|
||||
public function clonePSEAssociatedFiles($clonedProductId, $clonedProductPSEId, $originalProductPSEFiles, $type)
|
||||
{
|
||||
/** @var ProductSaleElementsDocument|ProductSaleElementsImage $originalProductPSEFile */
|
||||
foreach ($originalProductPSEFiles as $originalProductPSEFile) {
|
||||
$originalProductFilePositionQuery = [];
|
||||
$originalProductPSEFileId = null;
|
||||
|
||||
// Get file's original position
|
||||
switch ($type) {
|
||||
case 'image':
|
||||
$originalProductFilePositionQuery = ProductImageQuery::create();
|
||||
$originalProductPSEFileId = $originalProductPSEFile->getProductImageId();
|
||||
break;
|
||||
case 'document':
|
||||
$originalProductFilePositionQuery = ProductDocumentQuery::create();
|
||||
$originalProductPSEFileId = $originalProductPSEFile->getProductDocumentId();
|
||||
break;
|
||||
}
|
||||
$originalProductFilePosition = $originalProductFilePositionQuery
|
||||
->select(['POSITION'])
|
||||
->findPk($originalProductPSEFileId);
|
||||
|
||||
// Get cloned file ID to link to the cloned PSE
|
||||
switch ($type) {
|
||||
case 'image':
|
||||
$clonedProductFileIdToLinkToPSEQuery = ProductImageQuery::create();
|
||||
break;
|
||||
case 'document':
|
||||
$clonedProductFileIdToLinkToPSEQuery = ProductDocumentQuery::create();
|
||||
break;
|
||||
}
|
||||
|
||||
$clonedProductFileIdToLinkToPSE = $clonedProductFileIdToLinkToPSEQuery
|
||||
->filterByProductId($clonedProductId)
|
||||
->filterByPosition($originalProductFilePosition)
|
||||
->select(['ID'])
|
||||
->findOne();
|
||||
|
||||
// Save association
|
||||
switch ($type) {
|
||||
case 'image':
|
||||
$assoc = new ProductSaleElementsProductImage();
|
||||
$assoc->setProductImageId($clonedProductFileIdToLinkToPSE);
|
||||
break;
|
||||
case 'document':
|
||||
$assoc = new ProductSaleElementsProductDocument();
|
||||
$assoc->setProductDocumentId($clonedProductFileIdToLinkToPSE);
|
||||
break;
|
||||
}
|
||||
$assoc
|
||||
->setProductSaleElementsId($clonedProductPSEId)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
/***************
|
||||
* END CLONING *
|
||||
***************/
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT => array("create", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => array("update", 128),
|
||||
TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT => array("delete", 128),
|
||||
TheliaEvents::PRODUCT_COMBINATION_GENERATION => array("generateCombinations", 128),
|
||||
TheliaEvents::PSE_CLONE => array("clonePSE", 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
151
core/lib/Thelia/Action/Profile.php
Normal file
151
core/lib/Thelia/Action/Profile.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Profile\ProfileEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Security\AccessManager;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Model\Profile as ProfileModel;
|
||||
use Thelia\Model\ProfileModule;
|
||||
use Thelia\Model\ProfileModuleQuery;
|
||||
use Thelia\Model\ProfileQuery;
|
||||
use Thelia\Model\ProfileResource;
|
||||
use Thelia\Model\ProfileResourceQuery;
|
||||
use Thelia\Model\ResourceQuery;
|
||||
|
||||
class Profile extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @param ProfileEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(ProfileEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$profile = new ProfileModel();
|
||||
|
||||
$profile
|
||||
->setDispatcher($dispatcher)
|
||||
->setCode($event->getCode())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
;
|
||||
|
||||
$profile->save();
|
||||
|
||||
$event->setProfile($profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProfileEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(ProfileEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) {
|
||||
$profile
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setChapo($event->getChapo())
|
||||
->setDescription($event->getDescription())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
;
|
||||
|
||||
$profile->save();
|
||||
|
||||
$event->setProfile($profile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProfileEvent $event
|
||||
*/
|
||||
public function updateResourceAccess(ProfileEvent $event)
|
||||
{
|
||||
if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) {
|
||||
ProfileResourceQuery::create()->filterByProfileId($event->getId())->delete();
|
||||
foreach ($event->getResourceAccess() as $resourceCode => $accesses) {
|
||||
$manager = new AccessManager(0);
|
||||
$manager->build($accesses);
|
||||
|
||||
$profileResource = new ProfileResource();
|
||||
$profileResource->setProfileId($event->getId())
|
||||
->setResource(ResourceQuery::create()->findOneByCode($resourceCode))
|
||||
->setAccess($manager->getAccessValue());
|
||||
|
||||
$profileResource->save();
|
||||
}
|
||||
|
||||
$event->setProfile($profile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProfileEvent $event
|
||||
*/
|
||||
public function updateModuleAccess(ProfileEvent $event)
|
||||
{
|
||||
if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) {
|
||||
ProfileModuleQuery::create()->filterByProfileId($event->getId())->delete();
|
||||
foreach ($event->getModuleAccess() as $moduleCode => $accesses) {
|
||||
$manager = new AccessManager(0);
|
||||
$manager->build($accesses);
|
||||
|
||||
$profileModule = new ProfileModule();
|
||||
$profileModule->setProfileId($event->getId())
|
||||
->setModule(ModuleQuery::create()->findOneByCode($moduleCode))
|
||||
->setAccess($manager->getAccessValue());
|
||||
|
||||
$profileModule->save();
|
||||
}
|
||||
|
||||
$event->setProfile($profile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProfileEvent $event
|
||||
*/
|
||||
public function delete(ProfileEvent $event)
|
||||
{
|
||||
if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) {
|
||||
$profile
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setProfile($profile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::PROFILE_CREATE => array("create", 128),
|
||||
TheliaEvents::PROFILE_UPDATE => array("update", 128),
|
||||
TheliaEvents::PROFILE_DELETE => array("delete", 128),
|
||||
TheliaEvents::PROFILE_RESOURCE_ACCESS_UPDATE => array("updateResourceAccess", 128),
|
||||
TheliaEvents::PROFILE_MODULE_ACCESS_UPDATE => array("updateModuleAccess", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
60
core/lib/Thelia/Action/RedirectException.php
Normal file
60
core/lib/Thelia/Action/RedirectException.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Thelia\Tools\URL;
|
||||
use Thelia\Core\Security\Exception\AuthenticationException;
|
||||
use Thelia\Core\HttpKernel\Exception\RedirectException as ExceptionRedirectException;
|
||||
|
||||
/**
|
||||
* Class RedirectException
|
||||
* @package Thelia\Action
|
||||
* @author manuel raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class RedirectException extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var URL */
|
||||
protected $urlManager;
|
||||
|
||||
public function __construct(URL $urlManager)
|
||||
{
|
||||
$this->urlManager = $urlManager;
|
||||
}
|
||||
|
||||
public function checkRedirectException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
$exception = $event->getException();
|
||||
if ($exception instanceof ExceptionRedirectException) {
|
||||
$response = RedirectResponse::create($exception->getUrl(), $exception->getStatusCode());
|
||||
$event->setResponse($response);
|
||||
} elseif ($exception instanceof AuthenticationException) {
|
||||
// Redirect to the login template
|
||||
$response = RedirectResponse::create($this->urlManager->viewUrl($exception->getLoginTemplate()));
|
||||
$event->setResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::EXCEPTION => array("checkRedirectException", 128),
|
||||
];
|
||||
}
|
||||
}
|
||||
505
core/lib/Thelia/Action/Sale.php
Normal file
505
core/lib/Thelia/Action/Sale.php
Normal file
@@ -0,0 +1,505 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Sale\ProductSaleStatusUpdateEvent;
|
||||
use Thelia\Core\Event\Sale\SaleActiveStatusCheckEvent;
|
||||
use Thelia\Core\Event\Sale\SaleClearStatusEvent;
|
||||
use Thelia\Core\Event\Sale\SaleCreateEvent;
|
||||
use Thelia\Core\Event\Sale\SaleDeleteEvent;
|
||||
use Thelia\Core\Event\Sale\SaleToggleActivityEvent;
|
||||
use Thelia\Core\Event\Sale\SaleUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Base\ProductPriceQuery;
|
||||
use Thelia\Model\Country as CountryModel;
|
||||
use Thelia\Model\Map\SaleTableMap;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Model\Sale as SaleModel;
|
||||
use Thelia\Model\SaleOffsetCurrency;
|
||||
use Thelia\Model\SaleOffsetCurrencyQuery;
|
||||
use Thelia\Model\SaleProduct;
|
||||
use Thelia\Model\SaleProductQuery;
|
||||
use Thelia\Model\SaleQuery;
|
||||
use Thelia\TaxEngine\Calculator;
|
||||
|
||||
/**
|
||||
* Class Sale
|
||||
*
|
||||
* @package Thelia\Action
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class Sale extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Update PSE for a given product
|
||||
*
|
||||
* @param array $pseList an array of priduct sale elements
|
||||
* @param bool $promoStatus true if the PSEs are on sale, false otherwise
|
||||
* @param int $offsetType the offset type, see SaleModel::OFFSET_* constants
|
||||
* @param Calculator $taxCalculator the tax calculator
|
||||
* @param array $saleOffsetByCurrency an array of price offset for each currency (currency ID => offset_amount)
|
||||
* @param ConnectionInterface $con
|
||||
*/
|
||||
protected function updateProductSaleElementsPrices($pseList, $promoStatus, $offsetType, Calculator $taxCalculator, $saleOffsetByCurrency, ConnectionInterface $con)
|
||||
{
|
||||
/** @var ProductSaleElements $pse */
|
||||
foreach ($pseList as $pse) {
|
||||
if ($pse->getPromo()!= $promoStatus) {
|
||||
$pse
|
||||
->setPromo($promoStatus)
|
||||
->save($con)
|
||||
;
|
||||
}
|
||||
|
||||
/** @var SaleOffsetCurrency $offsetByCurrency */
|
||||
foreach ($saleOffsetByCurrency as $currencyId => $offset) {
|
||||
$productPrice = ProductPriceQuery::create()
|
||||
->filterByProductSaleElementsId($pse->getId())
|
||||
->filterByCurrencyId($currencyId)
|
||||
->findOne($con);
|
||||
|
||||
if (null !== $productPrice) {
|
||||
// Get the taxed price
|
||||
$priceWithTax = $taxCalculator->getTaxedPrice($productPrice->getPrice());
|
||||
|
||||
// Remove the price offset to get the taxed promo price
|
||||
switch ($offsetType) {
|
||||
case SaleModel::OFFSET_TYPE_AMOUNT:
|
||||
$promoPrice = max(0, $priceWithTax - $offset);
|
||||
break;
|
||||
|
||||
case SaleModel::OFFSET_TYPE_PERCENTAGE:
|
||||
$promoPrice = $priceWithTax * (1 - $offset / 100);
|
||||
break;
|
||||
|
||||
default:
|
||||
$promoPrice = $priceWithTax;
|
||||
}
|
||||
|
||||
// and then get the untaxed promo price.
|
||||
$promoPrice = $taxCalculator->getUntaxedPrice($promoPrice);
|
||||
|
||||
$productPrice
|
||||
->setPromoPrice($promoPrice)
|
||||
->save($con)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Update the promo status of the sale's selected products and combinations
|
||||
*
|
||||
* @param ProductSaleStatusUpdateEvent $event
|
||||
* @throws \RuntimeException
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function updateProductsSaleStatus(ProductSaleStatusUpdateEvent $event)
|
||||
{
|
||||
$taxCalculator = new Calculator();
|
||||
|
||||
$sale = $event->getSale();
|
||||
|
||||
// Get all selected product sale elements for this sale
|
||||
if (null !== $saleProducts = SaleProductQuery::create()->filterBySale($sale)->orderByProductId()) {
|
||||
$saleOffsetByCurrency = $sale->getPriceOffsets();
|
||||
|
||||
$offsetType = $sale->getPriceOffsetType();
|
||||
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
/** @var SaleProduct $saleProduct */
|
||||
foreach ($saleProducts as $saleProduct) {
|
||||
// Reset all sale status on product's PSE
|
||||
ProductSaleElementsQuery::create()
|
||||
->filterByProductId($saleProduct->getProductId())
|
||||
->update([ 'Promo' => false], $con)
|
||||
;
|
||||
|
||||
$taxCalculator->load(
|
||||
$saleProduct->getProduct($con),
|
||||
CountryModel::getShopLocation()
|
||||
);
|
||||
|
||||
$attributeAvId = $saleProduct->getAttributeAvId();
|
||||
|
||||
$pseRequest = ProductSaleElementsQuery::create()
|
||||
->filterByProductId($saleProduct->getProductId())
|
||||
;
|
||||
|
||||
// If no attribute AV id is defined, consider ALL product combinations
|
||||
if (! is_null($attributeAvId)) {
|
||||
// Find PSE attached to combination containing this attribute av :
|
||||
// SELECT * from product_sale_elements pse
|
||||
// left join attribute_combination ac on ac.product_sale_elements_id = pse.id
|
||||
// where pse.product_id=363
|
||||
// and ac.attribute_av_id = 7
|
||||
// group by pse.id
|
||||
|
||||
$pseRequest
|
||||
->useAttributeCombinationQuery(null, Criteria::LEFT_JOIN)
|
||||
->filterByAttributeAvId($attributeAvId)
|
||||
->endUse()
|
||||
;
|
||||
}
|
||||
|
||||
$pseList = $pseRequest->find();
|
||||
|
||||
if (null !== $pseList) {
|
||||
$this->updateProductSaleElementsPrices(
|
||||
$pseList,
|
||||
$sale->getActive(),
|
||||
$offsetType,
|
||||
$taxCalculator,
|
||||
$saleOffsetByCurrency,
|
||||
$con
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Sale
|
||||
*
|
||||
* @param SaleCreateEvent $event
|
||||
*/
|
||||
public function create(SaleCreateEvent $event)
|
||||
{
|
||||
$sale = new SaleModel();
|
||||
|
||||
$sale
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setSaleLabel($event->getSaleLabel())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setSale($sale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process update sale
|
||||
*
|
||||
* @param SaleUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function update(SaleUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $sale = SaleQuery::create()->findPk($event->getSaleId())) {
|
||||
$sale->setDispatcher($dispatcher);
|
||||
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Disable all promo flag on sale's currently selected products,
|
||||
// to reset promo status of the products that have been removed from the selection.
|
||||
$sale->setActive(false);
|
||||
|
||||
$now = new \DateTime();
|
||||
$startDate = $event->getStartDate();
|
||||
$endDate = $event->getEndDate();
|
||||
|
||||
$update = ($startDate <= $now && $now <= $endDate);
|
||||
|
||||
if ($update) {
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
}
|
||||
|
||||
$sale
|
||||
->setActive($event->getActive())
|
||||
->setStartDate($startDate)
|
||||
->setEndDate($endDate)
|
||||
->setPriceOffsetType($event->getPriceOffsetType())
|
||||
->setDisplayInitialPrice($event->getDisplayInitialPrice())
|
||||
->setLocale($event->getLocale())
|
||||
->setSaleLabel($event->getSaleLabel())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
->save($con)
|
||||
;
|
||||
|
||||
$event->setSale($sale);
|
||||
|
||||
// Update price offsets
|
||||
SaleOffsetCurrencyQuery::create()->filterBySaleId($sale->getId())->delete($con);
|
||||
|
||||
foreach ($event->getPriceOffsets() as $currencyId => $priceOffset) {
|
||||
$saleOffset = new SaleOffsetCurrency();
|
||||
|
||||
$saleOffset
|
||||
->setCurrencyId($currencyId)
|
||||
->setSaleId($sale->getId())
|
||||
->setPriceOffsetValue($priceOffset)
|
||||
->save($con)
|
||||
;
|
||||
}
|
||||
|
||||
// Update products
|
||||
SaleProductQuery::create()->filterBySaleId($sale->getId())->delete($con);
|
||||
|
||||
$productAttributesArray = $event->getProductAttributes();
|
||||
|
||||
foreach ($event->getProducts() as $productId) {
|
||||
if (isset($productAttributesArray[$productId])) {
|
||||
foreach ($productAttributesArray[$productId] as $attributeId) {
|
||||
$saleProduct = new SaleProduct();
|
||||
|
||||
$saleProduct
|
||||
->setSaleId($sale->getId())
|
||||
->setProductId($productId)
|
||||
->setAttributeAvId($attributeId)
|
||||
->save($con)
|
||||
;
|
||||
}
|
||||
} else {
|
||||
$saleProduct = new SaleProduct();
|
||||
|
||||
$saleProduct
|
||||
->setSaleId($sale->getId())
|
||||
->setProductId($productId)
|
||||
->setAttributeAvId(null)
|
||||
->save($con)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($update) {
|
||||
// Update related products sale status
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Sale activity
|
||||
*
|
||||
* @param SaleToggleActivityEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function toggleActivity(SaleToggleActivityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$sale = $event->getSale();
|
||||
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$sale
|
||||
->setDispatcher($dispatcher)
|
||||
->setActive(!$sale->getActive())
|
||||
->save($con);
|
||||
|
||||
// Update related products sale status
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
|
||||
$event->setSale($sale);
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a sale
|
||||
*
|
||||
* @param SaleDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function delete(SaleDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $sale = SaleQuery::create()->findPk($event->getSaleId())) {
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Update related products sale status, if required
|
||||
if ($sale->getActive()) {
|
||||
$sale->setActive(false);
|
||||
|
||||
// Update related products sale status
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
}
|
||||
|
||||
$sale->setDispatcher($dispatcher)->delete($con);
|
||||
|
||||
$event->setSale($sale);
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all sales
|
||||
*
|
||||
* @param SaleClearStatusEvent $event
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function clearStatus(/** @noinspection PhpUnusedParameterInspection */ SaleClearStatusEvent $event)
|
||||
{
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
// Set the active status of all Sales to false
|
||||
SaleQuery::create()
|
||||
->filterByActive(true)
|
||||
->update([ 'Active' => false ], $con)
|
||||
;
|
||||
|
||||
// Reset all sale status on PSE
|
||||
ProductSaleElementsQuery::create()
|
||||
->filterByPromo(true)
|
||||
->update([ 'Promo' => false], $con)
|
||||
;
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method check the activation and deactivation dates of sales, and perform
|
||||
* the required action depending on the current date.
|
||||
*
|
||||
* @param SaleActiveStatusCheckEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function checkSaleActivation(SaleActiveStatusCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
// Disable expired sales
|
||||
if (null !== $salesToDisable = SaleQuery::create()
|
||||
->filterByActive(true)
|
||||
->filterByEndDate($now, Criteria::LESS_THAN)
|
||||
->find()) {
|
||||
/** @var SaleModel $sale */
|
||||
foreach ($salesToDisable as $sale) {
|
||||
$sale->setActive(false)->save();
|
||||
|
||||
// Update related products sale status
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable sales that should be enabled.
|
||||
if (null !== $salesToEnable = SaleQuery::create()
|
||||
->filterByActive(false)
|
||||
->filterByStartDate($now, Criteria::LESS_EQUAL)
|
||||
->filterByEndDate($now, Criteria::GREATER_EQUAL)
|
||||
->find()) {
|
||||
/** @var SaleModel $sale */
|
||||
foreach ($salesToEnable as $sale) {
|
||||
$sale->setActive(true)->save();
|
||||
|
||||
// Update related products sale status
|
||||
$dispatcher->dispatch(
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS,
|
||||
new ProductSaleStatusUpdateEvent($sale)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::SALE_CREATE => array('create', 128),
|
||||
TheliaEvents::SALE_UPDATE => array('update', 128),
|
||||
TheliaEvents::SALE_DELETE => array('delete', 128),
|
||||
|
||||
TheliaEvents::SALE_TOGGLE_ACTIVITY => array('toggleActivity', 128),
|
||||
|
||||
TheliaEvents::SALE_CLEAR_SALE_STATUS => array('clearStatus', 128),
|
||||
|
||||
TheliaEvents::UPDATE_PRODUCT_SALE_STATUS => array('updateProductsSaleStatus', 128),
|
||||
|
||||
TheliaEvents::CHECK_SALE_ACTIVATION_EVENT => array('checkSaleActivation', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
63
core/lib/Thelia/Action/ShippingZone.php
Normal file
63
core/lib/Thelia/Action/ShippingZone.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\ShippingZone\ShippingZoneAddAreaEvent;
|
||||
use Thelia\Core\Event\ShippingZone\ShippingZoneRemoveAreaEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\AreaDeliveryModule;
|
||||
use Thelia\Model\AreaDeliveryModuleQuery;
|
||||
|
||||
/**
|
||||
* Class ShippingZone
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class ShippingZone extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function addArea(ShippingZoneAddAreaEvent $event)
|
||||
{
|
||||
$areaDelivery = new AreaDeliveryModule();
|
||||
|
||||
$areaDelivery
|
||||
->setAreaId($event->getAreaId())
|
||||
->setDeliveryModuleId($event->getShippingZoneId())
|
||||
->save();
|
||||
}
|
||||
|
||||
public function removeArea(ShippingZoneRemoveAreaEvent $event)
|
||||
{
|
||||
$areaDelivery = AreaDeliveryModuleQuery::create()
|
||||
->filterByAreaId($event->getAreaId())
|
||||
->filterByDeliveryModuleId($event->getShippingZoneId())
|
||||
->findOne();
|
||||
|
||||
if ($areaDelivery) {
|
||||
$areaDelivery->delete();
|
||||
} else {
|
||||
throw new \RuntimeException(sprintf('areaDeliveryModule not found with area_id = %d and delivery_module_id = %d', $event->getAreaId(), $event->getShippingZoneId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::SHIPPING_ZONE_ADD_AREA => array('addArea', 128),
|
||||
TheliaEvents::SHIPPING_ZONE_REMOVE_AREA => array('removeArea', 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
103
core/lib/Thelia/Action/State.php
Normal file
103
core/lib/Thelia/Action/State.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\State\StateCreateEvent;
|
||||
use Thelia\Core\Event\State\StateDeleteEvent;
|
||||
use Thelia\Core\Event\State\StateToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\State\StateUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\State as StateModel;
|
||||
use Thelia\Model\StateQuery;
|
||||
|
||||
/**
|
||||
* Class State
|
||||
* @package Thelia\Action
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class State extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(StateCreateEvent $event)
|
||||
{
|
||||
$state = new StateModel();
|
||||
|
||||
$state
|
||||
->setVisible($event->isVisible())
|
||||
->setCountryId($event->getCountry())
|
||||
->setIsocode($event->getIsocode())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setState($state);
|
||||
}
|
||||
|
||||
public function update(StateUpdateEvent $event)
|
||||
{
|
||||
if (null !== $state = StateQuery::create()->findPk($event->getStateId())) {
|
||||
$state
|
||||
->setVisible($event->isVisible())
|
||||
->setCountryId($event->getCountry())
|
||||
->setIsocode($event->getIsocode())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setState($state);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(StateDeleteEvent $event)
|
||||
{
|
||||
if (null !== $state = StateQuery::create()->findPk($event->getStateId())) {
|
||||
$state->delete();
|
||||
|
||||
$event->setState($state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle State visibility
|
||||
*
|
||||
* @param StateToggleVisibilityEvent $event
|
||||
*/
|
||||
public function toggleVisibility(StateToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$state = $event->getState();
|
||||
|
||||
$state
|
||||
->setDispatcher($dispatcher)
|
||||
->setVisible(!$state->getVisible())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setState($state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::STATE_CREATE => array('create', 128),
|
||||
TheliaEvents::STATE_UPDATE => array('update', 128),
|
||||
TheliaEvents::STATE_DELETE => array('delete', 128),
|
||||
TheliaEvents::STATE_TOGGLE_VISIBILITY => array('toggleVisibility', 128)
|
||||
);
|
||||
}
|
||||
}
|
||||
95
core/lib/Thelia/Action/Tax.php
Normal file
95
core/lib/Thelia/Action/Tax.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Tax\TaxEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\Tax as TaxModel;
|
||||
use Thelia\Model\TaxQuery;
|
||||
|
||||
class Tax extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @param TaxEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(TaxEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$tax = new TaxModel();
|
||||
|
||||
$tax
|
||||
->setDispatcher($dispatcher)
|
||||
->setRequirements($event->getRequirements())
|
||||
->setType($event->getType())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
;
|
||||
|
||||
$tax->save();
|
||||
|
||||
$event->setTax($tax);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(TaxEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $tax = TaxQuery::create()->findPk($event->getId())) {
|
||||
$tax
|
||||
->setDispatcher($dispatcher)
|
||||
->setRequirements($event->getRequirements())
|
||||
->setType($event->getType())
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
;
|
||||
|
||||
$tax->save();
|
||||
|
||||
$event->setTax($tax);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxEvent $event
|
||||
*/
|
||||
public function delete(TaxEvent $event)
|
||||
{
|
||||
if (null !== $tax = TaxQuery::create()->findPk($event->getId())) {
|
||||
$tax
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setTax($tax);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::TAX_CREATE => array("create", 128),
|
||||
TheliaEvents::TAX_UPDATE => array("update", 128),
|
||||
TheliaEvents::TAX_DELETE => array("delete", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
205
core/lib/Thelia/Action/TaxRule.php
Normal file
205
core/lib/Thelia/Action/TaxRule.php
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Tax\TaxRuleEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\TaxRuleCountry;
|
||||
use Thelia\Model\TaxRuleCountryQuery;
|
||||
use Thelia\Model\TaxRule as TaxRuleModel;
|
||||
use Thelia\Model\TaxRuleQuery;
|
||||
|
||||
class TaxRule extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @param TaxRuleEvent $event
|
||||
*/
|
||||
public function create(TaxRuleEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$taxRule = new TaxRuleModel();
|
||||
|
||||
$taxRule
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
;
|
||||
|
||||
$taxRule->save();
|
||||
|
||||
$event->setTaxRule($taxRule)->setId($taxRule->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxRuleEvent $event
|
||||
*/
|
||||
public function update(TaxRuleEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) {
|
||||
$taxRule
|
||||
->setDispatcher($dispatcher)
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setTaxRule($taxRule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxRuleEvent $event
|
||||
*/
|
||||
public function updateTaxes(TaxRuleEvent $event)
|
||||
{
|
||||
if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) {
|
||||
$taxList = $this->getArrayFromJson($event->getTaxList());
|
||||
$countryList = $this->getArrayFromJson22Compat($event->getCountryList());
|
||||
$countryDeletedList = $this->getArrayFromJson22Compat($event->getCountryDeletedList());
|
||||
|
||||
/* clean the current tax rule for the countries/states */
|
||||
$deletes = array_merge($countryList, $countryDeletedList);
|
||||
foreach ($deletes as $item) {
|
||||
TaxRuleCountryQuery::create()
|
||||
->filterByTaxRule($taxRule)
|
||||
->filterByCountryId(intval($item[0]), Criteria::EQUAL)
|
||||
->filterByStateId(intval($item[1]) !== 0 ? $item[1] : null, Criteria::EQUAL)
|
||||
->delete();
|
||||
}
|
||||
|
||||
/* for each country */
|
||||
foreach ($countryList as $item) {
|
||||
$position = 1;
|
||||
$countryId = intval($item[0]);
|
||||
$stateId = intval($item[1]);
|
||||
|
||||
/* on applique les nouvelles regles */
|
||||
foreach ($taxList as $tax) {
|
||||
if (is_array($tax)) {
|
||||
foreach ($tax as $samePositionTax) {
|
||||
$taxModel = new TaxRuleCountry();
|
||||
$taxModel->setTaxRule($taxRule)
|
||||
->setCountryId($countryId)
|
||||
->setStateId($stateId ?: null)
|
||||
->setTaxId($samePositionTax)
|
||||
->setPosition($position);
|
||||
$taxModel->save();
|
||||
}
|
||||
} else {
|
||||
$taxModel = new TaxRuleCountry();
|
||||
$taxModel->setTaxRule($taxRule)
|
||||
->setCountryId($countryId)
|
||||
->setStateId($stateId ?: null)
|
||||
->setTaxId($tax)
|
||||
->setPosition($position);
|
||||
$taxModel->save();
|
||||
}
|
||||
$position++;
|
||||
}
|
||||
}
|
||||
|
||||
$event->setTaxRule($taxRule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getArrayFromJson($obj)
|
||||
{
|
||||
if (is_null($obj)) {
|
||||
$obj = [];
|
||||
} else {
|
||||
$obj = is_array($obj)
|
||||
? $obj
|
||||
: json_decode($obj, true);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method ensures compatibility with the 2.2.x country arrays passed throught the TaxRuleEvent
|
||||
*
|
||||
* In 2.2.x, the TaxRuleEvent::getXXXCountryList() methods returned an array of country IDs. [ country ID, country ID ...].
|
||||
* From 2.3.0-alpha1, these functions are expected to return an array of arrays, each one containing a country ID and
|
||||
* a state ID. [ [ country ID, state ID], [ country ID, state ID], ...].
|
||||
*
|
||||
* This method checks the $obj parameter, and create a 2.3.0-alpha1 compatible return value if $obj is expressed using
|
||||
* the 2.2.x form.
|
||||
*
|
||||
* @param array $obj
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getArrayFromJson22Compat($obj)
|
||||
{
|
||||
$obj = $this->getArrayFromJson($obj);
|
||||
|
||||
if (isset($obj[0]) && ! is_array($obj[0])) {
|
||||
$objEx = [];
|
||||
foreach ($obj as $item) {
|
||||
$objEx[] = [$item, 0];
|
||||
}
|
||||
|
||||
return $objEx;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxRuleEvent $event
|
||||
*/
|
||||
public function delete(TaxRuleEvent $event)
|
||||
{
|
||||
if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) {
|
||||
$taxRule
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setTaxRule($taxRule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaxRuleEvent $event
|
||||
*/
|
||||
public function setDefault(TaxRuleEvent $event)
|
||||
{
|
||||
if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) {
|
||||
TaxRuleQuery::create()->update(array(
|
||||
"IsDefault" => 0
|
||||
));
|
||||
|
||||
$taxRule->setIsDefault(1)->save();
|
||||
|
||||
$event->setTaxRule($taxRule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::TAX_RULE_CREATE => array("create", 128),
|
||||
TheliaEvents::TAX_RULE_UPDATE => array("update", 128),
|
||||
TheliaEvents::TAX_RULE_TAXES_UPDATE => array("updateTaxes", 128),
|
||||
TheliaEvents::TAX_RULE_DELETE => array("delete", 128),
|
||||
TheliaEvents::TAX_RULE_SET_DEFAULT => array("setDefault", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
229
core/lib/Thelia/Action/Template.php
Normal file
229
core/lib/Thelia/Action/Template.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Model\CategoryQuery;
|
||||
use Thelia\Model\Map\TemplateTableMap;
|
||||
use Thelia\Model\TemplateQuery;
|
||||
use Thelia\Model\Template as TemplateModel;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Template\TemplateUpdateEvent;
|
||||
use Thelia\Core\Event\Template\TemplateCreateEvent;
|
||||
use Thelia\Core\Event\Template\TemplateDeleteEvent;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Core\Event\Template\TemplateAddAttributeEvent;
|
||||
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
||||
use Thelia\Model\AttributeTemplateQuery;
|
||||
use Thelia\Model\AttributeTemplate;
|
||||
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
||||
use Thelia\Core\Event\Template\TemplateAddFeatureEvent;
|
||||
use Thelia\Model\FeatureTemplateQuery;
|
||||
use Thelia\Model\FeatureTemplate;
|
||||
|
||||
class Template extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new template entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Template\TemplateCreateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function create(TemplateCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$template = new TemplateModel();
|
||||
|
||||
$template
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setName($event->getTemplateName())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setTemplate($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product template
|
||||
*
|
||||
* @param \Thelia\Core\Event\Template\TemplateUpdateEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function update(TemplateUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== $template = TemplateQuery::create()->findPk($event->getTemplateId())) {
|
||||
$template
|
||||
->setDispatcher($dispatcher)
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setName($event->getTemplateName())
|
||||
->save();
|
||||
|
||||
$event->setTemplate($template);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product template entry
|
||||
*
|
||||
* @param \Thelia\Core\Event\Template\TemplateDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(TemplateDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if (null !== ($template = TemplateQuery::create()->findPk($event->getTemplateId()))) {
|
||||
// Check if template is used by a product
|
||||
$product_count = ProductQuery::create()->findByTemplateId($template->getId())->count();
|
||||
|
||||
if ($product_count <= 0) {
|
||||
$con = Propel::getWriteConnection(TemplateTableMap::DATABASE_NAME);
|
||||
$con->beginTransaction();
|
||||
|
||||
try {
|
||||
$template
|
||||
->setDispatcher($dispatcher)
|
||||
->delete($con);
|
||||
|
||||
// We have to also delete any reference of this template in category tables
|
||||
// We can't use a FK here, as the DefaultTemplateId column may be NULL
|
||||
// so let's take care of this.
|
||||
CategoryQuery::create()
|
||||
->filterByDefaultTemplateId($event->getTemplateId())
|
||||
->update([ 'DefaultTemplateId' => null], $con);
|
||||
|
||||
$con->commit();
|
||||
} catch (\Exception $ex) {
|
||||
$con->rollback();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
$event->setTemplate($template);
|
||||
|
||||
$event->setProductCount($product_count);
|
||||
}
|
||||
}
|
||||
|
||||
public function addAttribute(TemplateAddAttributeEvent $event)
|
||||
{
|
||||
if (null === AttributeTemplateQuery::create()
|
||||
->filterByAttributeId($event->getAttributeId())
|
||||
->filterByTemplate($event->getTemplate())
|
||||
->findOne()) {
|
||||
$attribute_template = new AttributeTemplate();
|
||||
|
||||
$attribute_template
|
||||
->setAttributeId($event->getAttributeId())
|
||||
->setTemplate($event->getTemplate())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updateAttributePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(AttributeTemplateQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param UpdatePositionEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function updateFeaturePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->genericUpdatePosition(FeatureTemplateQuery::create(), $event, $dispatcher);
|
||||
}
|
||||
|
||||
public function deleteAttribute(TemplateDeleteAttributeEvent $event)
|
||||
{
|
||||
$attribute_template = AttributeTemplateQuery::create()
|
||||
->filterByAttributeId($event->getAttributeId())
|
||||
->filterByTemplate($event->getTemplate())->findOne()
|
||||
;
|
||||
|
||||
if ($attribute_template !== null) {
|
||||
$attribute_template->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function addFeature(TemplateAddFeatureEvent $event)
|
||||
{
|
||||
if (null === FeatureTemplateQuery::create()
|
||||
->filterByFeatureId($event->getFeatureId())
|
||||
->filterByTemplate($event->getTemplate())
|
||||
->findOne()
|
||||
) {
|
||||
$feature_template = new FeatureTemplate();
|
||||
|
||||
$feature_template
|
||||
->setFeatureId($event->getFeatureId())
|
||||
->setTemplate($event->getTemplate())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteFeature(TemplateDeleteFeatureEvent $event)
|
||||
{
|
||||
$feature_template = FeatureTemplateQuery::create()
|
||||
->filterByFeatureId($event->getFeatureId())
|
||||
->filterByTemplate($event->getTemplate())->findOne()
|
||||
;
|
||||
|
||||
if ($feature_template !== null) {
|
||||
$feature_template->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::TEMPLATE_CREATE => array("create", 128),
|
||||
TheliaEvents::TEMPLATE_UPDATE => array("update", 128),
|
||||
TheliaEvents::TEMPLATE_DELETE => array("delete", 128),
|
||||
|
||||
TheliaEvents::TEMPLATE_ADD_ATTRIBUTE => array("addAttribute", 128),
|
||||
TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE => array("deleteAttribute", 128),
|
||||
|
||||
TheliaEvents::TEMPLATE_ADD_FEATURE => array("addFeature", 128),
|
||||
TheliaEvents::TEMPLATE_DELETE_FEATURE => array("deleteFeature", 128),
|
||||
|
||||
TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION => array('updateAttributePosition', 128),
|
||||
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION => array('updateFeaturePosition', 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
372
core/lib/Thelia/Action/Translation.php
Normal file
372
core/lib/Thelia/Action/Translation.php
Normal file
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\Translation\TranslationEvent;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Log\Tlog;
|
||||
|
||||
/**
|
||||
* Class Translation
|
||||
* @package Thelia\Action
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Translation extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/** @var ContainerInterface */
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function getTranslatableStrings(TranslationEvent $event)
|
||||
{
|
||||
$stringCount = $this->walkDir(
|
||||
$event->getDirectory(),
|
||||
$event->getMode(),
|
||||
$event->getLocale(),
|
||||
$event->getDomain(),
|
||||
$strings
|
||||
);
|
||||
|
||||
$event
|
||||
->setTranslatableStrings($strings)
|
||||
->setTranslatableStringCount($stringCount)
|
||||
;
|
||||
}
|
||||
/**
|
||||
* Recursively examine files in a directory tree, and extract translatable strings.
|
||||
*
|
||||
* Returns an array of translatable strings, each item having with the following structure:
|
||||
* 'files' an array of file names in which the string appears,
|
||||
* 'text' the translatable text
|
||||
* 'translation' => the text translation, or an empty string if none available.
|
||||
* 'dollar' => true if the translatable text contains a $
|
||||
*
|
||||
* @param string $directory the path to the directory to examine
|
||||
* @param string $walkMode type of file scanning: WALK_MODE_PHP or WALK_MODE_TEMPLATE
|
||||
* @param string $currentLocale the current locale
|
||||
* @param string $domain the translation domain (fontoffice, backoffice, module, etc...)
|
||||
* @param array $strings the list of strings
|
||||
* @throws \InvalidArgumentException if $walkMode contains an invalid value
|
||||
* @return number the total number of translatable texts
|
||||
*/
|
||||
protected function walkDir($directory, $walkMode, $currentLocale, $domain, &$strings)
|
||||
{
|
||||
$numTexts = 0;
|
||||
|
||||
if ($walkMode == TranslationEvent::WALK_MODE_PHP) {
|
||||
$prefix = '\-\>[\s]*trans[\s]*\([\s]*';
|
||||
|
||||
$allowedExts = array('php');
|
||||
} elseif ($walkMode == TranslationEvent::WALK_MODE_TEMPLATE) {
|
||||
$prefix = '\{intl(?:.*?)[\s]l=[\s]*';
|
||||
|
||||
$allowedExts = array('html', 'tpl', 'xml', 'txt');
|
||||
} else {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Invalid value for walkMode parameter: %value',
|
||||
array('%value' => $walkMode)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
Tlog::getInstance()->debug("Walking in $directory, in mode $walkMode");
|
||||
|
||||
/** @var \DirectoryIterator $fileInfo */
|
||||
foreach (new \DirectoryIterator($directory) as $fileInfo) {
|
||||
if ($fileInfo->isDot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fileInfo->isDir()) {
|
||||
$numTexts += $this->walkDir(
|
||||
$fileInfo->getPathName(),
|
||||
$walkMode,
|
||||
$currentLocale,
|
||||
$domain,
|
||||
$strings
|
||||
);
|
||||
}
|
||||
|
||||
if ($fileInfo->isFile()) {
|
||||
$ext = $fileInfo->getExtension();
|
||||
|
||||
if (in_array($ext, $allowedExts)) {
|
||||
if ($content = file_get_contents($fileInfo->getPathName())) {
|
||||
$short_path = $this->normalizePath($fileInfo->getPathName());
|
||||
|
||||
Tlog::getInstance()->debug("Examining file $short_path\n");
|
||||
|
||||
$matches = array();
|
||||
|
||||
if (preg_match_all(
|
||||
'/'.$prefix.'((?<![\\\\])[\'"])((?:.(?!(?<![\\\\])\1))*.?)*?\1/ms',
|
||||
$content,
|
||||
$matches
|
||||
)) {
|
||||
Tlog::getInstance()->debug("Strings found: ", $matches[2]);
|
||||
|
||||
$idx = 0;
|
||||
|
||||
foreach ($matches[2] as $match) {
|
||||
$hash = md5($match);
|
||||
|
||||
if (isset($strings[$hash])) {
|
||||
if (! in_array($short_path, $strings[$hash]['files'])) {
|
||||
$strings[$hash]['files'][] = $short_path;
|
||||
}
|
||||
} else {
|
||||
$numTexts++;
|
||||
|
||||
// remove \' (or \"), that will prevent the translator to work properly, as
|
||||
// "abc \def\" ghi" will be passed as abc "def" ghi to the translator.
|
||||
|
||||
$quote = $matches[1][$idx];
|
||||
|
||||
$match = str_replace("\\$quote", $quote, $match);
|
||||
|
||||
// Ignore empty strings
|
||||
if (strlen($match) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$strings[$hash] = array(
|
||||
'files' => array($short_path),
|
||||
'text' => $match,
|
||||
'translation' => Translator::getInstance()->trans(
|
||||
$match,
|
||||
[],
|
||||
$domain,
|
||||
$currentLocale,
|
||||
false,
|
||||
false
|
||||
),
|
||||
'custom_fallback' => Translator::getInstance()->trans(
|
||||
sprintf(
|
||||
Translator::GLOBAL_FALLBACK_KEY,
|
||||
$domain,
|
||||
$match
|
||||
),
|
||||
[],
|
||||
Translator::GLOBAL_FALLBACK_DOMAIN,
|
||||
$currentLocale,
|
||||
false,
|
||||
false
|
||||
),
|
||||
'global_fallback' => Translator::getInstance()->trans(
|
||||
$match,
|
||||
[],
|
||||
Translator::GLOBAL_FALLBACK_DOMAIN,
|
||||
$currentLocale,
|
||||
false,
|
||||
false
|
||||
),
|
||||
'dollar' => strstr($match, '$') !== false
|
||||
);
|
||||
}
|
||||
|
||||
$idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\UnexpectedValueException $ex) {
|
||||
// Directory does not exists => ignore it.
|
||||
}
|
||||
|
||||
return $numTexts;
|
||||
}
|
||||
|
||||
public function writeTranslationFile(TranslationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$file = $event->getTranslationFilePath();
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
if (! $fs->exists($file) && true === $event->isCreateFileIfNotExists()) {
|
||||
$dir = dirname($file);
|
||||
|
||||
if (! $fs->exists($file)) {
|
||||
$fs->mkdir($dir);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
if ($fp = @fopen($file, 'w')) {
|
||||
fwrite($fp, '<' . "?php\n\n");
|
||||
fwrite($fp, "return array(\n");
|
||||
|
||||
$texts = $event->getTranslatableStrings();
|
||||
$translations = $event->getTranslatedStrings();
|
||||
|
||||
// Sort keys alphabetically while keeping index
|
||||
asort($texts);
|
||||
|
||||
foreach ($texts as $key => $text) {
|
||||
// Write only defined (not empty) translations
|
||||
if (! empty($translations[$key])) {
|
||||
$text = str_replace("'", "\'", $text);
|
||||
|
||||
$translation = str_replace("'", "\'", $translations[$key]);
|
||||
|
||||
fwrite($fp, sprintf(" '%s' => '%s',\n", $text, $translation));
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($fp, ");\n");
|
||||
|
||||
@fclose($fp);
|
||||
} else {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans(
|
||||
'Failed to open translation file %file. Please be sure that this file is writable by your Web server',
|
||||
array('%file' => $file)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function writeFallbackFile(TranslationEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$file = THELIA_LOCAL_DIR . 'I18n' . DS . $event->getLocale() . '.php';
|
||||
|
||||
$fs = new Filesystem();
|
||||
$translations = [];
|
||||
|
||||
if (! $fs->exists($file)) {
|
||||
if (true === $event->isCreateFileIfNotExists()) {
|
||||
$dir = dirname($file);
|
||||
$fs->mkdir($dir);
|
||||
|
||||
$this->cacheClear($dispatcher);
|
||||
} else {
|
||||
throw new \RuntimeException(
|
||||
Translator::getInstance()->trans(
|
||||
'Failed to open translation file %file. Please be sure that this file is writable by your Web server',
|
||||
array('%file' => $file)
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
/*$loader = new PhpFileLoader();
|
||||
$catalogue = $loade r->load($file);
|
||||
$translations = $catalogue->all();
|
||||
*/
|
||||
$translations = require $file;
|
||||
|
||||
if (! is_array($translations)) {
|
||||
$translations = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ($fp = @fopen($file, 'w')) {
|
||||
$texts = $event->getTranslatableStrings();
|
||||
$customs = $event->getCustomFallbackStrings();
|
||||
$globals = $event->getGlobalFallbackStrings();
|
||||
|
||||
// just reset current translations for this domain to remove strings that do not exist anymore
|
||||
$translations[$event->getDomain()] = [];
|
||||
|
||||
foreach ($texts as $key => $text) {
|
||||
if (!empty($customs[$key])) {
|
||||
$translations[$event->getDomain()][$text] = $customs[$key];
|
||||
}
|
||||
|
||||
if (!empty($globals[$key])) {
|
||||
$translations[$text] = $globals[$key];
|
||||
} else {
|
||||
unset($translations[$text]);
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($fp, '<' . "?php\n\n");
|
||||
fwrite($fp, "return [\n");
|
||||
|
||||
// Sort keys alphabetically while keeping index
|
||||
ksort($translations);
|
||||
|
||||
foreach ($translations as $key => $text) {
|
||||
// Write only defined (not empty) translations
|
||||
if (!empty($translations[$key])) {
|
||||
if (is_array($translations[$key])) {
|
||||
$key = str_replace("'", "\'", $key);
|
||||
fwrite($fp, sprintf(" '%s' => [\n", $key));
|
||||
ksort($translations[$key]);
|
||||
foreach ($translations[$key] as $subKey => $subText) {
|
||||
$subKey = str_replace("'", "\'", $subKey);
|
||||
$translation = str_replace("'", "\'", $subText);
|
||||
fwrite($fp, sprintf(" '%s' => '%s',\n", $subKey, $translation));
|
||||
}
|
||||
fwrite($fp, " ],\n");
|
||||
} else {
|
||||
$key = str_replace("'", "\'", $key);
|
||||
$translation = str_replace("'", "\'", $text);
|
||||
fwrite($fp, sprintf(" '%s' => '%s',\n", $key, $translation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($fp, "];\n");
|
||||
|
||||
@fclose($fp);
|
||||
}
|
||||
}
|
||||
|
||||
protected function normalizePath($path)
|
||||
{
|
||||
$path = str_replace(
|
||||
str_replace('\\', '/', THELIA_ROOT),
|
||||
'',
|
||||
str_replace('\\', '/', realpath($path))
|
||||
);
|
||||
|
||||
return ltrim($path, '/');
|
||||
}
|
||||
|
||||
protected function cacheClear(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$cacheEvent = new CacheEvent(
|
||||
$this->container->getParameter('kernel.cache_dir')
|
||||
);
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::TRANSLATION_GET_STRINGS => array('getTranslatableStrings', 128),
|
||||
TheliaEvents::TRANSLATION_WRITE_FILE => [
|
||||
['writeTranslationFile', 128],
|
||||
['writeFallbackFile', 128]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user