MAJ en Thelia 2.3.4
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
|
||||
namespace Thelia\Core\Archiver;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Class AbstractArchiver
|
||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||
@@ -28,10 +30,10 @@ abstract class AbstractArchiver implements ArchiverInterface
|
||||
*/
|
||||
protected $archivePath;
|
||||
|
||||
public function __construct()
|
||||
public function __construct($checkIsAvailable = false)
|
||||
{
|
||||
if (!$this->isAvailable()) {
|
||||
throw new Exception(
|
||||
if ($checkIsAvailable && !$this->isAvailable()) {
|
||||
throw new \Exception(
|
||||
Translator::getInstance()->trans(
|
||||
"The archiver :name is not available. Please install the php extension :extension first.",
|
||||
[
|
||||
@@ -40,7 +42,7 @@ abstract class AbstractArchiver implements ArchiverInterface
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getArchivePath()
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace Thelia\Core\DependencyInjection\Compiler;
|
||||
use Propel\Runtime\Propel;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Thelia\Core\Hook\BaseHook;
|
||||
use Thelia\Core\Hook\HookDefinition;
|
||||
@@ -26,8 +26,8 @@ use Thelia\Model\Base\IgnoredModuleHookQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Hook;
|
||||
use Thelia\Model\HookQuery;
|
||||
use Thelia\Model\ModuleHookQuery;
|
||||
use Thelia\Model\ModuleHook;
|
||||
use Thelia\Model\ModuleHookQuery;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
|
||||
/**
|
||||
@@ -61,11 +61,11 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
|
||||
protected function logAlertMessage($message)
|
||||
protected function logAlertMessage($message, $failSafe = false)
|
||||
{
|
||||
Tlog::getInstance()->addAlert($message);
|
||||
|
||||
if ($this->debugEnabled) {
|
||||
if (!$failSafe && $this->debugEnabled) {
|
||||
throw new \InvalidArgumentException($message);
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,6 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
$moduleHook
|
||||
->setHookActive(false)
|
||||
->save();
|
||||
|
||||
} else {
|
||||
//$moduleHook->setTemplates($attributes['templates']);
|
||||
|
||||
@@ -226,6 +225,7 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
$hookId = 0;
|
||||
/** @var ModuleHook $moduleHook */
|
||||
foreach ($moduleHooks as $moduleHook) {
|
||||
|
||||
// check if class and method exists
|
||||
if (!$container->hasDefinition($moduleHook->getClassname())) {
|
||||
continue;
|
||||
@@ -236,7 +236,8 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
if (!$this->isValidHookMethod(
|
||||
$container->getDefinition($moduleHook->getClassname())->getClass(),
|
||||
$moduleHook->getMethod(),
|
||||
$hook->getBlock()
|
||||
$hook->getBlock(),
|
||||
true
|
||||
)
|
||||
) {
|
||||
$moduleHook->delete();
|
||||
@@ -346,9 +347,7 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
}
|
||||
|
||||
if (! $hook->getActivate()) {
|
||||
$this->logAlertMessage(sprintf("Hook %s is not activated.", $hookName));
|
||||
|
||||
return null;
|
||||
$this->logAlertMessage(sprintf("Hook %s is not activated.", $hookName), true);
|
||||
}
|
||||
|
||||
return $hook;
|
||||
@@ -360,10 +359,11 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
* @param string $className the namespace of the class
|
||||
* @param string $methodName the method name
|
||||
* @param bool $block tell if the hook is a block or a function
|
||||
* @param bool $failSafe
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidHookMethod($className, $methodName, $block)
|
||||
protected function isValidHookMethod($className, $methodName, $block, $failSafe = false)
|
||||
{
|
||||
try {
|
||||
$method = new ReflectionMethod($className, $methodName);
|
||||
@@ -380,7 +380,10 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
||||
return false;
|
||||
}
|
||||
} catch (ReflectionException $ex) {
|
||||
$this->logAlertMessage(sprintf("Method %s does not exist in %s : %s", $methodName, $className, $ex));
|
||||
$this->logAlertMessage(
|
||||
sprintf("Method %s does not exist in %s : %s", $methodName, $className, $ex),
|
||||
$failSafe
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Thelia\Model\Module;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -52,8 +54,9 @@ class RegisterRouterPass implements CompilerPassInterface
|
||||
$chainRouter->addMethodCall("add", array(new Reference($id), $priority));
|
||||
}
|
||||
if (defined("THELIA_INSTALL_MODE") === false) {
|
||||
$modules = \Thelia\Model\ModuleQuery::getActivated();
|
||||
$modules = ModuleQuery::getActivated();
|
||||
|
||||
/** @var Module $module */
|
||||
foreach ($modules as $module) {
|
||||
$moduleBaseDir = $module->getBaseDir();
|
||||
$routingConfigFilePath = $module->getAbsoluteBaseDir() . DS . "Config" . DS . "routing.xml";
|
||||
@@ -76,7 +79,7 @@ class RegisterRouterPass implements CompilerPassInterface
|
||||
|
||||
$container->setDefinition("router.".$moduleBaseDir, $definition);
|
||||
|
||||
$chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150));
|
||||
$chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150 + $module->getPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class CartDuplicationEvent extends CartEvent
|
||||
*/
|
||||
public function getDuplicatedCart()
|
||||
{
|
||||
return parent::getCart();
|
||||
return $this->getCart();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Event\Country;
|
||||
*/
|
||||
class CountryToggleVisibilityEvent extends CountryEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -128,6 +128,4 @@ class ModuleHookCreateEvent extends ModuleHookEvent
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,36 +10,57 @@
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Thelia\Core\Event\Loop;
|
||||
|
||||
use Thelia\Core\Template\Element\BaseLoop;
|
||||
|
||||
/**
|
||||
* Class LoopExtendsBuildArrayEvent
|
||||
*
|
||||
* @package Thelia\Core\Event\Loop
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class LoopExtendsBuildArrayEvent extends LoopExtendsEvent
|
||||
{
|
||||
/** @var array $array */
|
||||
/**
|
||||
* @var array Build array results
|
||||
*/
|
||||
protected $array;
|
||||
|
||||
/**
|
||||
* LoopExtendsBuildArrayEvent constructor.
|
||||
* @param array $array
|
||||
* Class constructor
|
||||
*
|
||||
* @param \Thelia\Core\Template\Element\BaseLoop $loop Loop object
|
||||
* @param array $array Build array base results
|
||||
*/
|
||||
public function __construct(BaseLoop $loop, array $array)
|
||||
{
|
||||
parent::__construct($loop);
|
||||
|
||||
$this->array = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* Get build array results
|
||||
*
|
||||
* @return array Build array results
|
||||
*/
|
||||
public function getArray()
|
||||
{
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set build array results
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return $this Return $this, allow chaining
|
||||
*/
|
||||
public function setArray(array $array)
|
||||
{
|
||||
$this->array = $array;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,17 +25,28 @@ class ModuleDeleteEvent extends ModuleEvent
|
||||
protected $module_id;
|
||||
protected $delete_data;
|
||||
|
||||
public function __construct($module_id)
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $assume_delete;
|
||||
|
||||
public function __construct($module_id, $assume_delete = false)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->module_id = $module_id;
|
||||
$this->assume_delete = $assume_delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $module_id
|
||||
* @return $this
|
||||
*/
|
||||
public function setModuleId($module_id)
|
||||
{
|
||||
$this->module_id = $module_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,10 +62,33 @@ class ModuleDeleteEvent extends ModuleEvent
|
||||
return $this->delete_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param boolean $delete_data
|
||||
* @return $this
|
||||
*/
|
||||
public function setDeleteData($delete_data)
|
||||
{
|
||||
$this->delete_data = $delete_data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function getAssumeDelete()
|
||||
{
|
||||
return $this->assume_delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $assume_delete
|
||||
* @return $this
|
||||
*/
|
||||
public function setAssumeDelete($assume_delete)
|
||||
{
|
||||
$this->assume_delete = $assume_delete;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,21 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
||||
*/
|
||||
protected $recursive;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $assume_deactivate;
|
||||
|
||||
|
||||
/**
|
||||
* @param int $module_id
|
||||
*/
|
||||
public function __construct($module_id)
|
||||
public function __construct($module_id, $assume_deactivate = false)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->module_id = $module_id;
|
||||
$this->assume_deactivate = $assume_deactivate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +81,7 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
||||
|
||||
/**
|
||||
* @param boolean $noCheck
|
||||
* @return $this;
|
||||
* @return $this
|
||||
*/
|
||||
public function setNoCheck($noCheck)
|
||||
{
|
||||
@@ -92,11 +100,29 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
||||
|
||||
/**
|
||||
* @param boolean $recursive
|
||||
* @return $this;
|
||||
* @return $this
|
||||
*/
|
||||
public function setRecursive($recursive)
|
||||
{
|
||||
$this->recursive = $recursive;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function getAssumeDeactivate()
|
||||
{
|
||||
return $this->assume_deactivate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $assume_deactivate
|
||||
* @return $this
|
||||
*/
|
||||
public function setAssumeDeactivate($assume_deactivate)
|
||||
{
|
||||
$this->assume_deactivate = $assume_deactivate;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ class OrderEvent extends ActionEvent
|
||||
/** @var null|int */
|
||||
protected $cartItemId = null;
|
||||
|
||||
/** @var null|string */
|
||||
protected $transactionRef = null;
|
||||
|
||||
/**
|
||||
* @var Response
|
||||
*/
|
||||
@@ -352,4 +355,24 @@ class OrderEvent extends ActionEvent
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.4.0
|
||||
* @return null|string
|
||||
*/
|
||||
public function getTransactionRef()
|
||||
{
|
||||
return $this->transactionRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.4.0
|
||||
* @param null|string $transactionRef
|
||||
* @return $this
|
||||
*/
|
||||
public function setTransactionRef($transactionRef)
|
||||
{
|
||||
$this->transactionRef = $transactionRef;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,23 @@ use Thelia\Model\Product;
|
||||
|
||||
class ProductCloneEvent extends ActionEvent
|
||||
{
|
||||
/** @var string */
|
||||
protected $ref;
|
||||
/** @var string */
|
||||
protected $lang;
|
||||
protected $originalProduct = array();
|
||||
protected $clonedProduct = array();
|
||||
/** @var Product */
|
||||
protected $originalProduct;
|
||||
/** @var Product */
|
||||
protected $clonedProduct;
|
||||
/** @var array */
|
||||
protected $types = array('images', 'documents');
|
||||
|
||||
/**
|
||||
* ProductCloneEvent constructor.
|
||||
* @param string $ref
|
||||
* @param string $lang the locale (such as fr_FR)
|
||||
* @param $originalProduct
|
||||
*/
|
||||
public function __construct(
|
||||
$ref,
|
||||
$lang,
|
||||
@@ -34,7 +45,7 @@ class ProductCloneEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getRef()
|
||||
{
|
||||
@@ -42,7 +53,7 @@ class ProductCloneEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $ref
|
||||
* @param string $ref
|
||||
*/
|
||||
public function setRef($ref)
|
||||
{
|
||||
@@ -50,7 +61,7 @@ class ProductCloneEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string the locale (such as fr_FR)
|
||||
*/
|
||||
public function getLang()
|
||||
{
|
||||
@@ -58,7 +69,7 @@ class ProductCloneEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $lang
|
||||
* @param string $lang the locale (such as fr_FR)
|
||||
*/
|
||||
public function setLang($lang)
|
||||
{
|
||||
|
||||
@@ -14,34 +14,55 @@ namespace Thelia\Core\Event\ProductSaleElement;
|
||||
|
||||
class ProductSaleElementDeleteEvent extends ProductSaleElementEvent
|
||||
{
|
||||
/** @var int */
|
||||
protected $product_sale_element_id;
|
||||
/** @var int */
|
||||
protected $currency_id;
|
||||
|
||||
|
||||
/**
|
||||
* ProductSaleElementDeleteEvent constructor.
|
||||
* @param int $product_sale_element_id
|
||||
* @param int $currency_id
|
||||
*/
|
||||
public function __construct($product_sale_element_id, $currency_id)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->product_sale_element_id = $product_sale_element_id;
|
||||
$this->setCurrencyId($currency_id);
|
||||
$this->currency_id = $currency_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getProductSaleElementId()
|
||||
{
|
||||
return $this->product_sale_element_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $product_sale_element_id
|
||||
* @return $this
|
||||
*/
|
||||
public function setProductSaleElementId($product_sale_element_id)
|
||||
{
|
||||
$this->product_sale_element_id = $product_sale_element_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrencyId()
|
||||
{
|
||||
return $this->currency_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $currency_id
|
||||
* @return $this
|
||||
*/
|
||||
public function setCurrencyId($currency_id)
|
||||
{
|
||||
$this->currency_id = $currency_id;
|
||||
|
||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Event\State;
|
||||
*/
|
||||
class StateToggleVisibilityEvent extends StateEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -17,23 +17,36 @@ use Thelia\Model\Template;
|
||||
|
||||
class TemplateEvent extends ActionEvent
|
||||
{
|
||||
/**
|
||||
* @var Template
|
||||
*/
|
||||
protected $template = null;
|
||||
|
||||
public function __construct(Template $template = null)
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTemplate()
|
||||
{
|
||||
return ! is_null($this->template);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Template
|
||||
*/
|
||||
public function getTemplate()
|
||||
{
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Template $template
|
||||
* @return $this
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
|
||||
@@ -26,6 +26,10 @@ final class TheliaEvents
|
||||
* sent at the beginning
|
||||
*/
|
||||
const BOOT = "thelia.boot";
|
||||
/**
|
||||
* Kernel View Check Handle
|
||||
*/
|
||||
const VIEW_CHECK = "thelia.view_check";
|
||||
// -- END CORE EVENTS ---------------------------------------------------------
|
||||
// -- ADDRESS EVENTS ---------------------------------------------------------
|
||||
/**
|
||||
@@ -115,6 +119,8 @@ final class TheliaEvents
|
||||
const CATEGORY_REMOVE_CONTENT = "action.categoryRemoveContent";
|
||||
|
||||
const CATEGORY_UPDATE_SEO = "action.updateCategorySeo";
|
||||
|
||||
const VIEW_CATEGORY_ID_NOT_VISIBLE = "action.viewCategoryIdNotVisible";
|
||||
// -- END CATEGORIES EVENTS -----------------------------------------------
|
||||
|
||||
|
||||
@@ -137,6 +143,8 @@ final class TheliaEvents
|
||||
|
||||
const CONTENT_ADD_FOLDER = "action.contentAddFolder";
|
||||
const CONTENT_REMOVE_FOLDER = "action.contentRemoveFolder";
|
||||
|
||||
const VIEW_CONTENT_ID_NOT_VISIBLE = "action.viewContentIdNotVisible";
|
||||
// -- END CONTENT EVENTS ---------------------------------------------------------
|
||||
|
||||
|
||||
@@ -234,6 +242,12 @@ final class TheliaEvents
|
||||
* sent when a customer need a new password
|
||||
*/
|
||||
const LOST_PASSWORD = "action.lostPassword";
|
||||
|
||||
/**
|
||||
* Send the account ccreation confirmation email
|
||||
*/
|
||||
const SEND_ACCOUNT_CONFIRMATION_EMAIL = "action.customer.sendAccountConfirmationEmail";
|
||||
|
||||
// -- END CUSTOMER EVENTS ---------------------------------------------------------
|
||||
|
||||
|
||||
@@ -253,6 +267,8 @@ final class TheliaEvents
|
||||
const FOLDER_TOGGLE_VISIBILITY = "action.toggleFolderVisibility";
|
||||
const FOLDER_UPDATE_POSITION = "action.updateFolderPosition";
|
||||
const FOLDER_UPDATE_SEO = "action.updateFolderSeo";
|
||||
|
||||
const VIEW_FOLDER_ID_NOT_VISIBLE = "action.viewFolderIdNotVisible";
|
||||
// -- END FOLDER EVENTS ---------------------------------------------------------
|
||||
|
||||
|
||||
@@ -299,6 +315,7 @@ final class TheliaEvents
|
||||
const VIRTUAL_PRODUCT_ORDER_HANDLE = "action.virtualProduct.handleOrder";
|
||||
const VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE = "action.virtualProduct.downloadResponse";
|
||||
|
||||
const VIEW_PRODUCT_ID_NOT_VISIBLE = "action.viewProductIdNotVisible";
|
||||
// -- END PRODUCT EVENTS ---------------------------------------------------------
|
||||
|
||||
|
||||
@@ -437,6 +454,7 @@ final class TheliaEvents
|
||||
const ORDER_SEND_NOTIFICATION_EMAIL = "action.order.sendOrderNotificationEmail";
|
||||
|
||||
const ORDER_UPDATE_DELIVERY_REF = "action.order.updateDeliveryRef";
|
||||
const ORDER_UPDATE_TRANSACTION_REF = "action.order.updateTransactionRef";
|
||||
const ORDER_UPDATE_ADDRESS = "action.order.updateAddress";
|
||||
|
||||
const ORDER_PRODUCT_BEFORE_CREATE = "action.orderProduct.beforeCreate";
|
||||
@@ -694,6 +712,7 @@ final class TheliaEvents
|
||||
const TEMPLATE_CREATE = "action.createTemplate";
|
||||
const TEMPLATE_UPDATE = "action.updateTemplate";
|
||||
const TEMPLATE_DELETE = "action.deleteTemplate";
|
||||
const TEMPLATE_DUPLICATE = "action.duplicateTemplate";
|
||||
|
||||
const TEMPLATE_ADD_ATTRIBUTE = "action.templateAddAttribute";
|
||||
const TEMPLATE_DELETE_ATTRIBUTE = "action.templateDeleteAttribute";
|
||||
@@ -912,6 +931,8 @@ final class TheliaEvents
|
||||
const BEFORE_UPDATEBRAND = "action.before_updateBrand";
|
||||
const AFTER_UPDATEBRAND = "action.after_updateBrand";
|
||||
|
||||
const VIEW_BRAND_ID_NOT_VISIBLE = "action.viewBrandIdNotVisible";
|
||||
|
||||
// -- Import ----------------------------------------------
|
||||
|
||||
const IMPORT_CHANGE_POSITION = 'import.change.position';
|
||||
@@ -980,4 +1001,20 @@ final class TheliaEvents
|
||||
|
||||
const TRANSLATION_GET_STRINGS = 'action.translation.get_strings';
|
||||
const TRANSLATION_WRITE_FILE = 'action.translation.write_file';
|
||||
|
||||
// -- ORDER STATUS EVENTS -----------------------------------------------
|
||||
const BEFORE_CREATE_ORDER_STATUS = "action.before_createOrderStatus";
|
||||
const ORDER_STATUS_CREATE = "action.createOrderStatus";
|
||||
const AFTER_CREATE_ORDER_STATUS = "action.after_createOrderStatus";
|
||||
|
||||
const BEFORE_UPDATE_ORDER_STATUS = "action.before_updateOrderStatus";
|
||||
const ORDER_STATUS_UPDATE = "action.updateOrderStatus";
|
||||
const AFTER_UPDATE_ORDER_STATUS = "action.after_updateOrderStatus";
|
||||
|
||||
const BEFORE_DELETE_ORDER_STATUS = "action.before_deleteOrderStatus";
|
||||
const ORDER_STATUS_DELETE = "action.deleteOrderStatus";
|
||||
const AFTER_DELETE_ORDER_STATUS = "action.after_deleteOrderStatus";
|
||||
|
||||
const ORDER_STATUS_UPDATE_POSITION = "action.updateOrderStatusPosition";
|
||||
// -- END ORDER STATUS EVENTS -----------------------------------------------
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use Thelia\Core\Security\Exception\AuthenticationException;
|
||||
use Thelia\Core\Security\SecurityContext;
|
||||
use Thelia\Core\Template\ParserInterface;
|
||||
use Thelia\Core\TheliaKernelEvents;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
/**
|
||||
@@ -89,6 +90,25 @@ class ErrorListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function logException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
// Log exception in the Thelia log
|
||||
$exception = $event->getException();
|
||||
|
||||
$logMessage = '';
|
||||
|
||||
do {
|
||||
$logMessage .=
|
||||
($logMessage ? PHP_EOL . 'Caused by' : 'Uncaught exception')
|
||||
. $event->getException()->getMessage()
|
||||
. PHP_EOL
|
||||
. "Stack Trace: " . $event->getException()->getTraceAsString()
|
||||
;
|
||||
} while (null !== $exception = $exception->getPrevious());
|
||||
|
||||
Tlog::getInstance()->error($logMessage);
|
||||
}
|
||||
|
||||
public function authenticationException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
$exception = $event->getException();
|
||||
@@ -107,6 +127,7 @@ class ErrorListener implements EventSubscriberInterface
|
||||
{
|
||||
return array(
|
||||
KernelEvents::EXCEPTION => [
|
||||
["logException", 0],
|
||||
["handleException", 0],
|
||||
['authenticationException', 100]
|
||||
],
|
||||
|
||||
@@ -275,9 +275,11 @@ class RequestListener implements EventSubscriberInterface
|
||||
) {
|
||||
$request->getSession()->setCurrency($find);
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::CHANGE_DEFAULT_CURRENCY, new CurrencyChangeEvent($find, $request));
|
||||
} else {
|
||||
$defaultCurrency = Currency::getDefaultCurrency();
|
||||
$request->getSession()->setCurrency($defaultCurrency);
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::CHANGE_DEFAULT_CURRENCY, new CurrencyChangeEvent($defaultCurrency, $request));
|
||||
}
|
||||
} else {
|
||||
$request->getSession()->setCurrency(Currency::getDefaultCurrency());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ class ResponseListener implements EventSubscriberInterface
|
||||
$session = $event->getRequest()->getSession();
|
||||
|
||||
if (null !== $id = $session->get("cart_use_cookie")) {
|
||||
|
||||
$response = $event->getResponse();
|
||||
$cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart');
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace Thelia\Core\EventListener;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -20,6 +21,8 @@ use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Routing\Router;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\ViewCheckEvent;
|
||||
use Thelia\Core\HttpFoundation\Response;
|
||||
use Thelia\Core\Template\Exception\ResourceNotFoundException;
|
||||
use Thelia\Exception\OrderException;
|
||||
@@ -35,23 +38,23 @@ use Thelia\Exception\OrderException;
|
||||
|
||||
class ViewListener implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\ContainerInterface
|
||||
*/
|
||||
/** @var ContainerInterface */
|
||||
private $container;
|
||||
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
public function __construct(ContainerInterface $container, EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Launch the parser defined on the constructor and get the result.
|
||||
*
|
||||
* The result is transform id needed into a Response object
|
||||
@@ -66,7 +69,13 @@ class ViewListener implements EventSubscriberInterface
|
||||
$request = $this->container->get('request_stack')->getCurrentRequest();
|
||||
$response = null;
|
||||
try {
|
||||
$content = $parser->render($request->attributes->get('_view').".html");
|
||||
$view = $request->attributes->get('_view');
|
||||
|
||||
$viewId = $request->attributes->get($view . '_id');
|
||||
|
||||
$this->eventDispatcher->dispatch(TheliaEvents::VIEW_CHECK, new ViewCheckEvent($view, $viewId));
|
||||
|
||||
$content = $parser->render($view . '.html');
|
||||
|
||||
if ($content instanceof Response) {
|
||||
$response = $content;
|
||||
@@ -98,15 +107,19 @@ class ViewListener implements EventSubscriberInterface
|
||||
{
|
||||
$request = $this->container->get('request_stack')->getCurrentRequest();
|
||||
|
||||
if (null === $request->attributes->get('_view')) {
|
||||
if (null === $view = $request->attributes->get('_view')) {
|
||||
$request->attributes->set('_view', $this->findView($request));
|
||||
}
|
||||
|
||||
if (null === $request->attributes->get($view . '_id')) {
|
||||
$request->attributes->set($view . '_id', $this->findViewId($request, $view));
|
||||
}
|
||||
}
|
||||
|
||||
public function findView(Request $request)
|
||||
{
|
||||
if (! $view = $request->query->get('view')) {
|
||||
$view = "index";
|
||||
$view = 'index';
|
||||
if ($request->request->has('view')) {
|
||||
$view = $request->request->get('view');
|
||||
}
|
||||
@@ -115,6 +128,17 @@ class ViewListener implements EventSubscriberInterface
|
||||
return $view;
|
||||
}
|
||||
|
||||
public function findViewId(Request $request, $view)
|
||||
{
|
||||
if (! $viewId = $request->query->get($view . '_id')) {
|
||||
$viewId = 0;
|
||||
if ($request->request->has($view . '_id')) {
|
||||
$viewId = $request->request->get($view . '_id');
|
||||
}
|
||||
}
|
||||
|
||||
return $viewId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Hook;
|
||||
*/
|
||||
class DefaultHook extends BaseHook
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Thelia\Core\Routing;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Exception\InvalidParameterException;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
@@ -26,7 +27,10 @@ use Thelia\Core\HttpFoundation\Request as TheliaRequest;
|
||||
use Thelia\Core\HttpKernel\Exception\RedirectException;
|
||||
use Thelia\Exception\UrlRewritingException;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\CustomerQuery;
|
||||
use Thelia\Model\Lang;
|
||||
use Thelia\Model\LangQuery;
|
||||
use Thelia\Model\RewritingUrlQuery;
|
||||
use Thelia\Rewriting\RewritingResolver;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
@@ -177,6 +181,11 @@ class RewritingRouter implements RouterInterface, RequestMatcherInterface
|
||||
if (null ==! $requestedLocale = $request->get('lang')) {
|
||||
if (null !== $requestedLang = LangQuery::create()->findOneByLocale($requestedLocale)) {
|
||||
if ($requestedLang->getLocale() != $rewrittenUrlData->locale) {
|
||||
// Save one redirection if requested locale is disabled.
|
||||
if (! $requestedLang->getActive()) {
|
||||
$requestedLang = Lang::getDefaultLanguage();
|
||||
}
|
||||
|
||||
$localizedUrl = $urlTool->retrieve(
|
||||
$rewrittenUrlData->view,
|
||||
$rewrittenUrlData->viewId,
|
||||
@@ -188,9 +197,33 @@ class RewritingRouter implements RouterInterface, RequestMatcherInterface
|
||||
}
|
||||
}
|
||||
|
||||
// If the rewritten URL locale is disabled, redirect to the URL in the default language
|
||||
if (null === $lang = LangQuery::create()
|
||||
->filterByActive(true)
|
||||
->filterByLocale($rewrittenUrlData->locale)
|
||||
->findOne()) {
|
||||
$lang = Lang::getDefaultLanguage();
|
||||
|
||||
$localizedUrl = $urlTool->retrieve(
|
||||
$rewrittenUrlData->view,
|
||||
$rewrittenUrlData->viewId,
|
||||
$lang->getLocale()
|
||||
)->toString();
|
||||
|
||||
$this->redirect($urlTool->absoluteUrl($localizedUrl), 301);
|
||||
}
|
||||
|
||||
/* is the URL redirected ? */
|
||||
if (null !== $rewrittenUrlData->redirectedToUrl) {
|
||||
$this->redirect($urlTool->absoluteUrl($rewrittenUrlData->redirectedToUrl), 301);
|
||||
$redirect = RewritingUrlQuery::create()
|
||||
->filterByView($rewrittenUrlData->view)
|
||||
->filterByViewId($rewrittenUrlData->viewId)
|
||||
->filterByViewLocale($rewrittenUrlData->locale)
|
||||
->filterByRedirected(null, Criteria::ISNULL)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
$this->redirect($urlTool->absoluteUrl($redirect->getUrl()), 301);
|
||||
}
|
||||
|
||||
/* define GET arguments in request */
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
namespace Thelia\Core\Security\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Thelia\Core\Security\Exception\CustomerNotConfirmedException;
|
||||
use Thelia\Core\Security\UserProvider\UserProviderInterface;
|
||||
use Thelia\Core\Security\Exception\WrongPasswordException;
|
||||
use Thelia\Core\Security\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||
use Thelia\Form\BaseForm;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Customer;
|
||||
|
||||
class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
|
||||
{
|
||||
@@ -78,6 +81,14 @@ class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
|
||||
if ($authOk !== true) {
|
||||
throw new WrongPasswordException(sprintf("Wrong password for user '%s'.", $username));
|
||||
}
|
||||
|
||||
if (ConfigQuery::isCustomerEmailConfirmationEnable() && $user instanceof Customer) {
|
||||
// Customer email confirmation feature is available since Thelia 2.3.4
|
||||
if ($user->getConfirmationToken() !== null && ! $user->getEnable()) {
|
||||
throw (new CustomerNotConfirmedException())->setUser($user);
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ class AdminResources
|
||||
|
||||
const ORDER = "admin.order";
|
||||
|
||||
const ORDER_STATUS = "admin.configuration.order-status";
|
||||
|
||||
const PRODUCT = "admin.product";
|
||||
|
||||
const PROFILE = "admin.configuration.profile";
|
||||
|
||||
@@ -114,7 +114,7 @@ class CSVSerializer extends AbstractSerializer
|
||||
if ($this->headers !== null) {
|
||||
// Create tmp file with header
|
||||
$fd = fopen('php://temp', 'w+b');
|
||||
fputcsv($fd, $this->headers);
|
||||
fputcsv($fd, $this->headers, $this->delimiter, $this->enclosure);
|
||||
|
||||
// Copy file content into tmp file
|
||||
$fileObject->rewind();
|
||||
@@ -131,6 +131,8 @@ class CSVSerializer extends AbstractSerializer
|
||||
|
||||
// Remove last line feed
|
||||
$fileObject->ftruncate($fileObject->getSize() - 1);
|
||||
|
||||
clearstatcache(true, $fileObject->getPathname());
|
||||
}
|
||||
|
||||
public function unserialize(\SplFileObject $fileObject)
|
||||
|
||||
@@ -147,7 +147,6 @@ class ParamInitMiddleware implements HttpKernelInterface
|
||||
Tlog::getInstance()->warning("The domain URL for language ".$lang->getTitle()." (id ".$lang->getId().") is not defined.");
|
||||
|
||||
return Lang::getDefaultLanguage();
|
||||
|
||||
} else {
|
||||
// one domain for all languages, the lang has to be set into session
|
||||
return $lang;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Thelia\Core\Template\Element;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
use Thelia\Model\Tools\ModelCriteriaTools;
|
||||
@@ -54,8 +55,13 @@ abstract class BaseI18nLoop extends BaseLoop
|
||||
*
|
||||
* @return mixed the locale
|
||||
*/
|
||||
protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false)
|
||||
{
|
||||
protected function configureI18nProcessing(
|
||||
ModelCriteria $search,
|
||||
$columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
|
||||
$foreignTable = null,
|
||||
$foreignKey = 'ID',
|
||||
$forceReturn = false
|
||||
) {
|
||||
/* manage translations */
|
||||
|
||||
$this->locale = ModelCriteriaTools::getI18n(
|
||||
@@ -69,4 +75,34 @@ abstract class BaseI18nLoop extends BaseLoop
|
||||
$this->getForceReturn()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the search clause for an I18N column, taking care of the back/front context, as default_locale_i18n is
|
||||
* not defined in the backEnd I18N context.
|
||||
*
|
||||
* @param ModelCriteria $search
|
||||
* @param string $columnName the column to search into, such as TITLE
|
||||
* @param string $searchCriteria the search criteria, such as Criterial::LIKE, Criteria::EQUAL, etc.
|
||||
* @param string $searchTerm the searched term
|
||||
*/
|
||||
public function addSearchInI18nColumn($search, $columnName, $searchCriteria, $searchTerm)
|
||||
{
|
||||
if (! $this->getBackendContext()) {
|
||||
$search->where(
|
||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
||||
THEN `requested_locale_i18n`.`$columnName`
|
||||
ELSE `default_locale_i18n`.`$columnName`
|
||||
END " . $searchCriteria . " ?",
|
||||
$searchTerm,
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
} else {
|
||||
$search->where(
|
||||
"`requested_locale_i18n`.`$columnName` $searchCriteria ?",
|
||||
$searchTerm,
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
core/lib/Thelia/Core/Template/Element/BaseLoop.php
Normal file → Executable file
22
core/lib/Thelia/Core/Template/Element/BaseLoop.php
Normal file → Executable file
@@ -86,6 +86,7 @@ abstract class BaseLoop
|
||||
protected $translator = null;
|
||||
|
||||
private static $cacheLoopResult = [];
|
||||
private static $cacheLoopPagination = [];
|
||||
private static $cacheCount = [];
|
||||
|
||||
/** @var array cache of event to dispatch */
|
||||
@@ -498,6 +499,10 @@ abstract class BaseLoop
|
||||
$hash = $this->args->getHash();
|
||||
|
||||
if (($isCaching = $this->isCaching()) && isset(self::$cacheLoopResult[$hash])) {
|
||||
if (isset(self::$cacheLoopPagination[$hash])) {
|
||||
$pagination = self::$cacheLoopPagination[$hash];
|
||||
}
|
||||
|
||||
return self::$cacheLoopResult[$hash];
|
||||
}
|
||||
|
||||
@@ -533,9 +538,15 @@ abstract class BaseLoop
|
||||
}
|
||||
|
||||
$parsedResults = $this->extendsParseResults($this->parseResults($loopResult));
|
||||
|
||||
|
||||
$loopResult->finalizeRows();
|
||||
|
||||
if ($isCaching) {
|
||||
self::$cacheLoopResult[$hash] = $parsedResults;
|
||||
|
||||
if ($pagination instanceof PropelModelPager) {
|
||||
self::$cacheLoopPagination[$hash] = clone $pagination;
|
||||
}
|
||||
}
|
||||
|
||||
return $parsedResults;
|
||||
@@ -708,10 +719,11 @@ abstract class BaseLoop
|
||||
|
||||
$eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_BUILD_ARRAY);
|
||||
if (null !== $eventName) {
|
||||
$this->dispatcher->dispatch(
|
||||
$eventName,
|
||||
new LoopExtendsBuildArrayEvent($this, $search)
|
||||
);
|
||||
$event = new LoopExtendsBuildArrayEvent($this, $search);
|
||||
|
||||
$this->dispatcher->dispatch($eventName, $event);
|
||||
|
||||
$search = $event->getArray();
|
||||
}
|
||||
|
||||
return $search;
|
||||
|
||||
@@ -80,6 +80,20 @@ class LoopResult implements \Iterator, \JsonSerializable
|
||||
|
||||
$this->collection[] = $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the collection once all results have been added.
|
||||
*/
|
||||
public function finalizeRows()
|
||||
{
|
||||
// Fix rows LOOP_TOTAL if parseResults() did not added all resultsCollection items to the collection array
|
||||
// see https://github.com/thelia/thelia/issues/2337
|
||||
if (true === $this->countable && $this->getResultDataCollectionCount() !== $realCount = $this->getCount()) {
|
||||
foreach ($this->collection as &$item) {
|
||||
$item->set('LOOP_TOTAL', $realCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getCount()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
namespace Thelia\Core\Template\Element;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
@@ -28,5 +30,11 @@ interface SearchLoopInterface
|
||||
*/
|
||||
public function getSearchIn();
|
||||
|
||||
/**
|
||||
* @param ModelCriteria $search a query
|
||||
* @param string $searchTerm the searched term
|
||||
* @param array $searchIn available field to search in
|
||||
* @param string $searchCriteria the search criteria, such as Criterial::LIKE, Criteria::EQUAL, etc.
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria);
|
||||
}
|
||||
|
||||
@@ -143,13 +143,12 @@ class Argument
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is available from Thelia 2.2 version
|
||||
*
|
||||
* @param $name
|
||||
* @param null $default
|
||||
* @param bool $mandatory
|
||||
* @param bool $empty
|
||||
* @return Argument
|
||||
* @since 2.2
|
||||
*/
|
||||
public static function createAnyListTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||
{
|
||||
@@ -176,4 +175,46 @@ class Argument
|
||||
$empty
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $default
|
||||
* @param bool $mandatory
|
||||
* @param bool $empty
|
||||
* @return Argument
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public static function createAlphaNumStringTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||
{
|
||||
return new Argument(
|
||||
$name,
|
||||
new TypeCollection(
|
||||
new Type\AlphaNumStringType()
|
||||
),
|
||||
$default,
|
||||
$mandatory,
|
||||
$empty
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $default
|
||||
* @param bool $mandatory
|
||||
* @param bool $empty
|
||||
* @return Argument
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public static function createAlphaNumStringListTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||
{
|
||||
return new Argument(
|
||||
$name,
|
||||
new TypeCollection(
|
||||
new Type\AlphaNumStringListType()
|
||||
),
|
||||
$default,
|
||||
$mandatory,
|
||||
$empty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Model\BrandQuery;
|
||||
@@ -46,6 +47,8 @@ use Thelia\Type\TypeCollection;
|
||||
*/
|
||||
class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
protected $timestampable = true;
|
||||
|
||||
/**
|
||||
@@ -90,28 +93,20 @@ class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoo
|
||||
*/
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"title"
|
||||
];
|
||||
return $this->getStandardI18nSearchFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BrandQuery $search
|
||||
* @param string $searchTerm
|
||||
* @param string $searchIn
|
||||
* @param array $searchIn
|
||||
* @param string $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->_and();
|
||||
|
||||
$search->where(
|
||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
||||
THEN `requested_locale_i18n`.`TITLE`ELSE `default_locale_i18n`.`TITLE`
|
||||
END ".$searchCriteria." ?",
|
||||
$searchTerm,
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
@@ -153,14 +148,7 @@ class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoo
|
||||
$title = $this->getTitle();
|
||||
|
||||
if (!is_null($title)) {
|
||||
$search->where(
|
||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
||||
THEN `requested_locale_i18n`.`TITLE`
|
||||
ELSE `default_locale_i18n`.`TITLE`
|
||||
END ".Criteria::LIKE." ?",
|
||||
"%".$title."%",
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||
}
|
||||
|
||||
$current = $this->getCurrent();
|
||||
|
||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Model\CategoryQuery;
|
||||
@@ -59,9 +60,13 @@ use Thelia\Model\Category as CategoryModel;
|
||||
* @method bool|string getVisible()
|
||||
* @method int[] getExclude()
|
||||
* @method string[] getOrder()
|
||||
* @method int[] getTemplateId()
|
||||
* @method bool getProductCountVisibleOnly()
|
||||
*/
|
||||
class Category extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
protected $timestampable = true;
|
||||
protected $versionable = true;
|
||||
|
||||
@@ -82,11 +87,21 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
Argument::createBooleanTypeArgument('with_prev_next_info', false),
|
||||
Argument::createBooleanTypeArgument('need_count_child', false),
|
||||
Argument::createBooleanTypeArgument('need_product_count', false),
|
||||
Argument::createBooleanTypeArgument('product_count_visible_only', false),
|
||||
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
||||
Argument::createIntListTypeArgument('template_id'),
|
||||
new Argument(
|
||||
'order',
|
||||
new TypeCollection(
|
||||
new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'visible', 'visible_reverse', 'random'))
|
||||
new Type\EnumListType([
|
||||
'id', 'id_reverse',
|
||||
'alpha', 'alpha_reverse',
|
||||
'manual', 'manual_reverse',
|
||||
'visible', 'visible_reverse',
|
||||
'created', 'created_reverse',
|
||||
'updated', 'updated_reverse',
|
||||
'random'
|
||||
])
|
||||
),
|
||||
'manual'
|
||||
),
|
||||
@@ -99,22 +114,20 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
*/
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"title"
|
||||
];
|
||||
return $this->getStandardI18nSearchFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CategoryQuery $search
|
||||
* @param string $searchTerm
|
||||
* @param string $searchIn
|
||||
* @param array $searchIn
|
||||
* @param string $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->_and();
|
||||
|
||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR);
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
@@ -132,8 +145,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
|
||||
$parent = $this->getParent();
|
||||
|
||||
if (!is_null($parent)) {
|
||||
if (null !== $parent) {
|
||||
$search->filterByParent($parent, Criteria::IN);
|
||||
$positionOrderAllowed = true;
|
||||
} else {
|
||||
$positionOrderAllowed = false;
|
||||
}
|
||||
|
||||
$excludeParent = $this->getExcludeParent();
|
||||
@@ -190,6 +206,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
->endUse()
|
||||
;
|
||||
}
|
||||
$templateIdList = $this->getTemplateId();
|
||||
|
||||
if (!is_null($templateIdList)) {
|
||||
$search->filterByDefaultTemplateId($templateIdList, Criteria::IN);
|
||||
}
|
||||
|
||||
$orders = $this->getOrder();
|
||||
|
||||
@@ -219,6 +240,18 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
case "visible_reverse":
|
||||
$search->orderByVisible(Criteria::DESC);
|
||||
break;
|
||||
case "created":
|
||||
$search->addAscendingOrderByColumn('created_at');
|
||||
break;
|
||||
case "created_reverse":
|
||||
$search->addDescendingOrderByColumn('created_at');
|
||||
break;
|
||||
case "updated":
|
||||
$search->addAscendingOrderByColumn('updated_at');
|
||||
break;
|
||||
case "updated_reverse":
|
||||
$search->addDescendingOrderByColumn('updated_at');
|
||||
break;
|
||||
case "random":
|
||||
$search->clearOrderByColumns();
|
||||
$search->addAscendingOrderByColumn('RAND()');
|
||||
@@ -264,7 +297,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
||||
}
|
||||
|
||||
if ($this->getNeedProductCount()) {
|
||||
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProducts());
|
||||
if ($this->getProductCountVisibleOnly()) {
|
||||
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProductsVisibleOnly());
|
||||
} else {
|
||||
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProducts());
|
||||
}
|
||||
}
|
||||
|
||||
$isBackendContext = $this->getBackendContext();
|
||||
|
||||
@@ -49,32 +49,34 @@ class CategoryPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||
{
|
||||
return new ArgumentCollection(
|
||||
Argument::createIntTypeArgument('category', null, true),
|
||||
Argument::createIntTypeArgument('depth'),
|
||||
Argument::createIntTypeArgument('depth', PHP_INT_MAX),
|
||||
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
||||
);
|
||||
}
|
||||
|
||||
public function buildArray()
|
||||
{
|
||||
$id = $this->getCategory();
|
||||
$originalId = $currentId = $this->getCategory();
|
||||
$visible = $this->getVisible();
|
||||
|
||||
$search = CategoryQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($id);
|
||||
if ($visible !== BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
}
|
||||
|
||||
$depth = $this->getDepth();
|
||||
|
||||
$results = array();
|
||||
|
||||
|
||||
$ids = array();
|
||||
|
||||
|
||||
do {
|
||||
$search = CategoryQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($currentId);
|
||||
|
||||
if ($visible !== BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
}
|
||||
|
||||
$category = $search->findOne();
|
||||
|
||||
|
||||
if ($category != null) {
|
||||
$results[] = array(
|
||||
"ID" => $category->getId(),
|
||||
@@ -82,29 +84,26 @@ class CategoryPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||
"URL" => $category->getUrl($this->locale),
|
||||
"LOCALE" => $this->locale,
|
||||
);
|
||||
|
||||
$parent = $category->getParent();
|
||||
|
||||
if ($parent > 0) {
|
||||
|
||||
$currentId = $category->getParent();
|
||||
|
||||
if ($currentId > 0) {
|
||||
// Prevent circular refererences
|
||||
if (in_array($parent, $ids)) {
|
||||
throw new \LogicException(sprintf("Circular reference detected in category ID=%d hierarchy (category ID=%d appears more than one times in path)", $id, $parent));
|
||||
}
|
||||
|
||||
$ids[] = $parent;
|
||||
|
||||
$search = CategoryQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($parent);
|
||||
if ($visible != BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
if (in_array($currentId, $ids)) {
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"Circular reference detected in category ID=%d hierarchy (category ID=%d appears more than one times in path)",
|
||||
$originalId,
|
||||
$currentId
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$ids[] = $currentId;
|
||||
}
|
||||
}
|
||||
} while ($category != null && $parent > 0);
|
||||
|
||||
} while ($category != null && $currentId > 0 && --$depth > 0);
|
||||
|
||||
// Reverse list and build the final result
|
||||
return array_reverse($results);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Model\ContentFolderQuery;
|
||||
@@ -54,6 +55,8 @@ use Thelia\Type\BooleanOrBothType;
|
||||
*/
|
||||
class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
protected $timestampable = true;
|
||||
protected $versionable = true;
|
||||
|
||||
@@ -77,18 +80,15 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
new TypeCollection(
|
||||
new Type\EnumListType(
|
||||
array(
|
||||
'alpha',
|
||||
'alpha-reverse',
|
||||
'manual',
|
||||
'manual_reverse',
|
||||
'id', 'id_reverse',
|
||||
'alpha', 'alpha-reverse', 'alpha_reverse',
|
||||
'manual', 'manual_reverse',
|
||||
'visible', 'visible_reverse',
|
||||
'random',
|
||||
'given_id',
|
||||
'created',
|
||||
'created_reverse',
|
||||
'updated',
|
||||
'updated_reverse',
|
||||
'position',
|
||||
'position_reverse'
|
||||
'created', 'created_reverse',
|
||||
'updated', 'updated_reverse',
|
||||
'position', 'position_reverse'
|
||||
)
|
||||
)
|
||||
),
|
||||
@@ -104,22 +104,20 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
*/
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"title"
|
||||
];
|
||||
return $this->getStandardI18nSearchFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContentQuery $search
|
||||
* @param string $searchTerm
|
||||
* @param string $searchIn
|
||||
* @param array $searchIn
|
||||
* @param string $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->_and();
|
||||
|
||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR);
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
@@ -140,8 +138,8 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
// Select the contents which have $folderDefault as the default folder.
|
||||
$search
|
||||
->useContentFolderQuery('FolderSelect')
|
||||
->filterByDefaultFolder(true)
|
||||
->filterByFolderId($folderDefault, Criteria::IN)
|
||||
->filterByDefaultFolder(true)
|
||||
->filterByFolderId($folderDefault, Criteria::IN)
|
||||
->endUse()
|
||||
;
|
||||
|
||||
@@ -155,7 +153,7 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
|
||||
$search
|
||||
->useContentFolderQuery('FolderSelect')
|
||||
->filterByFolderId($allFolderIDs, Criteria::IN)
|
||||
->filterByFolderId($allFolderIDs, Criteria::IN)
|
||||
->endUse()
|
||||
;
|
||||
|
||||
@@ -163,12 +161,18 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$manualOrderAllowed = (1 == $depth && 1 == count($folderIdList));
|
||||
} else {
|
||||
$search
|
||||
->useContentFolderQuery('FolderSelect')
|
||||
->filterByDefaultFolder(true)
|
||||
->endUse()
|
||||
->leftJoinContentFolder('FolderSelect')
|
||||
->addJoinCondition('FolderSelect', '`FolderSelect`.DEFAULT_FOLDER = 1')
|
||||
;
|
||||
}
|
||||
|
||||
$search->withColumn(
|
||||
'CAST(CASE WHEN ISNULL(`FolderSelect`.POSITION) THEN \'' . PHP_INT_MAX . '\' ELSE `FolderSelect`.POSITION END AS SIGNED)',
|
||||
'position_delegate'
|
||||
);
|
||||
$search->withColumn('`FolderSelect`.FOLDER_ID', 'default_folder_id');
|
||||
$search->withColumn('`FolderSelect`.DEFAULT_FOLDER', 'is_default_folder');
|
||||
|
||||
$current = $this->getCurrent();
|
||||
|
||||
if ($current === true) {
|
||||
@@ -198,19 +202,39 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$title = $this->getTitle();
|
||||
|
||||
if (!is_null($title)) {
|
||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".Criteria::LIKE." ?", "%".$title."%", \PDO::PARAM_STR);
|
||||
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||
}
|
||||
|
||||
$search->withColumn('`FolderSelect`.POSITION', 'position_delegate');
|
||||
$exclude = $this->getExclude();
|
||||
|
||||
if (!is_null($exclude)) {
|
||||
$search->filterById($exclude, Criteria::NOT_IN);
|
||||
}
|
||||
|
||||
$exclude_folder = $this->getExcludeFolder();
|
||||
|
||||
if (!is_null($exclude_folder)) {
|
||||
$search->filterByFolder(
|
||||
FolderQuery::create()->filterById($exclude_folder, Criteria::IN)->find(),
|
||||
Criteria::NOT_IN
|
||||
);
|
||||
}
|
||||
|
||||
$orders = $this->getOrder();
|
||||
|
||||
foreach ($orders as $order) {
|
||||
switch ($order) {
|
||||
case "id":
|
||||
$search->orderById(Criteria::ASC);
|
||||
break;
|
||||
case "id_reverse":
|
||||
$search->orderById(Criteria::DESC);
|
||||
break;
|
||||
case "alpha":
|
||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
case "alpha-reverse":
|
||||
case "alpha_reverse":
|
||||
$search->addDescendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
case "manual":
|
||||
@@ -235,6 +259,12 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$search->orderBy($givenIdMatched, Criteria::DESC);
|
||||
}
|
||||
break;
|
||||
case "visible":
|
||||
$search->orderByVisible(Criteria::ASC);
|
||||
break;
|
||||
case "visible_reverse":
|
||||
$search->orderByVisible(Criteria::DESC);
|
||||
break;
|
||||
case "random":
|
||||
$search->clearOrderByColumns();
|
||||
$search->addAscendingOrderByColumn('RAND()');
|
||||
@@ -260,20 +290,7 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
}
|
||||
}
|
||||
|
||||
$exclude = $this->getExclude();
|
||||
|
||||
if (!is_null($exclude)) {
|
||||
$search->filterById($exclude, Criteria::NOT_IN);
|
||||
}
|
||||
|
||||
$exclude_folder = $this->getExcludeFolder();
|
||||
|
||||
if (!is_null($exclude_folder)) {
|
||||
$search->filterByFolder(
|
||||
FolderQuery::create()->filterById($exclude_folder, Criteria::IN)->find(),
|
||||
Criteria::NOT_IN
|
||||
);
|
||||
}
|
||||
$search->groupById();
|
||||
|
||||
return $search;
|
||||
}
|
||||
@@ -283,7 +300,13 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
/** @var ContentModel $content */
|
||||
foreach ($loopResult->getResultDataCollection() as $content) {
|
||||
$loopResultRow = new LoopResultRow($content);
|
||||
$defaultFolderId = $content->getDefaultFolderId();
|
||||
|
||||
if ((bool) $content->getVirtualColumn('is_default_folder')) {
|
||||
$defaultFolderId = $content->getVirtualColumn('default_folder_id');
|
||||
} else {
|
||||
$defaultFolderId = $content->getDefaultFolderId();
|
||||
}
|
||||
|
||||
$loopResultRow->set("ID", $content->getId())
|
||||
->set("IS_TRANSLATED", $content->getVirtualColumn('IS_TRANSLATED'))
|
||||
->set("LOCALE", $this->locale)
|
||||
|
||||
@@ -118,6 +118,7 @@ class Country extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
|
||||
if (true === $withArea) {
|
||||
$search
|
||||
->distinct()
|
||||
->joinCountryArea('with_area', Criteria::LEFT_JOIN)
|
||||
->where('`with_area`.country_id ' . Criteria::ISNOTNULL);
|
||||
} elseif (false === $withArea) {
|
||||
|
||||
@@ -252,7 +252,9 @@ class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoop
|
||||
->set("RESELLER", $customer->getReseller())
|
||||
->set("SPONSOR", $customer->getSponsor())
|
||||
->set("DISCOUNT", $customer->getDiscount())
|
||||
->set("NEWSLETTER", $customer->getVirtualColumn("is_registered_to_newsletter"));
|
||||
->set("NEWSLETTER", $customer->getVirtualColumn("is_registered_to_newsletter"))
|
||||
->set("CONFIRMATION_TOKEN", $customer->getConfirmationToken())
|
||||
;
|
||||
|
||||
if ($this->getWithPrevNextInfo()) {
|
||||
// Find previous and next category
|
||||
|
||||
@@ -123,6 +123,13 @@ class Feature extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
|
||||
/** @var ProductModel $product */
|
||||
foreach ($products as $product) {
|
||||
if (!$this->getBackendContext()) {
|
||||
$search
|
||||
->useFeatureProductQuery()
|
||||
->filterByProduct($product)
|
||||
->endUse()
|
||||
;
|
||||
}
|
||||
$tplId = $product->getTemplateId();
|
||||
|
||||
if (! is_null($tplId)) {
|
||||
|
||||
@@ -22,6 +22,8 @@ use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Model\FeatureAv;
|
||||
use Thelia\Model\FeatureAvQuery;
|
||||
use Thelia\Model\FeatureProductQuery;
|
||||
use Thelia\Model\Map\FeatureAvTableMap;
|
||||
use Thelia\Model\Map\FeatureProductTableMap;
|
||||
use Thelia\Type\TypeCollection;
|
||||
use Thelia\Type;
|
||||
|
||||
@@ -106,6 +108,24 @@ class FeatureAvailability extends BaseI18nLoop implements PropelSearchLoopInterf
|
||||
}
|
||||
}
|
||||
|
||||
// We do not consider here Free Text values, so be sure that the features values we will get
|
||||
// are not free text ones, e.g. are not defined as free-text feature values in the
|
||||
// feature_product table.
|
||||
// We are doig here something like
|
||||
// SELECT * FROM `feature_av`
|
||||
// WHERE feature_av.FEATURE_ID IN ('7')
|
||||
// AND feature_av.ID not in (
|
||||
// select feature_av_id from feature_product
|
||||
// where feature_id = `feature_av`.feature_id
|
||||
// and feature_av_id = `feature_av`.id
|
||||
// and free_text_value = 1
|
||||
// )
|
||||
$search->where(FeatureAvTableMap::ID . ' NOT IN (
|
||||
SELECT '. FeatureProductTableMap::FEATURE_AV_ID . '
|
||||
FROM ' .FeatureProductTableMap::TABLE_NAME. '
|
||||
WHERE ' . FeatureProductTableMap::FREE_TEXT_VALUE . ' = 1
|
||||
)');
|
||||
|
||||
return $search;
|
||||
}
|
||||
|
||||
@@ -113,26 +133,19 @@ class FeatureAvailability extends BaseI18nLoop implements PropelSearchLoopInterf
|
||||
{
|
||||
/** @var FeatureAv $featureAv */
|
||||
foreach ($loopResult->getResultDataCollection() as $featureAv) {
|
||||
$isFreeText = FeatureProductQuery::create()
|
||||
->filterByFeatureId($featureAv->getFeatureId())
|
||||
->filterByFeatureAvId($featureAv->getId())
|
||||
->findOneByFreeTextValue(true);
|
||||
$loopResultRow = new LoopResultRow($featureAv);
|
||||
$loopResultRow->set("ID", $featureAv->getId())
|
||||
->set("IS_TRANSLATED", $featureAv->getVirtualColumn('IS_TRANSLATED'))
|
||||
->set("LOCALE", $this->locale)
|
||||
->set("FEATURE_ID", $featureAv->getFeatureId())
|
||||
->set("TITLE", $featureAv->getVirtualColumn('i18n_TITLE'))
|
||||
->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO'))
|
||||
->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $featureAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("POSITION", $featureAv->getPosition());
|
||||
$this->addOutputFields($loopResultRow, $featureAv);
|
||||
|
||||
if ($isFreeText === null) {
|
||||
$loopResultRow = new LoopResultRow($featureAv);
|
||||
$loopResultRow->set("ID", $featureAv->getId())
|
||||
->set("IS_TRANSLATED", $featureAv->getVirtualColumn('IS_TRANSLATED'))
|
||||
->set("LOCALE", $this->locale)
|
||||
->set("FEATURE_ID", $featureAv->getFeatureId())
|
||||
->set("TITLE", $featureAv->getVirtualColumn('i18n_TITLE'))
|
||||
->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO'))
|
||||
->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $featureAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("POSITION", $featureAv->getPosition());
|
||||
$this->addOutputFields($loopResultRow, $featureAv);
|
||||
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
|
||||
return $loopResult;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Thelia\Core\Template\Loop;
|
||||
|
||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||
use Thelia\Core\Template\Element\ArraySearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\BaseLoop;
|
||||
use Thelia\Core\Template\Element\LoopResult;
|
||||
@@ -41,27 +42,25 @@ class Feed extends BaseLoop implements ArraySearchLoopInterface
|
||||
|
||||
public function buildArray()
|
||||
{
|
||||
$cachedir = THELIA_ROOT . 'cache/feeds';
|
||||
/** @var AdapterInterface $cacheAdapter */
|
||||
$cacheAdapter = $this->container->get('thelia.cache');
|
||||
|
||||
if (! is_dir($cachedir)) {
|
||||
if (! mkdir($cachedir)) {
|
||||
throw new \Exception(sprintf("Failed to create cache directory '%s'", $cachedir));
|
||||
}
|
||||
$cacheItem = $cacheAdapter->getItem('feed_' . md5($this->getUrl()));
|
||||
|
||||
if (!$cacheItem->isHit()) {
|
||||
$feed = new \SimplePie();
|
||||
$feed->set_feed_url($this->getUrl());
|
||||
|
||||
$feed->init();
|
||||
|
||||
$feed->handle_content_type();
|
||||
|
||||
$cacheItem->expiresAfter($this->getTimeout() * 60);
|
||||
$cacheItem->set($feed->get_items());
|
||||
$cacheAdapter->save($cacheItem);
|
||||
}
|
||||
|
||||
$feed = new \SimplePie();
|
||||
$feed->set_feed_url($this->getUrl());
|
||||
$feed->set_cache_location(THELIA_ROOT . 'cache/feeds');
|
||||
|
||||
$feed->init();
|
||||
|
||||
$feed->handle_content_type();
|
||||
|
||||
$feed->set_timeout($this->getTimeout());
|
||||
|
||||
$items = $feed->get_items();
|
||||
|
||||
return $items;
|
||||
return $cacheItem->get();
|
||||
}
|
||||
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
|
||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Model\ContentQuery;
|
||||
@@ -42,9 +43,14 @@ use Thelia\Type\BooleanOrBothType;
|
||||
* @method string getTitle()
|
||||
* @method string[] getOrder()
|
||||
* @method bool getWithPrevNextInfo()
|
||||
* @method bool getNeedCountChild()
|
||||
* @method bool getNeedContentCount()
|
||||
* @method bool getContentCountVisible()
|
||||
*/
|
||||
class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
protected $timestampable = true;
|
||||
protected $versionable = true;
|
||||
|
||||
@@ -61,27 +67,28 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
Argument::createBooleanTypeArgument('not_empty', 0),
|
||||
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
||||
Argument::createAnyTypeArgument('title'),
|
||||
Argument::createBooleanTypeArgument('need_count_child', true),
|
||||
Argument::createBooleanTypeArgument('need_content_count', true),
|
||||
new Argument(
|
||||
'order',
|
||||
new TypeCollection(
|
||||
new Type\EnumListType(
|
||||
[
|
||||
'alpha',
|
||||
'alpha_reverse',
|
||||
'manual',
|
||||
'manual_reverse',
|
||||
'id', 'id_reverse',
|
||||
'alpha', 'alpha_reverse',
|
||||
'manual', 'manual_reverse',
|
||||
'visible', 'visible_reverse',
|
||||
'random',
|
||||
'created',
|
||||
'created_reverse',
|
||||
'updated',
|
||||
'updated_reverse'
|
||||
'created', 'created_reverse',
|
||||
'updated', 'updated_reverse'
|
||||
]
|
||||
)
|
||||
),
|
||||
'manual'
|
||||
),
|
||||
Argument::createIntListTypeArgument('exclude'),
|
||||
Argument::createBooleanTypeArgument('with_prev_next_info', false)
|
||||
Argument::createBooleanTypeArgument('with_prev_next_info', false),
|
||||
Argument::createBooleanOrBothTypeArgument('content_count_visible', true)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -90,36 +97,20 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
*/
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"title"
|
||||
];
|
||||
return $this->getStandardI18nSearchFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderQuery $search
|
||||
* @param string $searchTerm
|
||||
* @param string $searchIn
|
||||
* @param array $searchIn
|
||||
* @param string $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->_and();
|
||||
|
||||
$this->addTitleSearchWhereClause($search, $searchCriteria, $searchTerm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderQuery $search
|
||||
* @param string $criteria
|
||||
* @param string $value
|
||||
*/
|
||||
protected function addTitleSearchWhereClause($search, $criteria, $value)
|
||||
{
|
||||
$search->where(
|
||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$criteria." ?",
|
||||
$value,
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
@@ -140,7 +131,7 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
|
||||
$parent = $this->getParent();
|
||||
|
||||
if (!is_null($parent)) {
|
||||
if (null !== $parent) {
|
||||
$search->filterByParent($parent);
|
||||
}
|
||||
|
||||
@@ -171,7 +162,7 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
$title = $this->getTitle();
|
||||
|
||||
if (!is_null($title)) {
|
||||
$this->addTitleSearchWhereClause($search, Criteria::LIKE, '%'.$title.'%');
|
||||
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||
}
|
||||
|
||||
$visible = $this->getVisible();
|
||||
@@ -184,6 +175,12 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
|
||||
foreach ($orders as $order) {
|
||||
switch ($order) {
|
||||
case "id":
|
||||
$search->orderById(Criteria::ASC);
|
||||
break;
|
||||
case "id_reverse":
|
||||
$search->orderById(Criteria::DESC);
|
||||
break;
|
||||
case "alpha":
|
||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
@@ -196,6 +193,12 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
case "manual":
|
||||
$search->orderByPosition(Criteria::ASC);
|
||||
break;
|
||||
case "visible":
|
||||
$search->orderByVisible(Criteria::ASC);
|
||||
break;
|
||||
case "visible_reverse":
|
||||
$search->orderByVisible(Criteria::DESC);
|
||||
break;
|
||||
case "random":
|
||||
$search->clearOrderByColumns();
|
||||
$search->addAscendingOrderByColumn('RAND()');
|
||||
@@ -221,6 +224,15 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
{
|
||||
$needCountChild = $this->getNeedCountChild();
|
||||
$needContentCount = $this->getNeedContentCount();
|
||||
|
||||
$contentCountVisiblility = $this->getContentCountVisible();
|
||||
|
||||
if ($contentCountVisiblility !== BooleanOrBothType::ANY) {
|
||||
$contentCountVisiblility = $contentCountVisiblility ? 1 : 0;
|
||||
}
|
||||
|
||||
/** @var \Thelia\Model\Folder $folder */
|
||||
foreach ($loopResult->getResultDataCollection() as $folder) {
|
||||
$loopResultRow = new LoopResultRow($folder);
|
||||
@@ -239,11 +251,18 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
->set("META_TITLE", $folder->getVirtualColumn('i18n_META_TITLE'))
|
||||
->set("META_DESCRIPTION", $folder->getVirtualColumn('i18n_META_DESCRIPTION'))
|
||||
->set("META_KEYWORDS", $folder->getVirtualColumn('i18n_META_KEYWORDS'))
|
||||
->set("CHILD_COUNT", $folder->countChild())
|
||||
->set("CONTENT_COUNT", $folder->countAllContents())
|
||||
->set("VISIBLE", $folder->getVisible() ? "1" : "0")
|
||||
->set("POSITION", $folder->getPosition());
|
||||
|
||||
|
||||
if ($needCountChild) {
|
||||
$loopResultRow->set("CHILD_COUNT", $folder->countChild());
|
||||
}
|
||||
|
||||
if ($needContentCount) {
|
||||
$loopResultRow->set("CONTENT_COUNT", $folder->countAllContents($contentCountVisiblility));
|
||||
}
|
||||
|
||||
$isBackendContext = $this->getBackendContext();
|
||||
|
||||
if ($this->getWithPrevNextInfo()) {
|
||||
@@ -286,4 +305,4 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
||||
|
||||
return $loopResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use Thelia\Type\BooleanOrBothType;
|
||||
* {@inheritdoc}
|
||||
* @method int getFolder()
|
||||
* @method bool|string getVisible()
|
||||
* @method int getDepth()
|
||||
* @method string[] getOrder()
|
||||
*/
|
||||
class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||
@@ -40,30 +41,32 @@ class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||
{
|
||||
return new ArgumentCollection(
|
||||
Argument::createIntTypeArgument('folder', null, true),
|
||||
Argument::createIntTypeArgument('depth'),
|
||||
Argument::createIntTypeArgument('depth', PHP_INT_MAX),
|
||||
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
||||
);
|
||||
}
|
||||
|
||||
public function buildArray()
|
||||
{
|
||||
$id = $this->getFolder();
|
||||
$originalId = $currentId = $this->getFolder();
|
||||
$visible = $this->getVisible();
|
||||
|
||||
$search = FolderQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($id);
|
||||
if ($visible !== BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
}
|
||||
|
||||
$depth = $this->getDepth();
|
||||
|
||||
$results = array();
|
||||
|
||||
$ids = array();
|
||||
|
||||
do {
|
||||
$search = FolderQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($currentId);
|
||||
|
||||
if ($visible !== BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
}
|
||||
|
||||
$folder = $search->findOne();
|
||||
|
||||
if ($folder != null) {
|
||||
@@ -73,28 +76,25 @@ class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||
"URL" => $folder->getUrl($this->locale),
|
||||
"LOCALE" => $this->locale,
|
||||
);
|
||||
|
||||
$currentId = $folder->getParent();
|
||||
|
||||
$parent = $folder->getParent();
|
||||
|
||||
if ($parent > 0) {
|
||||
if ($currentId > 0) {
|
||||
// Prevent circular refererences
|
||||
if (in_array($parent, $ids)) {
|
||||
throw new \LogicException(sprintf("Circular reference detected in folder ID=%d hierarchy (folder ID=%d appears more than one times in path)", $id, $parent));
|
||||
if (in_array($currentId, $ids)) {
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"Circular reference detected in folder ID=%d hierarchy (folder ID=%d appears more than one times in path)",
|
||||
$originalId,
|
||||
$currentId
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$ids[] = $parent;
|
||||
|
||||
$search = FolderQuery::create();
|
||||
|
||||
$this->configureI18nProcessing($search, array('TITLE'));
|
||||
|
||||
$search->filterById($parent);
|
||||
if ($visible != BooleanOrBothType::ANY) {
|
||||
$search->filterByVisible($visible);
|
||||
}
|
||||
$ids[] = $currentId;
|
||||
}
|
||||
}
|
||||
} while ($folder != null && $parent > 0);
|
||||
} while ($folder != null && $currentId > 0 && --$depth > 0);
|
||||
|
||||
// Reverse list and build the final result
|
||||
return array_reverse($results);
|
||||
|
||||
@@ -47,6 +47,8 @@ use Thelia\Type\TypeCollection;
|
||||
* @method int[] getExclude()
|
||||
* @method bool|string getActive()
|
||||
* @method string[] getOrder()
|
||||
* @method bool|string getMandatory()
|
||||
* @method bool|string getHidden()
|
||||
*/
|
||||
class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
{
|
||||
@@ -87,24 +89,26 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
'order',
|
||||
new TypeCollection(
|
||||
new Type\EnumListType([
|
||||
'id',
|
||||
'id_reverse',
|
||||
'code',
|
||||
'code_reverse',
|
||||
'title',
|
||||
'title_reverse',
|
||||
'type',
|
||||
'type_reverse',
|
||||
'manual',
|
||||
'manual_reverse',
|
||||
'enabled',
|
||||
'enabled_reverse'
|
||||
'id',
|
||||
'id_reverse',
|
||||
'code',
|
||||
'code_reverse',
|
||||
'title',
|
||||
'title_reverse',
|
||||
'type',
|
||||
'type_reverse',
|
||||
'manual',
|
||||
'manual_reverse',
|
||||
'enabled',
|
||||
'enabled_reverse'
|
||||
])
|
||||
),
|
||||
'manual'
|
||||
),
|
||||
Argument::createIntListTypeArgument('exclude'),
|
||||
Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY)
|
||||
Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY),
|
||||
Argument::createBooleanOrBothTypeArgument('hidden', Type\BooleanOrBothType::ANY),
|
||||
Argument::createBooleanOrBothTypeArgument('mandatory', Type\BooleanOrBothType::ANY)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -169,6 +173,18 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
$search->filterByActivate($active ? 1 : 0, Criteria::EQUAL);
|
||||
}
|
||||
|
||||
$hidden = $this->getHidden();
|
||||
|
||||
if ($hidden !== Type\BooleanOrBothType::ANY) {
|
||||
$search->filterByHidden($hidden ? 1 : 0, Criteria::EQUAL);
|
||||
}
|
||||
|
||||
$mandatory = $this->getMandatory();
|
||||
|
||||
if ($mandatory !== Type\BooleanOrBothType::ANY) {
|
||||
$search->filterByMandatory($mandatory ? 1 : 0, Criteria::EQUAL);
|
||||
}
|
||||
|
||||
$orders = $this->getOrder();
|
||||
|
||||
foreach ($orders as $order) {
|
||||
@@ -245,6 +261,8 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
->set("VERSION", $module->getVersion())
|
||||
->set("CLASS", $module->getFullNamespace())
|
||||
->set("POSITION", $module->getPosition())
|
||||
->set("MANDATORY", $module->getMandatory())
|
||||
->set("HIDDEN", $module->getHidden())
|
||||
->set("EXISTS", $exists);
|
||||
|
||||
$hasConfigurationInterface = false;
|
||||
|
||||
@@ -93,6 +93,7 @@ class OrderCoupon extends BaseLoop implements PropelSearchLoopInterface
|
||||
|
||||
$loopResultRow->set("ID", $orderCoupon->getId())
|
||||
->set("CODE", $orderCoupon->getCode())
|
||||
->set("DISCOUNT_AMOUNT", $orderCoupon->getAmount())
|
||||
->set("TITLE", $orderCoupon->getTitle())
|
||||
->set("SHORT_DESCRIPTION", $orderCoupon->getShortDescription())
|
||||
->set("DESCRIPTION", $orderCoupon->getDescription())
|
||||
@@ -104,6 +105,7 @@ class OrderCoupon extends BaseLoop implements PropelSearchLoopInterface
|
||||
->set("FREE_SHIPPING_FOR_COUNTRIES_LIST", implode(',', $freeShippingForCountriesIds))
|
||||
->set("FREE_SHIPPING_FOR_MODULES_LIST", implode(',', $freeShippingForModulesIds))
|
||||
->set("PER_CUSTOMER_USAGE_COUNT", $orderCoupon->getPerCustomerUsageCount())
|
||||
->set("IS_USAGE_CANCELED", $orderCoupon->getUsageCanceled())
|
||||
;
|
||||
$this->addOutputFields($loopResultRow, $orderCoupon);
|
||||
|
||||
|
||||
@@ -30,9 +30,11 @@ use Thelia\Model\OrderStatus as OrderStatusModel;
|
||||
* Class OrderStatus
|
||||
* @package Thelia\Core\Template\Loop
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
* @author Gilles Bourgeat <gbourgeat@gmail.com>
|
||||
*
|
||||
* @method int[] getId()
|
||||
* @method string getCode()
|
||||
* @method string[] getOrder()
|
||||
*/
|
||||
class OrderStatus extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
{
|
||||
@@ -45,7 +47,17 @@ class OrderStatus extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
{
|
||||
return new ArgumentCollection(
|
||||
Argument::createIntListTypeArgument('id'),
|
||||
Argument::createAnyTypeArgument('code')
|
||||
Argument::createAnyTypeArgument('code'),
|
||||
Argument::createEnumListTypeArgument(
|
||||
'order',
|
||||
[
|
||||
'alpha',
|
||||
'alpha_reverse',
|
||||
'manual',
|
||||
'manual_reverse'
|
||||
],
|
||||
'manual'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,18 +68,33 @@ class OrderStatus extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
/* manage translations */
|
||||
$this->configureI18nProcessing($search);
|
||||
|
||||
$id = $this->getId();
|
||||
|
||||
if (null !== $id) {
|
||||
if (null !== $id = $this->getId()) {
|
||||
$search->filterById($id, Criteria::IN);
|
||||
}
|
||||
|
||||
$code = $this->getCode();
|
||||
|
||||
if (null !== $code) {
|
||||
if (null !== $code = $this->getCode()) {
|
||||
$search->filterByCode($code, Criteria::EQUAL);
|
||||
}
|
||||
|
||||
$orders = $this->getOrder();
|
||||
|
||||
foreach ($orders as $order) {
|
||||
switch ($order) {
|
||||
case "alpha":
|
||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
case "alpha_reverse":
|
||||
$search->addDescendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
case "manual":
|
||||
$search->orderByPosition(Criteria::ASC);
|
||||
break;
|
||||
case "manual_reverse":
|
||||
$search->orderByPosition(Criteria::DESC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $search;
|
||||
}
|
||||
|
||||
@@ -80,6 +107,9 @@ class OrderStatus extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
->set("IS_TRANSLATED", $orderStatus->getVirtualColumn('IS_TRANSLATED'))
|
||||
->set("LOCALE", $this->locale)
|
||||
->set("CODE", $orderStatus->getCode())
|
||||
->set("COLOR", $orderStatus->getColor())
|
||||
->set("POSITION", $orderStatus->getPosition())
|
||||
->set("PROTECTED_STATUS", $orderStatus->getProtectedStatus())
|
||||
->set("TITLE", $orderStatus->getVirtualColumn('i18n_TITLE'))
|
||||
->set("CHAPO", $orderStatus->getVirtualColumn('i18n_CHAPO'))
|
||||
->set("DESCRIPTION", $orderStatus->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
|
||||
@@ -19,6 +19,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Exception\TaxEngineException;
|
||||
@@ -26,6 +27,7 @@ use Thelia\Log\Tlog;
|
||||
use Thelia\Model\CategoryQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Currency as CurrencyModel;
|
||||
use Thelia\Model\Map\ProductPriceTableMap;
|
||||
use Thelia\Model\Map\ProductSaleElementsTableMap;
|
||||
use Thelia\Model\Map\ProductTableMap;
|
||||
@@ -75,12 +77,15 @@ use Thelia\Type\TypeCollection;
|
||||
* @method int[] getFeatureAvailability()
|
||||
* @method string[] getFeatureValues()
|
||||
* @method string[] getAttributeNonStrictMatch()
|
||||
* @method int[] getTemplateId()
|
||||
*/
|
||||
class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
protected $timestampable = true;
|
||||
protected $versionable = true;
|
||||
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
/**
|
||||
* @return ArgumentCollection
|
||||
*/
|
||||
@@ -111,6 +116,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
||||
Argument::createIntTypeArgument('currency'),
|
||||
Argument::createAnyTypeArgument('title'),
|
||||
Argument::createIntListTypeArgument('template_id'),
|
||||
new Argument(
|
||||
'order',
|
||||
new TypeCollection(
|
||||
@@ -124,6 +130,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
'updated', 'updated_reverse',
|
||||
'ref', 'ref_reverse',
|
||||
'visible', 'visible_reverse',
|
||||
'position', 'position_reverse',
|
||||
'promo',
|
||||
'new',
|
||||
'random',
|
||||
@@ -172,10 +179,10 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"ref",
|
||||
"title",
|
||||
];
|
||||
return array_merge(
|
||||
[ 'ref' ],
|
||||
$this->getStandardI18nSearchFields()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,6 +194,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->_and();
|
||||
|
||||
foreach ($searchIn as $index => $searchInElement) {
|
||||
if ($index > 0) {
|
||||
$search->_or();
|
||||
@@ -195,18 +203,10 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
case "ref":
|
||||
$search->filterByRef($searchTerm, $searchCriteria);
|
||||
break;
|
||||
case "title":
|
||||
$search->where(
|
||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
||||
THEN `requested_locale_i18n`.`TITLE`
|
||||
ELSE `default_locale_i18n`.`TITLE`
|
||||
END ".$searchCriteria." ?",
|
||||
$searchTerm,
|
||||
\PDO::PARAM_STR
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
@@ -232,7 +232,9 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
|
||||
$price = $product->getVirtualColumn('price');
|
||||
|
||||
if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) {
|
||||
if (!$this->getBackendContext()
|
||||
&& $securityContext->hasCustomerUser()
|
||||
&& $securityContext->getCustomerUser()->getDiscount() > 0) {
|
||||
$price = $price * (1-($securityContext->getCustomerUser()->getDiscount()/100));
|
||||
}
|
||||
|
||||
@@ -246,7 +248,9 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
}
|
||||
$promoPrice = $product->getVirtualColumn('promo_price');
|
||||
|
||||
if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) {
|
||||
if (!$this->getBackendContext()
|
||||
&& $securityContext->hasCustomerUser()
|
||||
&& $securityContext->getCustomerUser()->getDiscount() > 0) {
|
||||
$promoPrice = $promoPrice * (1-($securityContext->getCustomerUser()->getDiscount()/100));
|
||||
}
|
||||
try {
|
||||
@@ -258,7 +262,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$taxedPromoPrice = null;
|
||||
}
|
||||
|
||||
$default_category_id = $product->getDefaultCategoryId();
|
||||
$defaultCategoryId = $this->getDefaultCategoryId($product);
|
||||
|
||||
$loopResultRow
|
||||
->set("WEIGHT", $product->getVirtualColumn('weight'))
|
||||
@@ -277,9 +281,12 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
->set("IS_NEW", $product->getVirtualColumn('is_new'))
|
||||
->set("PRODUCT_SALE_ELEMENT", $product->getVirtualColumn('pse_id'))
|
||||
->set("PSE_COUNT", $product->getVirtualColumn('pse_count'));
|
||||
|
||||
$this->associateValues($loopResultRow, $product, $defaultCategoryId);
|
||||
|
||||
$this->addOutputFields($loopResultRow, $product);
|
||||
|
||||
$loopResult->addRow($this->associateValues($loopResultRow, $product, $default_category_id));
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
|
||||
return $loopResult;
|
||||
@@ -311,8 +318,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$taxedPrice = null;
|
||||
}
|
||||
|
||||
// Find previous and next product, in the default category.
|
||||
$default_category_id = $product->getDefaultCategoryId();
|
||||
$defaultCategoryId = $this->getDefaultCategoryId($product);
|
||||
|
||||
$loopResultRow
|
||||
->set("BEST_PRICE", $price)
|
||||
@@ -321,7 +327,11 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
->set("IS_PROMO", $product->getVirtualColumn('main_product_is_promo'))
|
||||
->set("IS_NEW", $product->getVirtualColumn('main_product_is_new'));
|
||||
|
||||
$loopResult->addRow($this->associateValues($loopResultRow, $product, $default_category_id));
|
||||
$this->associateValues($loopResultRow, $product, $defaultCategoryId);
|
||||
|
||||
$this->addOutputFields($loopResultRow, $product);
|
||||
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
|
||||
return $loopResult;
|
||||
@@ -330,10 +340,10 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
/**
|
||||
* @param LoopResultRow $loopResultRow the current result row
|
||||
* @param \Thelia\Model\Product $product
|
||||
* @param $default_category_id
|
||||
* @param $defaultCategoryId
|
||||
* @return mixed
|
||||
*/
|
||||
private function associateValues($loopResultRow, $product, $default_category_id)
|
||||
private function associateValues($loopResultRow, $product, $defaultCategoryId)
|
||||
{
|
||||
$display_initial_price = $product->getVirtualColumn('display_initial_price');
|
||||
|
||||
@@ -358,12 +368,12 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
->set("VIRTUAL", $product->getVirtual() ? "1" : "0")
|
||||
->set("VISIBLE", $product->getVisible() ? "1" : "0")
|
||||
->set("TEMPLATE", $product->getTemplateId())
|
||||
->set("DEFAULT_CATEGORY", $default_category_id)
|
||||
->set("DEFAULT_CATEGORY", $defaultCategoryId)
|
||||
->set("TAX_RULE_ID", $product->getTaxRuleId())
|
||||
->set("BRAND_ID", $product->getBrandId() ?: 0)
|
||||
->set("SHOW_ORIGINAL_PRICE", $display_initial_price);
|
||||
|
||||
$this->findNextPrev($loopResultRow, $product, $default_category_id);
|
||||
$this->findNextPrev($loopResultRow, $product, $defaultCategoryId);
|
||||
|
||||
return $loopResultRow;
|
||||
}
|
||||
@@ -371,23 +381,23 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
/**
|
||||
* @param LoopResultRow $loopResultRow
|
||||
* @param ProductModel $product
|
||||
* @param int $defaultFolderId
|
||||
* @param int $defaultCategoryId
|
||||
*/
|
||||
private function findNextPrev(LoopResultRow $loopResultRow, ProductModel $product, $defaultFolderId)
|
||||
private function findNextPrev(LoopResultRow $loopResultRow, ProductModel $product, $defaultCategoryId)
|
||||
{
|
||||
if ($this->getWithPrevNextInfo()) {
|
||||
$currentPosition = ProductCategoryQuery::create()
|
||||
->filterByCategoryId($defaultFolderId)
|
||||
->filterByCategoryId($defaultCategoryId)
|
||||
->filterByProductId($product->getId())
|
||||
->findOne()->getPosition();
|
||||
|
||||
// Find previous and next product
|
||||
$previousQuery = ProductCategoryQuery::create()
|
||||
->filterByCategoryId($defaultFolderId)
|
||||
->filterByCategoryId($defaultCategoryId)
|
||||
->filterByPosition($currentPosition, Criteria::LESS_THAN);
|
||||
|
||||
$nextQuery = ProductCategoryQuery::create()
|
||||
->filterByCategoryId($defaultFolderId)
|
||||
->filterByCategoryId($defaultCategoryId)
|
||||
->filterByPosition($currentPosition, Criteria::GREATER_THAN);
|
||||
|
||||
if (!$this->getBackendContext()) {
|
||||
@@ -500,7 +510,7 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$currency = $this->getCurrentRequest()->getSession()->getCurrency();
|
||||
}
|
||||
|
||||
$defaultCurrency = CurrencyQuery::create()->findOneByByDefault(1);
|
||||
$defaultCurrency = CurrencyModel::getDefaultCurrency();
|
||||
$defaultCurrencySuffix = '_default_currency';
|
||||
|
||||
$priceToCompareAsSQL = '';
|
||||
@@ -571,7 +581,13 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$title = $this->getTitle();
|
||||
|
||||
if (!is_null($title)) {
|
||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".Criteria::LIKE." ?", "%".$title."%", \PDO::PARAM_STR);
|
||||
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||
}
|
||||
|
||||
$templateIdList = $this->getTemplateId();
|
||||
|
||||
if (!is_null($templateIdList)) {
|
||||
$search->filterByTemplateId($templateIdList, Criteria::IN);
|
||||
}
|
||||
|
||||
$manualOrderAllowed = false;
|
||||
@@ -603,13 +619,17 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
$manualOrderAllowed = (1 == $depth && 1 == count($categoryIdList));
|
||||
} else {
|
||||
$search
|
||||
->useProductCategoryQuery('CategorySelect')
|
||||
->filterByDefaultCategory(true)
|
||||
->endUse()
|
||||
->leftJoinProductCategory('CategorySelect')
|
||||
->addJoinCondition('CategorySelect', '`CategorySelect`.DEFAULT_CATEGORY = 1')
|
||||
;
|
||||
}
|
||||
|
||||
$search->withColumn('`CategorySelect`.POSITION', 'position_delegate');
|
||||
$search->withColumn(
|
||||
'CASE WHEN ISNULL(`CategorySelect`.POSITION) THEN ' . PHP_INT_MAX . ' ELSE CAST(`CategorySelect`.POSITION as SIGNED) END',
|
||||
'position_delegate'
|
||||
);
|
||||
$search->withColumn('`CategorySelect`.CATEGORY_ID', 'default_category_id');
|
||||
$search->withColumn('`CategorySelect`.DEFAULT_CATEGORY', 'is_default_category');
|
||||
|
||||
$current = $this->getCurrent();
|
||||
|
||||
@@ -1080,6 +1100,12 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
case "updated_reverse":
|
||||
$search->addDescendingOrderByColumn('updated_at');
|
||||
break;
|
||||
case "position":
|
||||
$search->addAscendingOrderByColumn('position_delegate');
|
||||
break;
|
||||
case "position_reverse":
|
||||
$search->addDescendingOrderByColumn('position_delegate');
|
||||
break;
|
||||
case "given_id":
|
||||
if (null === $id) {
|
||||
throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument');
|
||||
@@ -1099,4 +1125,21 @@ class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
||||
|
||||
return $search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default category id for a product
|
||||
*
|
||||
* @param \Thelia\Model\Product $product
|
||||
* @return null|int
|
||||
*/
|
||||
protected function getDefaultCategoryId($product)
|
||||
{
|
||||
$defaultCategoryId = null;
|
||||
if ((bool) $product->getVirtualColumn('is_default_category')) {
|
||||
$defaultCategoryId = $product->getVirtualColumn('default_category_id');
|
||||
} else {
|
||||
$defaultCategoryId = $product->getDefaultCategoryId();
|
||||
}
|
||||
return $defaultCategoryId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Exception\TaxEngineException;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Currency as CurrencyModel;
|
||||
use Thelia\Model\Map\ProductSaleElementsTableMap;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Type;
|
||||
@@ -150,7 +151,7 @@ class ProductSaleElements extends BaseLoop implements PropelSearchLoopInterface,
|
||||
$search->orderByQuantity(Criteria::DESC);
|
||||
break;
|
||||
case "min_price":
|
||||
$search->addAscendingOrderByColumn('price_FINAL_PRICE', Criteria::ASC);
|
||||
$search->addAscendingOrderByColumn('price_FINAL_PRICE');
|
||||
break;
|
||||
case "max_price":
|
||||
$search->addDescendingOrderByColumn('price_FINAL_PRICE');
|
||||
@@ -184,7 +185,7 @@ class ProductSaleElements extends BaseLoop implements PropelSearchLoopInterface,
|
||||
$currency = $this->getCurrentRequest()->getSession()->getCurrency();
|
||||
}
|
||||
|
||||
$defaultCurrency = CurrencyQuery::create()->findOneByByDefault(1);
|
||||
$defaultCurrency = CurrencyModel::getDefaultCurrency();
|
||||
$defaultCurrencySuffix = '_default_currency';
|
||||
|
||||
$search->joinProductPrice('price', Criteria::LEFT_JOIN)
|
||||
@@ -275,11 +276,32 @@ class ProductSaleElements extends BaseLoop implements PropelSearchLoopInterface,
|
||||
{
|
||||
return [
|
||||
"ref",
|
||||
"ean_code"
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProductSaleElementsQuery $search
|
||||
* @param $searchTerm
|
||||
* @param $searchIn
|
||||
* @param $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
$search->filterByRef($searchTerm, $searchCriteria);
|
||||
$search->_and();
|
||||
|
||||
foreach ($searchIn as $index => $searchInElement) {
|
||||
if ($index > 0) {
|
||||
$search->_or();
|
||||
}
|
||||
switch ($searchInElement) {
|
||||
case "ref":
|
||||
$search->filterByRef($searchTerm, $searchCriteria);
|
||||
break;
|
||||
case "ean_code":
|
||||
$search->filterByEanCode($searchTerm, $searchCriteria);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Model\SaleQuery;
|
||||
@@ -42,6 +43,8 @@ use Thelia\Type\BooleanOrBothType;
|
||||
*/
|
||||
class Sale extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||
{
|
||||
use StandardI18nFieldsSearchTrait;
|
||||
|
||||
protected $timestampable = true;
|
||||
|
||||
/**
|
||||
@@ -89,17 +92,34 @@ class Sale extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoop
|
||||
*/
|
||||
public function getSearchIn()
|
||||
{
|
||||
return [
|
||||
"title"
|
||||
];
|
||||
return array_merge(
|
||||
[ "sale_label" ],
|
||||
$this->getStandardI18nSearchFields()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SaleQuery $search
|
||||
* @param string $searchTerm
|
||||
* @param array $searchIn
|
||||
* @param string $searchCriteria
|
||||
*/
|
||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||
{
|
||||
/** @var SaleQuery $search */
|
||||
$search->_and();
|
||||
|
||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR);
|
||||
|
||||
foreach ($searchIn as $index => $searchInElement) {
|
||||
if ($index > 0) {
|
||||
$search->_or();
|
||||
}
|
||||
switch ($searchInElement) {
|
||||
case "sale_label":
|
||||
$this->addSearchInI18nColumn($search, 'SALE_LABEL', $searchCriteria, $searchTerm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
|
||||
@@ -133,6 +133,28 @@ class ParserContext implements \IteratorAggregate
|
||||
{
|
||||
$formErrorInformation = $this->getSession()->getFormErrorInformation();
|
||||
|
||||
// Get form field error details
|
||||
$formFieldErrors = [];
|
||||
|
||||
/** @var Form $field */
|
||||
foreach ($form->getForm()->getIterator() as $field) {
|
||||
$errors = $field->getErrors();
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$formFieldErrors[$field->getName()] = [];
|
||||
|
||||
/** @var FormError $error */
|
||||
foreach ($errors as $error) {
|
||||
$formFieldErrors[$field->getName()][] = [
|
||||
'message' => $error->getMessage(),
|
||||
'template' => $error->getMessageTemplate(),
|
||||
'parameters' => $error->getMessageParameters(),
|
||||
'pluralization' => $error->getMessagePluralization()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->set(get_class($form) . ":" . $form->getType(), $form);
|
||||
|
||||
// Set form error information
|
||||
@@ -142,7 +164,8 @@ class ParserContext implements \IteratorAggregate
|
||||
'errorMessage' => $form->getErrorMessage(),
|
||||
'method' => $this->requestStack->getCurrentRequest()->getMethod(),
|
||||
'timestamp' => time(),
|
||||
'validation_groups' => $form->getForm()->getConfig()->getOption('validation_groups')
|
||||
'validation_groups' => $form->getForm()->getConfig()->getOption('validation_groups'),
|
||||
'field_errors' => $formFieldErrors
|
||||
];
|
||||
|
||||
$this->getSession()->setFormErrorInformation($formErrorInformation);
|
||||
@@ -189,6 +212,26 @@ class ParserContext implements \IteratorAggregate
|
||||
} catch (\Exception $ex) {
|
||||
// Ignore the exception.
|
||||
}
|
||||
|
||||
// Manually set the form fields error information, if validateForm() did not the job,
|
||||
// which is the case when the user has been redirected.
|
||||
foreach ($formInfo['field_errors'] as $fieldName => $errors) {
|
||||
/** @var Form $field */
|
||||
$field = $form->getForm()->get($fieldName);
|
||||
|
||||
if (null !== $field && count($field->getErrors()) == 0) {
|
||||
foreach ($errors as $errorData) {
|
||||
$error = new FormError(
|
||||
$errorData['message'],
|
||||
$errorData['template'],
|
||||
$errorData['parameters'],
|
||||
$errorData['pluralization']
|
||||
);
|
||||
|
||||
$field->addError($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form->setError($formInfo['hasError']);
|
||||
|
||||
@@ -50,7 +50,7 @@ use Thelia\Model\ModuleQuery;
|
||||
|
||||
class Thelia extends Kernel
|
||||
{
|
||||
const THELIA_VERSION = '2.3.1';
|
||||
const THELIA_VERSION = '2.3.4';
|
||||
|
||||
public function __construct($environment, $debug)
|
||||
{
|
||||
@@ -136,6 +136,15 @@ class Thelia extends Kernel
|
||||
$canUpdate = true;
|
||||
Tlog::getInstance()->addWarning("Remove sql_mode ONLY_FULL_GROUP_BY. Please configure your MySQL server.");
|
||||
}
|
||||
|
||||
// remove STRICT_ALL_TABLES, the scheme has been fixed in version 2.4 of Thelia
|
||||
if (version_compare(Thelia::THELIA_VERSION, '2.4', '<')) {
|
||||
if (($key = array_search('STRICT_ALL_TABLES', $sessionSqlMode)) !== false) {
|
||||
unset($sessionSqlMode[$key]);
|
||||
$canUpdate = true;
|
||||
Tlog::getInstance()->addWarning("Remove sql_mode STRICT_ALL_TABLES. Please configure your MySQL server or update your Thelia on version 2.4 or higher.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user