Quelques modifs de style front-office
This commit is contained in:
31
local/modules/StockAlert/Config/config.xml
Normal file
31
local/modules/StockAlert/Config/config.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<forms>
|
||||
<form name="stockalert.subscribe.form" class="StockAlert\Form\StockAlertSubscribe" />
|
||||
<form name= "stockalert.configuration.form" class="StockAlert\Form\StockAlertConfig" />
|
||||
</forms>
|
||||
|
||||
<loops>
|
||||
<loop name="restocking-alert" class="StockAlert\Loop\RestockingAlertLoop" />
|
||||
</loops>
|
||||
|
||||
<services>
|
||||
<service id="stockalert.alert.manager" class="StockAlert\EventListeners\StockAlertManager" scope="request">
|
||||
<argument type="service" id="mailer"/>
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
</services>
|
||||
|
||||
<hooks>
|
||||
<hook id="stockalert.hook" class="StockAlert\Hook\StockAlertHook" scope="request">
|
||||
<tag name="hook.event_listener" event="product.stock-alert" type="front" method="onProductDetailsBottom" />
|
||||
<tag name="hook.event_listener" event="product.details-bottom" type="front" method="onProductDetailsBottom" />
|
||||
<tag name="hook.event_listener" event="product.javascript-initialization" type="front" />
|
||||
<tag name="hook.event_listener" event="module.configuration" type="back" />
|
||||
</hook>
|
||||
</hooks>
|
||||
</config>
|
||||
2
local/modules/StockAlert/Config/destroy.sql
Normal file
2
local/modules/StockAlert/Config/destroy.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS `restocking_alert`;
|
||||
|
||||
24
local/modules/StockAlert/Config/module.xml
Normal file
24
local/modules/StockAlert/Config/module.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module xmlns="http://thelia.net/schema/dic/module"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/module http://thelia.net/schema/dic/module/module-2_1.xsd">
|
||||
<fullnamespace>StockAlert\StockAlert</fullnamespace>
|
||||
<descriptive locale="en_US">
|
||||
<title>Stock Alerts</title>
|
||||
</descriptive>
|
||||
<descriptive locale="fr_FR">
|
||||
<title>Alertes Stock</title>
|
||||
</descriptive>
|
||||
<languages>
|
||||
<language>en_US</language>
|
||||
<language>fr_FR</language>
|
||||
</languages>
|
||||
<version>1.2</version>
|
||||
<author>
|
||||
<name>Julien Chanséaume</name>
|
||||
<email>julien@thelia.net</email>
|
||||
</author>
|
||||
<type>classic</type>
|
||||
<thelia>2.1.0</thelia>
|
||||
<stability>rc</stability>
|
||||
</module>
|
||||
15
local/modules/StockAlert/Config/routing.xml
Normal file
15
local/modules/StockAlert/Config/routing.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="stockalert.front.subscribe" path="/module/stockalert/subscribe" methods="post">
|
||||
<default key="_controller">StockAlert\Controller\StockAlertFrontOfficeController::subscribe</default>
|
||||
</route>
|
||||
|
||||
<route id="stockalert.back.subscribe" path="/admin/module/stockalert/configuration" methods="post">
|
||||
<default key="_controller">StockAlert\Controller\StockAlertBackOfficeController::configuration</default>
|
||||
</route>
|
||||
|
||||
</routes>
|
||||
22
local/modules/StockAlert/Config/schema.xml
Normal file
22
local/modules/StockAlert/Config/schema.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<database defaultIdMethod="native" name="thelia"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../../core/vendor/propel/propel/resources/xsd/database.xsd" >
|
||||
|
||||
<table name="restocking_alert" namespace="StockAlert\Model">
|
||||
|
||||
<column name="id" primaryKey="true" autoIncrement="true" required="true" type="INTEGER" />
|
||||
<column name="product_sale_elements_id" required="true" type="INTEGER" />
|
||||
<column name="email" size="255" type="VARCHAR" />
|
||||
<column name="locale" size="45" type="VARCHAR" />
|
||||
|
||||
<foreign-key foreignTable="product_sale_elements" name="fk_restocking_alert_product_sale_elements_id" onDelete="CASCADE" >
|
||||
<reference foreign="id" local="product_sale_elements_id" />
|
||||
</foreign-key>
|
||||
|
||||
<behavior name="timestampable" />
|
||||
|
||||
</table>
|
||||
|
||||
<external-schema filename="local/config/schema.xml" referenceOnly="true" />
|
||||
|
||||
</database>
|
||||
29
local/modules/StockAlert/Config/thelia.sql
Normal file
29
local/modules/StockAlert/Config/thelia.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
# This is a fix for InnoDB in MySQL >= 4.1.x
|
||||
# It "suspends judgement" for fkey relationships until are tables are set.
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- restocking_alert
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `restocking_alert`;
|
||||
|
||||
CREATE TABLE `restocking_alert`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`product_sale_elements_id` INTEGER NOT NULL,
|
||||
`email` VARCHAR(255),
|
||||
`locale` VARCHAR(45),
|
||||
`created_at` DATETIME,
|
||||
`updated_at` DATETIME,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `FI_restocking_alert_product_sale_elements_id` (`product_sale_elements_id`),
|
||||
CONSTRAINT `fk_restocking_alert_product_sale_elements_id`
|
||||
FOREIGN KEY (`product_sale_elements_id`)
|
||||
REFERENCES `product_sale_elements` (`id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
# This restores the fkey checks, after having unset them earlier
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Controller;
|
||||
|
||||
|
||||
use StockAlert\StockAlert;
|
||||
use Thelia\Controller\Admin\BaseAdminController;
|
||||
use Thelia\Form\Exception\FormValidationException;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
/**
|
||||
* Class StockAlertBackOfficeController
|
||||
* @package StockAlert\Controller
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertBackOfficeController extends BaseAdminController
|
||||
{
|
||||
|
||||
public function configuration()
|
||||
{
|
||||
$errorMessage = null;
|
||||
|
||||
$form = $this->createForm('stockalert.configuration.form', 'form');
|
||||
|
||||
try {
|
||||
$configForm = $this->validateForm($form)->getData();
|
||||
|
||||
ConfigQuery::write(StockAlert::CONFIG_ENABLED, $configForm['enabled']);
|
||||
ConfigQuery::write(StockAlert::CONFIG_THRESHOLD, $configForm['threshold']);
|
||||
$emails = str_replace(' ', '', $configForm['emails']);
|
||||
ConfigQuery::write(StockAlert::CONFIG_EMAILS, $emails);
|
||||
|
||||
return $this->generateSuccessRedirect($form);
|
||||
} catch (FormValidationException $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
$form->setErrorMessage($errorMessage);
|
||||
|
||||
$this->getParserContext()
|
||||
->addForm($form)
|
||||
->setGeneralError($errorMessage);
|
||||
|
||||
return $this->render(
|
||||
"module-configure",
|
||||
[
|
||||
"module_code" => StockAlert::getModuleCode()
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Controller;
|
||||
|
||||
use StockAlert\Event\StockAlertEvent;
|
||||
use StockAlert\Event\StockAlertEvents;
|
||||
use StockAlert\StockAlert;
|
||||
use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Form\Exception\FormValidationException;
|
||||
|
||||
/**
|
||||
* Class RestockingAlertFrontOfficeController
|
||||
* @package StockAlert\Controller
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertFrontOfficeController extends BaseFrontController
|
||||
{
|
||||
|
||||
public function subscribe()
|
||||
{
|
||||
$errorMessage = null;
|
||||
|
||||
$form = $this->createForm('stockalert.subscribe.form', 'form');
|
||||
|
||||
try {
|
||||
$subscribeForm = $this->validateForm($form)->getData();
|
||||
|
||||
$subscriberEvent = new StockAlertEvent(
|
||||
$subscribeForm['product_sale_elements_id'],
|
||||
$subscribeForm['email'],
|
||||
$this->getRequest()->getSession()->getLang()->getLocale()
|
||||
);
|
||||
|
||||
$this->dispatch(StockAlertEvents::STOCK_ALERT_SUBSCRIBE, $subscriberEvent);
|
||||
|
||||
return $this->jsonResponse(
|
||||
json_encode(
|
||||
[
|
||||
"success" => true,
|
||||
"message" => $this->getTranslator()->trans(
|
||||
"Your request has been taken into account",
|
||||
[],
|
||||
StockAlert::MESSAGE_DOMAIN
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
} catch (FormValidationException $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
return $this->jsonResponse(
|
||||
json_encode(
|
||||
[
|
||||
"success" => false,
|
||||
"message" => $errorMessage
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace StockAlert\Event;
|
||||
|
||||
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementEvent;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
|
||||
/**
|
||||
* Class ProductSaleElementAvailabilityEvent
|
||||
* @package StockAlert\Event
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class ProductSaleElementAvailabilityEvent extends ProductSaleElementEvent
|
||||
{
|
||||
|
||||
/** @var bool */
|
||||
protected $available = true;
|
||||
|
||||
|
||||
public function __construct(ProductSaleElements $product_sale_element = null)
|
||||
{
|
||||
$this->product_sale_element = $product_sale_element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
return $this->available;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $available
|
||||
*/
|
||||
public function setAvailable($available)
|
||||
{
|
||||
$this->available = $available;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
121
local/modules/StockAlert/Event/StockAlertEvent.php
Normal file
121
local/modules/StockAlert/Event/StockAlertEvent.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Event;
|
||||
|
||||
use StockAlert\Model\Base\RestockingAlert;
|
||||
use Thelia\Core\Event\ActionEvent;
|
||||
|
||||
/**
|
||||
* Class StockAlertEvent
|
||||
* @package StockAlert\Event
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertEvent extends ActionEvent
|
||||
{
|
||||
|
||||
/** @var int */
|
||||
private $productSaleElementsId;
|
||||
|
||||
/** @var string */
|
||||
private $email;
|
||||
|
||||
/** @var string */
|
||||
private $locale;
|
||||
|
||||
/** @var RestockingAlert */
|
||||
private $restockingAlert;
|
||||
|
||||
/**
|
||||
* @param $productSaleElementsId
|
||||
* @param $email
|
||||
*/
|
||||
public function __construct($productSaleElementsId, $email, $locale)
|
||||
{
|
||||
$this->setEmail($email);
|
||||
$this->setProductSaleElementsId($productSaleElementsId);
|
||||
$this->setLocale($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $email
|
||||
*/
|
||||
public function setEmail($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProductSaleElementsId()
|
||||
{
|
||||
return $this->productSaleElementsId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $productSaleElementsId
|
||||
*/
|
||||
public function setProductSaleElementsId($productSaleElementsId)
|
||||
{
|
||||
$this->productSaleElementsId = $productSaleElementsId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RestockingAlert
|
||||
*/
|
||||
public function getRestockingAlert()
|
||||
{
|
||||
return $this->restockingAlert;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RestockingAlert $restockingAlert
|
||||
*/
|
||||
public function setRestockingAlert($restockingAlert)
|
||||
{
|
||||
$this->restockingAlert = $restockingAlert;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setLocale($locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
26
local/modules/StockAlert/Event/StockAlertEvents.php
Normal file
26
local/modules/StockAlert/Event/StockAlertEvents.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Event;
|
||||
|
||||
/**
|
||||
* Class StockAlertEvents
|
||||
* @package RestockingAlert\Event
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*
|
||||
*/
|
||||
class StockAlertEvents
|
||||
{
|
||||
const STOCK_ALERT_SUBSCRIBE = "stockalert.subscribe";
|
||||
const STOCK_ALERT_CHECK_AVAILABILITY = "stockalert.check.availability";
|
||||
}
|
||||
234
local/modules/StockAlert/EventListeners/StockAlertManager.php
Normal file
234
local/modules/StockAlert/EventListeners/StockAlertManager.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\EventListeners;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use StockAlert\Event\ProductSaleElementAvailabilityEvent;
|
||||
use StockAlert\Event\StockAlertEvent;
|
||||
use StockAlert\Event\StockAlertEvents;
|
||||
use StockAlert\Model\RestockingAlert;
|
||||
use StockAlert\Model\RestockingAlertQuery;
|
||||
use StockAlert\StockAlert;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Thelia\Core\Event\Order\OrderEvent;
|
||||
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementUpdateEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Mailer\MailerFactory;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Lang;
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
|
||||
/**
|
||||
* Class StockAlertManager
|
||||
* @package StockAlert\EventListeners
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertManager implements EventSubscriberInterface
|
||||
{
|
||||
protected $mailer;
|
||||
|
||||
public function __construct(MailerFactory $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of event names this subscriber wants to listen to.
|
||||
* @return array The event names to listen to
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
StockAlertEvents::STOCK_ALERT_SUBSCRIBE => ['subscribe', 128],
|
||||
TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => ['checkStock', 120],
|
||||
TheliaEvents::ORDER_UPDATE_STATUS => ['checkStockForAdmin', 128],
|
||||
];
|
||||
}
|
||||
|
||||
public function subscribe(StockAlertEvent $event)
|
||||
{
|
||||
$productSaleElementsId = $event->getProductSaleElementsId();
|
||||
$email = $event->getEmail();
|
||||
|
||||
if (!isset($productSaleElementsId)) {
|
||||
throw new \Exception("missing param");
|
||||
}
|
||||
|
||||
if (!isset($email)) {
|
||||
throw new \Exception("missing param");
|
||||
}
|
||||
|
||||
// test if it already exists
|
||||
$subscribe = RestockingAlertQuery::create()
|
||||
->filterByEmail($email)
|
||||
->filterByProductSaleElementsId($productSaleElementsId)
|
||||
->findOne();
|
||||
|
||||
if (null === $subscribe) {
|
||||
$subscribe = new RestockingAlert();
|
||||
$subscribe
|
||||
->setProductSaleElementsId($productSaleElementsId)
|
||||
->setEmail($email)
|
||||
->setLocale($event->getLocale())
|
||||
->save();
|
||||
} else {
|
||||
throw new \Exception(
|
||||
Translator::getInstance()->trans(
|
||||
"You have already subscribed to this product",
|
||||
[],
|
||||
StockAlert::MESSAGE_DOMAIN
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$event->setRestockingAlert($subscribe);
|
||||
}
|
||||
|
||||
|
||||
public function checkStock(ProductSaleElementUpdateEvent $productSaleElementUpdateEvent)
|
||||
{
|
||||
if ($productSaleElementUpdateEvent->getQuantity() > 0) {
|
||||
// add extra checking
|
||||
$pse = ProductSaleElementsQuery::create()->findPk(
|
||||
$productSaleElementUpdateEvent->getProductSaleElementId()
|
||||
);
|
||||
$availabilityEvent = new ProductSaleElementAvailabilityEvent(
|
||||
$pse
|
||||
);
|
||||
|
||||
$productSaleElementUpdateEvent->getDispatcher()->dispatch(
|
||||
StockAlertEvents::STOCK_ALERT_CHECK_AVAILABILITY,
|
||||
$availabilityEvent
|
||||
);
|
||||
|
||||
if ($availabilityEvent->isAvailable()) {
|
||||
$subscribers = RestockingAlertQuery::create()
|
||||
->filterByProductSaleElementsId($productSaleElementUpdateEvent->getProductSaleElementId())
|
||||
->find();
|
||||
|
||||
if (null !== $subscribers) {
|
||||
foreach ($subscribers as $subscriber) {
|
||||
try {
|
||||
$this->sendEmail($subscriber);
|
||||
$subscriber->delete();
|
||||
} catch (\Exception $ex) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RestockingAlert $subscriber
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function sendEmail(RestockingAlert $subscriber)
|
||||
{
|
||||
$contactEmail = ConfigQuery::read('store_email');
|
||||
|
||||
if ($contactEmail) {
|
||||
$pse = ProductSaleElementsQuery::create()->findPk($subscriber->getProductSaleElementsId());
|
||||
|
||||
$this->mailer->sendEmailMessage(
|
||||
'stockalert_customer',
|
||||
[ $contactEmail => ConfigQuery::read('store_name') ],
|
||||
[ $subscriber->getEmail() => ConfigQuery::read('store_name') ],
|
||||
[
|
||||
'locale' => $subscriber->getLocale(),
|
||||
'pse_id' => $pse->getId(),
|
||||
'product_id' => $pse->getProductId(),
|
||||
'product_title' => $pse->getProduct()->setLocale($subscriber->getLocale())->getTitle()
|
||||
],
|
||||
$subscriber->getLocale()
|
||||
);
|
||||
|
||||
Tlog::getInstance()->debug("Restocking Alert sent to customer " . $subscriber->getEmail());
|
||||
} else {
|
||||
Tlog::getInstance()->debug(
|
||||
"Restocking Alert: no contact email is defined !"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkStockForAdmin(OrderEvent $event)
|
||||
{
|
||||
$order = $event->getOrder();
|
||||
|
||||
$config = StockAlert::getConfig();
|
||||
|
||||
$pseIds = [];
|
||||
|
||||
foreach ($order->getOrderProducts() as $orderProduct) {
|
||||
$pseIds[] = $orderProduct->getProductSaleElementsId();
|
||||
}
|
||||
|
||||
if ($config['enabled']) {
|
||||
$threshold = $config['threshold'];
|
||||
|
||||
$productIds = ProductQuery::create()
|
||||
->useProductSaleElementsQuery()
|
||||
->filterById($pseIds, Criteria::IN)
|
||||
->filterByQuantity($threshold, Criteria::LESS_EQUAL)
|
||||
// exclude virtual product with weight at 0
|
||||
->filterByWeight(0, Criteria::NOT_EQUAL)
|
||||
->endUse()
|
||||
->select('Id')
|
||||
->find()
|
||||
->toArray();
|
||||
|
||||
if (!empty($productIds)) {
|
||||
$this->sendEmailForAdmin($config['emails'], $productIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function sendEmailForAdmin($emails, $productIds)
|
||||
{
|
||||
$locale = Lang::getDefaultLanguage()->getLocale();
|
||||
|
||||
$contactEmail = ConfigQuery::read('store_email');
|
||||
|
||||
if ($contactEmail) {
|
||||
$storeName = ConfigQuery::read('store_name');
|
||||
|
||||
$to = [];
|
||||
|
||||
foreach ($emails as $recipient) {
|
||||
$to[$recipient] = $storeName;
|
||||
}
|
||||
|
||||
$this->mailer->sendEmailMessage(
|
||||
'stockalert_administrator',
|
||||
[ $contactEmail => $storeName ],
|
||||
$to,
|
||||
[
|
||||
'locale' => $locale,
|
||||
'products_id' => $productIds
|
||||
],
|
||||
$locale
|
||||
);
|
||||
|
||||
Tlog::getInstance()->debug("Stock Alert sent to administrator " . implode(', ', $emails));
|
||||
} else {
|
||||
Tlog::getInstance()->debug("Restocking Alert: no contact email is defined !");
|
||||
}
|
||||
}
|
||||
}
|
||||
148
local/modules/StockAlert/Form/StockAlertConfig.php
Normal file
148
local/modules/StockAlert/Form/StockAlertConfig.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Form;
|
||||
|
||||
use StockAlert\StockAlert;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\ExecutionContextInterface;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Form\BaseForm;
|
||||
|
||||
/**
|
||||
* Class StockAlertConfig
|
||||
* @package StockAlert\Form
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertConfig extends BaseForm
|
||||
{
|
||||
/** @var Translator $translator */
|
||||
protected $translator;
|
||||
|
||||
public function checkEmails($value, ExecutionContextInterface $context)
|
||||
{
|
||||
$data = $context->getRoot()->getData();
|
||||
|
||||
$value = trim($value);
|
||||
|
||||
if ("" === trim($value) && !empty($data["enabled"])) {
|
||||
$context->addViolation(
|
||||
$this->trans(
|
||||
"The Emails can not be empty",
|
||||
[
|
||||
"%id" => $value,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$emails = explode(',', $value);
|
||||
foreach ($emails as $email) {
|
||||
if (false === filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$context->addViolation(
|
||||
$this->trans(
|
||||
"'%email' is not a valid email address",
|
||||
["%email" => $email]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function trans($id, $parameters = [])
|
||||
{
|
||||
if (null === $this->translator) {
|
||||
$this->translator = Translator::getInstance();
|
||||
}
|
||||
|
||||
return $this->translator->trans($id, $parameters, StockAlert::MESSAGE_DOMAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the name of you form. This name must be unique
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'stockalert_config_form';
|
||||
}
|
||||
|
||||
protected function buildForm()
|
||||
{
|
||||
$config = StockAlert::getConfig();
|
||||
|
||||
$this->formBuilder
|
||||
->add(
|
||||
'enabled',
|
||||
'checkbox',
|
||||
[
|
||||
"required" => false,
|
||||
"data" => $config['enabled'],
|
||||
"label" => Translator::getInstance()->trans("Enabled", [], StockAlert::MESSAGE_DOMAIN),
|
||||
"label_attr" => [
|
||||
"for" => "enabled"
|
||||
]
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'threshold',
|
||||
'integer',
|
||||
[
|
||||
"required" => true,
|
||||
"constraints" => [
|
||||
new NotBlank(),
|
||||
],
|
||||
"data" => $config['threshold'],
|
||||
"label" => Translator::getInstance()->trans("Threshold", [], StockAlert::MESSAGE_DOMAIN),
|
||||
"label_attr" => [
|
||||
"for" => "email",
|
||||
"help" => Translator::getInstance()->trans(
|
||||
"You will recieve a notification when the quantity in stock is lower or equal to this value.",
|
||||
[],
|
||||
StockAlert::MESSAGE_DOMAIN
|
||||
),
|
||||
]
|
||||
]
|
||||
)
|
||||
->add(
|
||||
"emails",
|
||||
"text",
|
||||
[
|
||||
"constraints" => [
|
||||
new Callback(
|
||||
[
|
||||
"methods" => [
|
||||
[$this, "checkEmails"]
|
||||
]
|
||||
]
|
||||
),
|
||||
],
|
||||
"required" => false,
|
||||
"data" => implode(',', $config['emails']),
|
||||
"label" => Translator::getInstance()->trans(
|
||||
"Email Address",
|
||||
[],
|
||||
StockAlert::MESSAGE_DOMAIN
|
||||
),
|
||||
"label_attr" => [
|
||||
"for" => "emails",
|
||||
"help" => Translator::getInstance()->trans(
|
||||
"A comma separated list of email that will recieve notifications",
|
||||
[],
|
||||
StockAlert::MESSAGE_DOMAIN
|
||||
),
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
66
local/modules/StockAlert/Form/StockAlertSubscribe.php
Normal file
66
local/modules/StockAlert/Form/StockAlertSubscribe.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert\Form;
|
||||
|
||||
use StockAlert\StockAlert;
|
||||
use Symfony\Component\Validator\Constraints\Email;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Form\BaseForm;
|
||||
|
||||
/**
|
||||
* Class RestockingAlertSubscribe
|
||||
* @package RestockingAlert\Form
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertSubscribe extends BaseForm
|
||||
{
|
||||
protected function buildForm()
|
||||
{
|
||||
$this->formBuilder
|
||||
->add(
|
||||
'product_sale_elements_id',
|
||||
'product_sale_elements_id',
|
||||
[
|
||||
'required' => true,
|
||||
"label" => Translator::getInstance()->trans("Product", [], StockAlert::MESSAGE_DOMAIN),
|
||||
"label_attr" => [
|
||||
"for" => "product_sale_elements_id"
|
||||
]
|
||||
]
|
||||
)
|
||||
->add(
|
||||
"email",
|
||||
"email",
|
||||
[
|
||||
"constraints" => [
|
||||
new NotBlank(),
|
||||
new Email()
|
||||
],
|
||||
"label" => Translator::getInstance()->trans("Email Address", [], StockAlert::MESSAGE_DOMAIN),
|
||||
"label_attr" => [
|
||||
"for" => "email"
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the name of you form. This name must be unique
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'stockalert_subscribe_form';
|
||||
}
|
||||
}
|
||||
61
local/modules/StockAlert/Hook/StockAlertHook.php
Normal file
61
local/modules/StockAlert/Hook/StockAlertHook.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace StockAlert\Hook;
|
||||
|
||||
use StockAlert\StockAlert;
|
||||
use Thelia\Core\Event\Hook\HookRenderEvent;
|
||||
use Thelia\Core\Hook\BaseHook;
|
||||
|
||||
/**
|
||||
* Class StockAlertHook
|
||||
* @package StockAlert\Hook
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*/
|
||||
class StockAlertHook extends BaseHook
|
||||
{
|
||||
|
||||
public function onProductDetailsBottom(HookRenderEvent $event)
|
||||
{
|
||||
$event->add(
|
||||
$this->render(
|
||||
"product-details-bottom.html"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function onProductJavascriptInitialization(HookRenderEvent $event)
|
||||
{
|
||||
$event->add(
|
||||
$this->render(
|
||||
"product.javascript-initialization.html"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function onModuleConfiguration(HookRenderEvent $event)
|
||||
{
|
||||
$moduleId = $this->getModule()->getModuleId();
|
||||
$config = StockAlert::getConfig();
|
||||
|
||||
$event->add(
|
||||
$this->render(
|
||||
"configuration.html",
|
||||
[
|
||||
'module_id' => $moduleId,
|
||||
'config' => $config
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
13
local/modules/StockAlert/I18n/backOffice/default/en_US.php
Normal file
13
local/modules/StockAlert/I18n/backOffice/default/en_US.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Actions' => 'Actions',
|
||||
'Configuration.' => 'Configuration.',
|
||||
'Date' => 'Date',
|
||||
'Email' => 'Email',
|
||||
'List of current subscriptions.' => 'List of current subscriptions.',
|
||||
'Product' => 'Product',
|
||||
'Save' => 'Save',
|
||||
'The stock is not not use on the site. Please set the config variable check-available-stock to 1.' => 'The stock is not not use on the site. Please set the config variable check-available-stock to 1.',
|
||||
'There is no subscriptions.' => 'There is no subscriptions.',
|
||||
);
|
||||
13
local/modules/StockAlert/I18n/backOffice/default/fr_FR.php
Normal file
13
local/modules/StockAlert/I18n/backOffice/default/fr_FR.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Actions' => 'Actions',
|
||||
'Configuration.' => 'Configuration',
|
||||
'Date' => 'Date',
|
||||
'Email' => 'Email',
|
||||
'List of current subscriptions.' => 'Abonnements des clients',
|
||||
'Product' => 'Produit',
|
||||
'Save' => 'Enregistrer',
|
||||
'The stock is not not use on the site. Please set the config variable check-available-stock to 1.' => 'Le stock n\'est pas utilisé sur le site. Veuillez mettre la variable check-available-stock à 1.',
|
||||
'There is no subscriptions.' => 'Aucune alerte n\'a encore été créée.',
|
||||
);
|
||||
12
local/modules/StockAlert/I18n/email/default/en_US.php
Normal file
12
local/modules/StockAlert/I18n/email/default/en_US.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Best Regards.' => 'Best Regards.',
|
||||
'Feel free to contact us for any further information' => 'Feel free to contact us for any further information',
|
||||
'Hi' => 'Hi',
|
||||
'Some product(s) is (are) going to be out of stock :' => 'Some product(s) is (are) going to be out of stock :',
|
||||
'The product %title (%pse) is available again.' => 'The product %title (%pse) is available again.',
|
||||
'The product %title (%pse) is now available.' => 'The product %title (%pse) is now available.',
|
||||
'You can now <a href="%url">order this product here</a>.' => 'You can now <a href="%url">order this product here</a>.',
|
||||
'You can now order this product : %url' => 'You can now order this product : %url',
|
||||
);
|
||||
12
local/modules/StockAlert/I18n/email/default/fr_FR.php
Normal file
12
local/modules/StockAlert/I18n/email/default/fr_FR.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Best Regards.' => 'Cordialement.',
|
||||
'Feel free to contact us for any further information' => 'N\'hésitez pas à nous contacter pour toute question ou information.',
|
||||
'Hi' => 'Bonjour',
|
||||
'Some product(s) is (are) going to be out of stock :' => 'certains produits vont bientôt être indisponible :',
|
||||
'The product %title (%pse) is available again.' => 'Le produit %title (%pse) est à nouveau disponible.',
|
||||
'The product %title (%pse) is now available.' => 'Le produit %title (%pse) est à nouveau disponible.',
|
||||
'You can now <a href="%url">order this product here</a>.' => 'Vous pouvez maintenant <a href="%url">le commander en cliquant ici</a>.',
|
||||
'You can now order this product : %url' => 'Vous pouvez maintenant commander le produit : %url',
|
||||
);
|
||||
15
local/modules/StockAlert/I18n/en_US.php
Normal file
15
local/modules/StockAlert/I18n/en_US.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'\'%email\' is not a valid email address' => '\'%email\' is not a valid email address',
|
||||
'A comma separated list of email that will recieve notifications' => 'A comma separated list of email that will recieve notifications',
|
||||
'Email Address' => 'Email Address',
|
||||
'Enabled' => 'Enabled',
|
||||
'List of products nearly out of stock' => 'List of products nearly out of stock',
|
||||
'Product' => 'Product',
|
||||
'The Emails can not be empty' => 'The Emails can not be empty',
|
||||
'Threshold' => 'Threshold',
|
||||
'You have already subscribed to this product' => 'You have already subscribed to this product',
|
||||
'You will recieve a notification when the quantity in stock is lower or equal to this value.' => 'You will recieve a notification when the quantity in stock is lower or equal to this value.',
|
||||
'Your request has been taken into account' => 'Your request has been taken into account',
|
||||
);
|
||||
15
local/modules/StockAlert/I18n/fr_FR.php
Normal file
15
local/modules/StockAlert/I18n/fr_FR.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'\'%email\' is not a valid email address' => '\'%email\' n\'est pas un email valide',
|
||||
'A comma separated list of email that will recieve notifications' => 'Une liste d\'email séparés par des virgules',
|
||||
'Email Address' => 'Adresse email',
|
||||
'Enabled' => 'Activé',
|
||||
'List of products nearly out of stock' => 'Liste des produits bentôt en rupture de stock',
|
||||
'Product' => 'Produit',
|
||||
'The Emails can not be empty' => 'Le champs Email ne peut être vide',
|
||||
'Threshold' => 'Seuil',
|
||||
'You have already subscribed to this product' => 'Vous avez déjà souscrit à ce produit',
|
||||
'You will recieve a notification when the quantity in stock is lower or equal to this value.' => 'Vous recevrez une notification quand la quantité en stock sera inférieure ou égale à cette valeur.',
|
||||
'Your request has been taken into account' => 'Votre demande a été prise en compte',
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Notify me !' => 'Notify me !',
|
||||
'Register your email to be notified when it will be available again.' => 'Register your email to be notified when it will be available again.',
|
||||
'This product is not available for now.' => 'This product is not available for now.',
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Notify me !' => 'Alertez moi !',
|
||||
'Register your email to be notified when it will be available again.' => 'Saisissez votre email pour être alerté quand il sera à nouveau disponible.',
|
||||
'This product is not available for now.' => 'Ce produit n\'est pas disponible pour le moment',
|
||||
);
|
||||
166
local/modules/StockAlert/LICENSE
Normal file
166
local/modules/StockAlert/LICENSE
Normal file
@@ -0,0 +1,166 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
||||
186
local/modules/StockAlert/Loop/RestockingAlertLoop.php
Normal file
186
local/modules/StockAlert/Loop/RestockingAlertLoop.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace StockAlert\Loop;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use StockAlert\Model\RestockingAlert;
|
||||
use StockAlert\Model\RestockingAlertQuery;
|
||||
use Thelia\Core\Template\Element\BaseLoop;
|
||||
use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Type\EnumListType;
|
||||
use Thelia\Type\TypeCollection;
|
||||
|
||||
/**
|
||||
* Class RestockingAlertLoop
|
||||
* @package StockAlert\Loop
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class RestockingAlertLoop extends BaseLoop implements PropelSearchLoopInterface
|
||||
{
|
||||
|
||||
protected $timestampable = true;
|
||||
|
||||
/**
|
||||
* @param LoopResult $loopResult
|
||||
*
|
||||
* @return LoopResult
|
||||
*/
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
{
|
||||
/** @var RestockingAlert $item */
|
||||
foreach ($loopResult->getResultDataCollection() as $item) {
|
||||
|
||||
$loopResultRow = new LoopResultRow($item);
|
||||
|
||||
$loopResultRow
|
||||
->set("ID", $item->getId())
|
||||
->set("PRODUCT_SALE_ELEMENTS_ID", $item->getProductSaleElementsId())
|
||||
->set("EMAIL", $item->getEmail())
|
||||
->set("LOCALE", $item->getLocale())
|
||||
;
|
||||
|
||||
$this->addOutputFields($loopResultRow, $item);
|
||||
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
|
||||
return $loopResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition of loop arguments
|
||||
*
|
||||
* example :
|
||||
*
|
||||
* public function getArgDefinitions()
|
||||
* {
|
||||
* return new ArgumentCollection(
|
||||
*
|
||||
* Argument::createIntListTypeArgument('id'),
|
||||
* new Argument(
|
||||
* 'ref',
|
||||
* new TypeCollection(
|
||||
* new Type\AlphaNumStringListType()
|
||||
* )
|
||||
* ),
|
||||
* Argument::createIntListTypeArgument('category'),
|
||||
* Argument::createBooleanTypeArgument('new'),
|
||||
* ...
|
||||
* );
|
||||
* }
|
||||
*
|
||||
* @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection
|
||||
*/
|
||||
protected function getArgDefinitions()
|
||||
{
|
||||
return new ArgumentCollection(
|
||||
Argument::createIntListTypeArgument('id'),
|
||||
Argument::createIntTypeArgument('email'),
|
||||
Argument::createIntListTypeArgument('product_sale_element'),
|
||||
new Argument(
|
||||
'order',
|
||||
new TypeCollection(
|
||||
new EnumListType(
|
||||
[
|
||||
'id',
|
||||
'id_reverse',
|
||||
'product_sale_element_id',
|
||||
'product_sale_element_id_reverse',
|
||||
'email',
|
||||
'email_reverse',
|
||||
'created',
|
||||
'created_reverse',
|
||||
'updated',
|
||||
'updated_reverse',
|
||||
'random'
|
||||
]
|
||||
)
|
||||
),
|
||||
'id_reverse'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* this method returns a Propel ModelCriteria
|
||||
*
|
||||
* @return \Propel\Runtime\ActiveQuery\ModelCriteria
|
||||
*/
|
||||
public function buildModelCriteria()
|
||||
{
|
||||
$query = RestockingAlertQuery::create();
|
||||
|
||||
$id = $this->getArgValue('id');
|
||||
if (!empty($id)) {
|
||||
$query->filterById($id, Criteria::IN);
|
||||
}
|
||||
|
||||
$email = $this->getArgValue('email');
|
||||
if (!empty($email)) {
|
||||
$query->filterByEmail('%' . $email . '%', Criteria::LIKE);
|
||||
}
|
||||
|
||||
$id = $this->getArgValue('product_sale_element');
|
||||
if (!empty($id)) {
|
||||
$query->filterByProductSaleElementsId($id, Criteria::IN);
|
||||
}
|
||||
|
||||
$orders = $this->getArgValue('order');
|
||||
|
||||
foreach ($orders as $order) {
|
||||
switch ($order) {
|
||||
case "id":
|
||||
$query->orderById(Criteria::ASC);
|
||||
break;
|
||||
case "id_reverse":
|
||||
$query->orderById(Criteria::DESC);
|
||||
break;
|
||||
case "product_sale_element_id":
|
||||
$query->orderByProductSaleElementsId(Criteria::ASC);
|
||||
break;
|
||||
case "product_sale_element_id_reverse":
|
||||
$query->orderByProductSaleElementsId(Criteria::DESC);
|
||||
break;
|
||||
case "email_id":
|
||||
$query->orderByEmail(Criteria::ASC);
|
||||
break;
|
||||
case "email_reverse":
|
||||
$query->orderByEmail(Criteria::DESC);
|
||||
break;
|
||||
case "created":
|
||||
$query->addAscendingOrderByColumn('created_at');
|
||||
break;
|
||||
case "created_reverse":
|
||||
$query->addDescendingOrderByColumn('created_at');
|
||||
break;
|
||||
case "updated":
|
||||
$query->addAscendingOrderByColumn('updated_at');
|
||||
break;
|
||||
case "updated_reverse":
|
||||
$query->addDescendingOrderByColumn('updated_at');
|
||||
break;
|
||||
case "random":
|
||||
$query->clearOrderByColumns();
|
||||
$query->addAscendingOrderByColumn('RAND()');
|
||||
break(2);
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
1479
local/modules/StockAlert/Model/Base/RestockingAlert.php
Normal file
1479
local/modules/StockAlert/Model/Base/RestockingAlert.php
Normal file
File diff suppressed because it is too large
Load Diff
700
local/modules/StockAlert/Model/Base/RestockingAlertQuery.php
Normal file
700
local/modules/StockAlert/Model/Base/RestockingAlertQuery.php
Normal file
@@ -0,0 +1,700 @@
|
||||
<?php
|
||||
|
||||
namespace StockAlert\Model\Base;
|
||||
|
||||
use \Exception;
|
||||
use \PDO;
|
||||
use Propel\Runtime\Propel;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
use Propel\Runtime\ActiveQuery\ModelJoin;
|
||||
use Propel\Runtime\Collection\Collection;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use StockAlert\Model\RestockingAlert as ChildRestockingAlert;
|
||||
use StockAlert\Model\RestockingAlertQuery as ChildRestockingAlertQuery;
|
||||
use StockAlert\Model\Map\RestockingAlertTableMap;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
|
||||
/**
|
||||
* Base class that represents a query for the 'restocking_alert' table.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @method ChildRestockingAlertQuery orderById($order = Criteria::ASC) Order by the id column
|
||||
* @method ChildRestockingAlertQuery orderByProductSaleElementsId($order = Criteria::ASC) Order by the product_sale_elements_id column
|
||||
* @method ChildRestockingAlertQuery orderByEmail($order = Criteria::ASC) Order by the email column
|
||||
* @method ChildRestockingAlertQuery orderByLocale($order = Criteria::ASC) Order by the locale column
|
||||
* @method ChildRestockingAlertQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column
|
||||
* @method ChildRestockingAlertQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column
|
||||
*
|
||||
* @method ChildRestockingAlertQuery groupById() Group by the id column
|
||||
* @method ChildRestockingAlertQuery groupByProductSaleElementsId() Group by the product_sale_elements_id column
|
||||
* @method ChildRestockingAlertQuery groupByEmail() Group by the email column
|
||||
* @method ChildRestockingAlertQuery groupByLocale() Group by the locale column
|
||||
* @method ChildRestockingAlertQuery groupByCreatedAt() Group by the created_at column
|
||||
* @method ChildRestockingAlertQuery groupByUpdatedAt() Group by the updated_at column
|
||||
*
|
||||
* @method ChildRestockingAlertQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
|
||||
* @method ChildRestockingAlertQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query
|
||||
* @method ChildRestockingAlertQuery innerJoin($relation) Adds a INNER JOIN clause to the query
|
||||
*
|
||||
* @method ChildRestockingAlertQuery leftJoinProductSaleElements($relationAlias = null) Adds a LEFT JOIN clause to the query using the ProductSaleElements relation
|
||||
* @method ChildRestockingAlertQuery rightJoinProductSaleElements($relationAlias = null) Adds a RIGHT JOIN clause to the query using the ProductSaleElements relation
|
||||
* @method ChildRestockingAlertQuery innerJoinProductSaleElements($relationAlias = null) Adds a INNER JOIN clause to the query using the ProductSaleElements relation
|
||||
*
|
||||
* @method ChildRestockingAlert findOne(ConnectionInterface $con = null) Return the first ChildRestockingAlert matching the query
|
||||
* @method ChildRestockingAlert findOneOrCreate(ConnectionInterface $con = null) Return the first ChildRestockingAlert matching the query, or a new ChildRestockingAlert object populated from the query conditions when no match is found
|
||||
*
|
||||
* @method ChildRestockingAlert findOneById(int $id) Return the first ChildRestockingAlert filtered by the id column
|
||||
* @method ChildRestockingAlert findOneByProductSaleElementsId(int $product_sale_elements_id) Return the first ChildRestockingAlert filtered by the product_sale_elements_id column
|
||||
* @method ChildRestockingAlert findOneByEmail(string $email) Return the first ChildRestockingAlert filtered by the email column
|
||||
* @method ChildRestockingAlert findOneByLocale(string $locale) Return the first ChildRestockingAlert filtered by the locale column
|
||||
* @method ChildRestockingAlert findOneByCreatedAt(string $created_at) Return the first ChildRestockingAlert filtered by the created_at column
|
||||
* @method ChildRestockingAlert findOneByUpdatedAt(string $updated_at) Return the first ChildRestockingAlert filtered by the updated_at column
|
||||
*
|
||||
* @method array findById(int $id) Return ChildRestockingAlert objects filtered by the id column
|
||||
* @method array findByProductSaleElementsId(int $product_sale_elements_id) Return ChildRestockingAlert objects filtered by the product_sale_elements_id column
|
||||
* @method array findByEmail(string $email) Return ChildRestockingAlert objects filtered by the email column
|
||||
* @method array findByLocale(string $locale) Return ChildRestockingAlert objects filtered by the locale column
|
||||
* @method array findByCreatedAt(string $created_at) Return ChildRestockingAlert objects filtered by the created_at column
|
||||
* @method array findByUpdatedAt(string $updated_at) Return ChildRestockingAlert objects filtered by the updated_at column
|
||||
*
|
||||
*/
|
||||
abstract class RestockingAlertQuery extends ModelCriteria
|
||||
{
|
||||
|
||||
/**
|
||||
* Initializes internal state of \StockAlert\Model\Base\RestockingAlertQuery object.
|
||||
*
|
||||
* @param string $dbName The database name
|
||||
* @param string $modelName The phpName of a model, e.g. 'Book'
|
||||
* @param string $modelAlias The alias for the model in this query, e.g. 'b'
|
||||
*/
|
||||
public function __construct($dbName = 'thelia', $modelName = '\\StockAlert\\Model\\RestockingAlert', $modelAlias = null)
|
||||
{
|
||||
parent::__construct($dbName, $modelName, $modelAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new ChildRestockingAlertQuery object.
|
||||
*
|
||||
* @param string $modelAlias The alias of a model in the query
|
||||
* @param Criteria $criteria Optional Criteria to build the query from
|
||||
*
|
||||
* @return ChildRestockingAlertQuery
|
||||
*/
|
||||
public static function create($modelAlias = null, $criteria = null)
|
||||
{
|
||||
if ($criteria instanceof \StockAlert\Model\RestockingAlertQuery) {
|
||||
return $criteria;
|
||||
}
|
||||
$query = new \StockAlert\Model\RestockingAlertQuery();
|
||||
if (null !== $modelAlias) {
|
||||
$query->setModelAlias($modelAlias);
|
||||
}
|
||||
if ($criteria instanceof Criteria) {
|
||||
$query->mergeWith($criteria);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find object by primary key.
|
||||
* Propel uses the instance pool to skip the database if the object exists.
|
||||
* Go fast if the query is untouched.
|
||||
*
|
||||
* <code>
|
||||
* $obj = $c->findPk(12, $con);
|
||||
* </code>
|
||||
*
|
||||
* @param mixed $key Primary key to use for the query
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
*
|
||||
* @return ChildRestockingAlert|array|mixed the result, formatted by the current formatter
|
||||
*/
|
||||
public function findPk($key, $con = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
return null;
|
||||
}
|
||||
if ((null !== ($obj = RestockingAlertTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) {
|
||||
// the object is already in the instance pool
|
||||
return $obj;
|
||||
}
|
||||
if ($con === null) {
|
||||
$con = Propel::getServiceContainer()->getReadConnection(RestockingAlertTableMap::DATABASE_NAME);
|
||||
}
|
||||
$this->basePreSelect($con);
|
||||
if ($this->formatter || $this->modelAlias || $this->with || $this->select
|
||||
|| $this->selectColumns || $this->asColumns || $this->selectModifiers
|
||||
|| $this->map || $this->having || $this->joins) {
|
||||
return $this->findPkComplex($key, $con);
|
||||
} else {
|
||||
return $this->findPkSimple($key, $con);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find object by primary key using raw SQL to go fast.
|
||||
* Bypass doSelect() and the object formatter by using generated code.
|
||||
*
|
||||
* @param mixed $key Primary key to use for the query
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*
|
||||
* @return ChildRestockingAlert A model object, or null if the key is not found
|
||||
*/
|
||||
protected function findPkSimple($key, $con)
|
||||
{
|
||||
$sql = 'SELECT ID, PRODUCT_SALE_ELEMENTS_ID, EMAIL, LOCALE, CREATED_AT, UPDATED_AT FROM restocking_alert WHERE ID = :p0';
|
||||
try {
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindValue(':p0', $key, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
} catch (Exception $e) {
|
||||
Propel::log($e->getMessage(), Propel::LOG_ERR);
|
||||
throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e);
|
||||
}
|
||||
$obj = null;
|
||||
if ($row = $stmt->fetch(\PDO::FETCH_NUM)) {
|
||||
$obj = new ChildRestockingAlert();
|
||||
$obj->hydrate($row);
|
||||
RestockingAlertTableMap::addInstanceToPool($obj, (string) $key);
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find object by primary key.
|
||||
*
|
||||
* @param mixed $key Primary key to use for the query
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*
|
||||
* @return ChildRestockingAlert|array|mixed the result, formatted by the current formatter
|
||||
*/
|
||||
protected function findPkComplex($key, $con)
|
||||
{
|
||||
// As the query uses a PK condition, no limit(1) is necessary.
|
||||
$criteria = $this->isKeepQuery() ? clone $this : $this;
|
||||
$dataFetcher = $criteria
|
||||
->filterByPrimaryKey($key)
|
||||
->doSelect($con);
|
||||
|
||||
return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find objects by primary key
|
||||
* <code>
|
||||
* $objs = $c->findPks(array(12, 56, 832), $con);
|
||||
* </code>
|
||||
* @param array $keys Primary keys to use for the query
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
*
|
||||
* @return ObjectCollection|array|mixed the list of results, formatted by the current formatter
|
||||
*/
|
||||
public function findPks($keys, $con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = Propel::getServiceContainer()->getReadConnection($this->getDbName());
|
||||
}
|
||||
$this->basePreSelect($con);
|
||||
$criteria = $this->isKeepQuery() ? clone $this : $this;
|
||||
$dataFetcher = $criteria
|
||||
->filterByPrimaryKeys($keys)
|
||||
->doSelect($con);
|
||||
|
||||
return $criteria->getFormatter()->init($criteria)->format($dataFetcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query by primary key
|
||||
*
|
||||
* @param mixed $key Primary key to use for the query
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByPrimaryKey($key)
|
||||
{
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::ID, $key, Criteria::EQUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query by a list of primary keys
|
||||
*
|
||||
* @param array $keys The list of primary key to use for the query
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByPrimaryKeys($keys)
|
||||
{
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::ID, $keys, Criteria::IN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the id column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterById(1234); // WHERE id = 1234
|
||||
* $query->filterById(array(12, 34)); // WHERE id IN (12, 34)
|
||||
* $query->filterById(array('min' => 12)); // WHERE id > 12
|
||||
* </code>
|
||||
*
|
||||
* @param mixed $id The value to use as filter.
|
||||
* Use scalar values for equality.
|
||||
* Use array values for in_array() equivalent.
|
||||
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterById($id = null, $comparison = null)
|
||||
{
|
||||
if (is_array($id)) {
|
||||
$useMinMax = false;
|
||||
if (isset($id['min'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::ID, $id['min'], Criteria::GREATER_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if (isset($id['max'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::ID, $id['max'], Criteria::LESS_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if ($useMinMax) {
|
||||
return $this;
|
||||
}
|
||||
if (null === $comparison) {
|
||||
$comparison = Criteria::IN;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::ID, $id, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the product_sale_elements_id column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterByProductSaleElementsId(1234); // WHERE product_sale_elements_id = 1234
|
||||
* $query->filterByProductSaleElementsId(array(12, 34)); // WHERE product_sale_elements_id IN (12, 34)
|
||||
* $query->filterByProductSaleElementsId(array('min' => 12)); // WHERE product_sale_elements_id > 12
|
||||
* </code>
|
||||
*
|
||||
* @see filterByProductSaleElements()
|
||||
*
|
||||
* @param mixed $productSaleElementsId The value to use as filter.
|
||||
* Use scalar values for equality.
|
||||
* Use array values for in_array() equivalent.
|
||||
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByProductSaleElementsId($productSaleElementsId = null, $comparison = null)
|
||||
{
|
||||
if (is_array($productSaleElementsId)) {
|
||||
$useMinMax = false;
|
||||
if (isset($productSaleElementsId['min'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId['min'], Criteria::GREATER_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if (isset($productSaleElementsId['max'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId['max'], Criteria::LESS_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if ($useMinMax) {
|
||||
return $this;
|
||||
}
|
||||
if (null === $comparison) {
|
||||
$comparison = Criteria::IN;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the email column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterByEmail('fooValue'); // WHERE email = 'fooValue'
|
||||
* $query->filterByEmail('%fooValue%'); // WHERE email LIKE '%fooValue%'
|
||||
* </code>
|
||||
*
|
||||
* @param string $email The value to use as filter.
|
||||
* Accepts wildcards (* and % trigger a LIKE)
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByEmail($email = null, $comparison = null)
|
||||
{
|
||||
if (null === $comparison) {
|
||||
if (is_array($email)) {
|
||||
$comparison = Criteria::IN;
|
||||
} elseif (preg_match('/[\%\*]/', $email)) {
|
||||
$email = str_replace('*', '%', $email);
|
||||
$comparison = Criteria::LIKE;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::EMAIL, $email, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the locale column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterByLocale('fooValue'); // WHERE locale = 'fooValue'
|
||||
* $query->filterByLocale('%fooValue%'); // WHERE locale LIKE '%fooValue%'
|
||||
* </code>
|
||||
*
|
||||
* @param string $locale The value to use as filter.
|
||||
* Accepts wildcards (* and % trigger a LIKE)
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByLocale($locale = null, $comparison = null)
|
||||
{
|
||||
if (null === $comparison) {
|
||||
if (is_array($locale)) {
|
||||
$comparison = Criteria::IN;
|
||||
} elseif (preg_match('/[\%\*]/', $locale)) {
|
||||
$locale = str_replace('*', '%', $locale);
|
||||
$comparison = Criteria::LIKE;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::LOCALE, $locale, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the created_at column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterByCreatedAt('2011-03-14'); // WHERE created_at = '2011-03-14'
|
||||
* $query->filterByCreatedAt('now'); // WHERE created_at = '2011-03-14'
|
||||
* $query->filterByCreatedAt(array('max' => 'yesterday')); // WHERE created_at > '2011-03-13'
|
||||
* </code>
|
||||
*
|
||||
* @param mixed $createdAt The value to use as filter.
|
||||
* Values can be integers (unix timestamps), DateTime objects, or strings.
|
||||
* Empty strings are treated as NULL.
|
||||
* Use scalar values for equality.
|
||||
* Use array values for in_array() equivalent.
|
||||
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByCreatedAt($createdAt = null, $comparison = null)
|
||||
{
|
||||
if (is_array($createdAt)) {
|
||||
$useMinMax = false;
|
||||
if (isset($createdAt['min'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::CREATED_AT, $createdAt['min'], Criteria::GREATER_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if (isset($createdAt['max'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::CREATED_AT, $createdAt['max'], Criteria::LESS_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if ($useMinMax) {
|
||||
return $this;
|
||||
}
|
||||
if (null === $comparison) {
|
||||
$comparison = Criteria::IN;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::CREATED_AT, $createdAt, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query on the updated_at column
|
||||
*
|
||||
* Example usage:
|
||||
* <code>
|
||||
* $query->filterByUpdatedAt('2011-03-14'); // WHERE updated_at = '2011-03-14'
|
||||
* $query->filterByUpdatedAt('now'); // WHERE updated_at = '2011-03-14'
|
||||
* $query->filterByUpdatedAt(array('max' => 'yesterday')); // WHERE updated_at > '2011-03-13'
|
||||
* </code>
|
||||
*
|
||||
* @param mixed $updatedAt The value to use as filter.
|
||||
* Values can be integers (unix timestamps), DateTime objects, or strings.
|
||||
* Empty strings are treated as NULL.
|
||||
* Use scalar values for equality.
|
||||
* Use array values for in_array() equivalent.
|
||||
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByUpdatedAt($updatedAt = null, $comparison = null)
|
||||
{
|
||||
if (is_array($updatedAt)) {
|
||||
$useMinMax = false;
|
||||
if (isset($updatedAt['min'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::UPDATED_AT, $updatedAt['min'], Criteria::GREATER_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if (isset($updatedAt['max'])) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::UPDATED_AT, $updatedAt['max'], Criteria::LESS_EQUAL);
|
||||
$useMinMax = true;
|
||||
}
|
||||
if ($useMinMax) {
|
||||
return $this;
|
||||
}
|
||||
if (null === $comparison) {
|
||||
$comparison = Criteria::IN;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::UPDATED_AT, $updatedAt, $comparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query by a related \Thelia\Model\ProductSaleElements object
|
||||
*
|
||||
* @param \Thelia\Model\ProductSaleElements|ObjectCollection $productSaleElements The related object(s) to use as filter
|
||||
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function filterByProductSaleElements($productSaleElements, $comparison = null)
|
||||
{
|
||||
if ($productSaleElements instanceof \Thelia\Model\ProductSaleElements) {
|
||||
return $this
|
||||
->addUsingAlias(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElements->getId(), $comparison);
|
||||
} elseif ($productSaleElements instanceof ObjectCollection) {
|
||||
if (null === $comparison) {
|
||||
$comparison = Criteria::IN;
|
||||
}
|
||||
|
||||
return $this
|
||||
->addUsingAlias(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElements->toKeyValue('PrimaryKey', 'Id'), $comparison);
|
||||
} else {
|
||||
throw new PropelException('filterByProductSaleElements() only accepts arguments of type \Thelia\Model\ProductSaleElements or Collection');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a JOIN clause to the query using the ProductSaleElements relation
|
||||
*
|
||||
* @param string $relationAlias optional alias for the relation
|
||||
* @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function joinProductSaleElements($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
{
|
||||
$tableMap = $this->getTableMap();
|
||||
$relationMap = $tableMap->getRelation('ProductSaleElements');
|
||||
|
||||
// create a ModelJoin object for this join
|
||||
$join = new ModelJoin();
|
||||
$join->setJoinType($joinType);
|
||||
$join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias);
|
||||
if ($previousJoin = $this->getPreviousJoin()) {
|
||||
$join->setPreviousJoin($previousJoin);
|
||||
}
|
||||
|
||||
// add the ModelJoin to the current object
|
||||
if ($relationAlias) {
|
||||
$this->addAlias($relationAlias, $relationMap->getRightTable()->getName());
|
||||
$this->addJoinObject($join, $relationAlias);
|
||||
} else {
|
||||
$this->addJoinObject($join, 'ProductSaleElements');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the ProductSaleElements relation ProductSaleElements object
|
||||
*
|
||||
* @see useQuery()
|
||||
*
|
||||
* @param string $relationAlias optional alias for the relation,
|
||||
* to be used as main alias in the secondary query
|
||||
* @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'
|
||||
*
|
||||
* @return \Thelia\Model\ProductSaleElementsQuery A secondary query class using the current class as primary query
|
||||
*/
|
||||
public function useProductSaleElementsQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
{
|
||||
return $this
|
||||
->joinProductSaleElements($relationAlias, $joinType)
|
||||
->useQuery($relationAlias ? $relationAlias : 'ProductSaleElements', '\Thelia\Model\ProductSaleElementsQuery');
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude object from result
|
||||
*
|
||||
* @param ChildRestockingAlert $restockingAlert Object to remove from the list of results
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function prune($restockingAlert = null)
|
||||
{
|
||||
if ($restockingAlert) {
|
||||
$this->addUsingAlias(RestockingAlertTableMap::ID, $restockingAlert->getId(), Criteria::NOT_EQUAL);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all rows from the restocking_alert table.
|
||||
*
|
||||
* @param ConnectionInterface $con the connection to use
|
||||
* @return int The number of affected rows (if supported by underlying database driver).
|
||||
*/
|
||||
public function doDeleteAll(ConnectionInterface $con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = Propel::getServiceContainer()->getWriteConnection(RestockingAlertTableMap::DATABASE_NAME);
|
||||
}
|
||||
$affectedRows = 0; // initialize var to track total num of affected rows
|
||||
try {
|
||||
// use transaction because $criteria could contain info
|
||||
// for more than one table or we could emulating ON DELETE CASCADE, etc.
|
||||
$con->beginTransaction();
|
||||
$affectedRows += parent::doDeleteAll($con);
|
||||
// Because this db requires some delete cascade/set null emulation, we have to
|
||||
// clear the cached instance *after* the emulation has happened (since
|
||||
// instances get re-added by the select statement contained therein).
|
||||
RestockingAlertTableMap::clearInstancePool();
|
||||
RestockingAlertTableMap::clearRelatedInstancePool();
|
||||
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $affectedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a DELETE on the database, given a ChildRestockingAlert or Criteria object OR a primary key value.
|
||||
*
|
||||
* @param mixed $values Criteria or ChildRestockingAlert object or primary key or array of primary keys
|
||||
* which is used to create the DELETE statement
|
||||
* @param ConnectionInterface $con the connection to use
|
||||
* @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows
|
||||
* if supported by native driver or if emulated using Propel.
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public function delete(ConnectionInterface $con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = Propel::getServiceContainer()->getWriteConnection(RestockingAlertTableMap::DATABASE_NAME);
|
||||
}
|
||||
|
||||
$criteria = $this;
|
||||
|
||||
// Set the correct dbName
|
||||
$criteria->setDbName(RestockingAlertTableMap::DATABASE_NAME);
|
||||
|
||||
$affectedRows = 0; // initialize var to track total num of affected rows
|
||||
|
||||
try {
|
||||
// use transaction because $criteria could contain info
|
||||
// for more than one table or we could emulating ON DELETE CASCADE, etc.
|
||||
$con->beginTransaction();
|
||||
|
||||
|
||||
RestockingAlertTableMap::removeInstanceFromPool($criteria);
|
||||
|
||||
$affectedRows += ModelCriteria::delete($con);
|
||||
RestockingAlertTableMap::clearRelatedInstancePool();
|
||||
$con->commit();
|
||||
|
||||
return $affectedRows;
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
// timestampable behavior
|
||||
|
||||
/**
|
||||
* Filter by the latest updated
|
||||
*
|
||||
* @param int $nbDays Maximum age of the latest update in days
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function recentlyUpdated($nbDays = 7)
|
||||
{
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::UPDATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by the latest created
|
||||
*
|
||||
* @param int $nbDays Maximum age of in days
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function recentlyCreated($nbDays = 7)
|
||||
{
|
||||
return $this->addUsingAlias(RestockingAlertTableMap::CREATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by update date desc
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function lastUpdatedFirst()
|
||||
{
|
||||
return $this->addDescendingOrderByColumn(RestockingAlertTableMap::UPDATED_AT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by update date asc
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function firstUpdatedFirst()
|
||||
{
|
||||
return $this->addAscendingOrderByColumn(RestockingAlertTableMap::UPDATED_AT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by create date desc
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function lastCreatedFirst()
|
||||
{
|
||||
return $this->addDescendingOrderByColumn(RestockingAlertTableMap::CREATED_AT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by create date asc
|
||||
*
|
||||
* @return ChildRestockingAlertQuery The current query, for fluid interface
|
||||
*/
|
||||
public function firstCreatedFirst()
|
||||
{
|
||||
return $this->addAscendingOrderByColumn(RestockingAlertTableMap::CREATED_AT);
|
||||
}
|
||||
|
||||
} // RestockingAlertQuery
|
||||
456
local/modules/StockAlert/Model/Map/RestockingAlertTableMap.php
Normal file
456
local/modules/StockAlert/Model/Map/RestockingAlertTableMap.php
Normal file
@@ -0,0 +1,456 @@
|
||||
<?php
|
||||
|
||||
namespace StockAlert\Model\Map;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\ActiveQuery\InstancePoolTrait;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Propel\Runtime\DataFetcher\DataFetcherInterface;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Propel\Runtime\Map\RelationMap;
|
||||
use Propel\Runtime\Map\TableMap;
|
||||
use Propel\Runtime\Map\TableMapTrait;
|
||||
use StockAlert\Model\RestockingAlert;
|
||||
use StockAlert\Model\RestockingAlertQuery;
|
||||
|
||||
|
||||
/**
|
||||
* This class defines the structure of the 'restocking_alert' table.
|
||||
*
|
||||
*
|
||||
*
|
||||
* This map class is used by Propel to do runtime db structure discovery.
|
||||
* For example, the createSelectSql() method checks the type of a given column used in an
|
||||
* ORDER BY clause to know whether it needs to apply SQL to make the ORDER BY case-insensitive
|
||||
* (i.e. if it's a text column type).
|
||||
*
|
||||
*/
|
||||
class RestockingAlertTableMap extends TableMap
|
||||
{
|
||||
use InstancePoolTrait;
|
||||
use TableMapTrait;
|
||||
/**
|
||||
* The (dot-path) name of this class
|
||||
*/
|
||||
const CLASS_NAME = 'StockAlert.Model.Map.RestockingAlertTableMap';
|
||||
|
||||
/**
|
||||
* The default database name for this class
|
||||
*/
|
||||
const DATABASE_NAME = 'thelia';
|
||||
|
||||
/**
|
||||
* The table name for this class
|
||||
*/
|
||||
const TABLE_NAME = 'restocking_alert';
|
||||
|
||||
/**
|
||||
* The related Propel class for this table
|
||||
*/
|
||||
const OM_CLASS = '\\StockAlert\\Model\\RestockingAlert';
|
||||
|
||||
/**
|
||||
* A class that can be returned by this tableMap
|
||||
*/
|
||||
const CLASS_DEFAULT = 'StockAlert.Model.RestockingAlert';
|
||||
|
||||
/**
|
||||
* The total number of columns
|
||||
*/
|
||||
const NUM_COLUMNS = 6;
|
||||
|
||||
/**
|
||||
* The number of lazy-loaded columns
|
||||
*/
|
||||
const NUM_LAZY_LOAD_COLUMNS = 0;
|
||||
|
||||
/**
|
||||
* The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS)
|
||||
*/
|
||||
const NUM_HYDRATE_COLUMNS = 6;
|
||||
|
||||
/**
|
||||
* the column name for the ID field
|
||||
*/
|
||||
const ID = 'restocking_alert.ID';
|
||||
|
||||
/**
|
||||
* the column name for the PRODUCT_SALE_ELEMENTS_ID field
|
||||
*/
|
||||
const PRODUCT_SALE_ELEMENTS_ID = 'restocking_alert.PRODUCT_SALE_ELEMENTS_ID';
|
||||
|
||||
/**
|
||||
* the column name for the EMAIL field
|
||||
*/
|
||||
const EMAIL = 'restocking_alert.EMAIL';
|
||||
|
||||
/**
|
||||
* the column name for the LOCALE field
|
||||
*/
|
||||
const LOCALE = 'restocking_alert.LOCALE';
|
||||
|
||||
/**
|
||||
* the column name for the CREATED_AT field
|
||||
*/
|
||||
const CREATED_AT = 'restocking_alert.CREATED_AT';
|
||||
|
||||
/**
|
||||
* the column name for the UPDATED_AT field
|
||||
*/
|
||||
const UPDATED_AT = 'restocking_alert.UPDATED_AT';
|
||||
|
||||
/**
|
||||
* The default string format for model objects of the related table
|
||||
*/
|
||||
const DEFAULT_STRING_FORMAT = 'YAML';
|
||||
|
||||
/**
|
||||
* holds an array of fieldnames
|
||||
*
|
||||
* first dimension keys are the type constants
|
||||
* e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id'
|
||||
*/
|
||||
protected static $fieldNames = array (
|
||||
self::TYPE_PHPNAME => array('Id', 'ProductSaleElementsId', 'Email', 'Locale', 'CreatedAt', 'UpdatedAt', ),
|
||||
self::TYPE_STUDLYPHPNAME => array('id', 'productSaleElementsId', 'email', 'locale', 'createdAt', 'updatedAt', ),
|
||||
self::TYPE_COLNAME => array(RestockingAlertTableMap::ID, RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID, RestockingAlertTableMap::EMAIL, RestockingAlertTableMap::LOCALE, RestockingAlertTableMap::CREATED_AT, RestockingAlertTableMap::UPDATED_AT, ),
|
||||
self::TYPE_RAW_COLNAME => array('ID', 'PRODUCT_SALE_ELEMENTS_ID', 'EMAIL', 'LOCALE', 'CREATED_AT', 'UPDATED_AT', ),
|
||||
self::TYPE_FIELDNAME => array('id', 'product_sale_elements_id', 'email', 'locale', 'created_at', 'updated_at', ),
|
||||
self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, )
|
||||
);
|
||||
|
||||
/**
|
||||
* holds an array of keys for quick access to the fieldnames array
|
||||
*
|
||||
* first dimension keys are the type constants
|
||||
* e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0
|
||||
*/
|
||||
protected static $fieldKeys = array (
|
||||
self::TYPE_PHPNAME => array('Id' => 0, 'ProductSaleElementsId' => 1, 'Email' => 2, 'Locale' => 3, 'CreatedAt' => 4, 'UpdatedAt' => 5, ),
|
||||
self::TYPE_STUDLYPHPNAME => array('id' => 0, 'productSaleElementsId' => 1, 'email' => 2, 'locale' => 3, 'createdAt' => 4, 'updatedAt' => 5, ),
|
||||
self::TYPE_COLNAME => array(RestockingAlertTableMap::ID => 0, RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID => 1, RestockingAlertTableMap::EMAIL => 2, RestockingAlertTableMap::LOCALE => 3, RestockingAlertTableMap::CREATED_AT => 4, RestockingAlertTableMap::UPDATED_AT => 5, ),
|
||||
self::TYPE_RAW_COLNAME => array('ID' => 0, 'PRODUCT_SALE_ELEMENTS_ID' => 1, 'EMAIL' => 2, 'LOCALE' => 3, 'CREATED_AT' => 4, 'UPDATED_AT' => 5, ),
|
||||
self::TYPE_FIELDNAME => array('id' => 0, 'product_sale_elements_id' => 1, 'email' => 2, 'locale' => 3, 'created_at' => 4, 'updated_at' => 5, ),
|
||||
self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, )
|
||||
);
|
||||
|
||||
/**
|
||||
* Initialize the table attributes and columns
|
||||
* Relations are not initialized by this method since they are lazy loaded
|
||||
*
|
||||
* @return void
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
// attributes
|
||||
$this->setName('restocking_alert');
|
||||
$this->setPhpName('RestockingAlert');
|
||||
$this->setClassName('\\StockAlert\\Model\\RestockingAlert');
|
||||
$this->setPackage('StockAlert.Model');
|
||||
$this->setUseIdGenerator(true);
|
||||
// columns
|
||||
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
|
||||
$this->addForeignKey('PRODUCT_SALE_ELEMENTS_ID', 'ProductSaleElementsId', 'INTEGER', 'product_sale_elements', 'ID', true, null, null);
|
||||
$this->addColumn('EMAIL', 'Email', 'VARCHAR', false, 255, null);
|
||||
$this->addColumn('LOCALE', 'Locale', 'VARCHAR', false, 45, null);
|
||||
$this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null);
|
||||
} // initialize()
|
||||
|
||||
/**
|
||||
* Build the RelationMap objects for this table relationships
|
||||
*/
|
||||
public function buildRelations()
|
||||
{
|
||||
$this->addRelation('ProductSaleElements', '\\Thelia\\Model\\ProductSaleElements', RelationMap::MANY_TO_ONE, array('product_sale_elements_id' => 'id', ), 'CASCADE', null);
|
||||
} // buildRelations()
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets the list of behaviors registered for this table
|
||||
*
|
||||
* @return array Associative array (name => parameters) of behaviors
|
||||
*/
|
||||
public function getBehaviors()
|
||||
{
|
||||
return array(
|
||||
'timestampable' => array('create_column' => 'created_at', 'update_column' => 'updated_at', ),
|
||||
);
|
||||
} // getBehaviors()
|
||||
|
||||
/**
|
||||
* Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table.
|
||||
*
|
||||
* For tables with a single-column primary key, that simple pkey value will be returned. For tables with
|
||||
* a multi-column primary key, a serialize()d version of the primary key will be returned.
|
||||
*
|
||||
* @param array $row resultset row.
|
||||
* @param int $offset The 0-based offset for reading from the resultset row.
|
||||
* @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME
|
||||
* TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM
|
||||
*/
|
||||
public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM)
|
||||
{
|
||||
// If the PK cannot be derived from the row, return NULL.
|
||||
if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the primary key from the DB resultset row
|
||||
* For tables with a single-column primary key, that simple pkey value will be returned. For tables with
|
||||
* a multi-column primary key, an array of the primary key columns will be returned.
|
||||
*
|
||||
* @param array $row resultset row.
|
||||
* @param int $offset The 0-based offset for reading from the resultset row.
|
||||
* @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME
|
||||
* TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM
|
||||
*
|
||||
* @return mixed The primary key of the row
|
||||
*/
|
||||
public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM)
|
||||
{
|
||||
|
||||
return (int) $row[
|
||||
$indexType == TableMap::TYPE_NUM
|
||||
? 0 + $offset
|
||||
: self::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The class that the tableMap will make instances of.
|
||||
*
|
||||
* If $withPrefix is true, the returned path
|
||||
* uses a dot-path notation which is translated into a path
|
||||
* relative to a location on the PHP include_path.
|
||||
* (e.g. path.to.MyClass -> 'path/to/MyClass.php')
|
||||
*
|
||||
* @param boolean $withPrefix Whether or not to return the path with the class name
|
||||
* @return string path.to.ClassName
|
||||
*/
|
||||
public static function getOMClass($withPrefix = true)
|
||||
{
|
||||
return $withPrefix ? RestockingAlertTableMap::CLASS_DEFAULT : RestockingAlertTableMap::OM_CLASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates an object of the default type or an object that inherit from the default.
|
||||
*
|
||||
* @param array $row row returned by DataFetcher->fetch().
|
||||
* @param int $offset The 0-based offset for reading from the resultset row.
|
||||
* @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType().
|
||||
One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME
|
||||
* TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM.
|
||||
*
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
* @return array (RestockingAlert object, last column rank)
|
||||
*/
|
||||
public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM)
|
||||
{
|
||||
$key = RestockingAlertTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType);
|
||||
if (null !== ($obj = RestockingAlertTableMap::getInstanceFromPool($key))) {
|
||||
// We no longer rehydrate the object, since this can cause data loss.
|
||||
// See http://www.propelorm.org/ticket/509
|
||||
// $obj->hydrate($row, $offset, true); // rehydrate
|
||||
$col = $offset + RestockingAlertTableMap::NUM_HYDRATE_COLUMNS;
|
||||
} else {
|
||||
$cls = RestockingAlertTableMap::OM_CLASS;
|
||||
$obj = new $cls();
|
||||
$col = $obj->hydrate($row, $offset, false, $indexType);
|
||||
RestockingAlertTableMap::addInstanceToPool($obj, $key);
|
||||
}
|
||||
|
||||
return array($obj, $col);
|
||||
}
|
||||
|
||||
/**
|
||||
* The returned array will contain objects of the default type or
|
||||
* objects that inherit from the default.
|
||||
*
|
||||
* @param DataFetcherInterface $dataFetcher
|
||||
* @return array
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public static function populateObjects(DataFetcherInterface $dataFetcher)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
// set the class once to avoid overhead in the loop
|
||||
$cls = static::getOMClass(false);
|
||||
// populate the object(s)
|
||||
while ($row = $dataFetcher->fetch()) {
|
||||
$key = RestockingAlertTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType());
|
||||
if (null !== ($obj = RestockingAlertTableMap::getInstanceFromPool($key))) {
|
||||
// We no longer rehydrate the object, since this can cause data loss.
|
||||
// See http://www.propelorm.org/ticket/509
|
||||
// $obj->hydrate($row, 0, true); // rehydrate
|
||||
$results[] = $obj;
|
||||
} else {
|
||||
$obj = new $cls();
|
||||
$obj->hydrate($row);
|
||||
$results[] = $obj;
|
||||
RestockingAlertTableMap::addInstanceToPool($obj, $key);
|
||||
} // if key exists
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
/**
|
||||
* Add all the columns needed to create a new object.
|
||||
*
|
||||
* Note: any columns that were marked with lazyLoad="true" in the
|
||||
* XML schema will not be added to the select list and only loaded
|
||||
* on demand.
|
||||
*
|
||||
* @param Criteria $criteria object containing the columns to add.
|
||||
* @param string $alias optional table alias
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public static function addSelectColumns(Criteria $criteria, $alias = null)
|
||||
{
|
||||
if (null === $alias) {
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::ID);
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::PRODUCT_SALE_ELEMENTS_ID);
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::EMAIL);
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::LOCALE);
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::CREATED_AT);
|
||||
$criteria->addSelectColumn(RestockingAlertTableMap::UPDATED_AT);
|
||||
} else {
|
||||
$criteria->addSelectColumn($alias . '.ID');
|
||||
$criteria->addSelectColumn($alias . '.PRODUCT_SALE_ELEMENTS_ID');
|
||||
$criteria->addSelectColumn($alias . '.EMAIL');
|
||||
$criteria->addSelectColumn($alias . '.LOCALE');
|
||||
$criteria->addSelectColumn($alias . '.CREATED_AT');
|
||||
$criteria->addSelectColumn($alias . '.UPDATED_AT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TableMap related to this object.
|
||||
* This method is not needed for general use but a specific application could have a need.
|
||||
* @return TableMap
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public static function getTableMap()
|
||||
{
|
||||
return Propel::getServiceContainer()->getDatabaseMap(RestockingAlertTableMap::DATABASE_NAME)->getTable(RestockingAlertTableMap::TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a TableMap instance to the database for this tableMap class.
|
||||
*/
|
||||
public static function buildTableMap()
|
||||
{
|
||||
$dbMap = Propel::getServiceContainer()->getDatabaseMap(RestockingAlertTableMap::DATABASE_NAME);
|
||||
if (!$dbMap->hasTable(RestockingAlertTableMap::TABLE_NAME)) {
|
||||
$dbMap->addTableObject(new RestockingAlertTableMap());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a DELETE on the database, given a RestockingAlert or Criteria object OR a primary key value.
|
||||
*
|
||||
* @param mixed $values Criteria or RestockingAlert object or primary key or array of primary keys
|
||||
* which is used to create the DELETE statement
|
||||
* @param ConnectionInterface $con the connection to use
|
||||
* @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows
|
||||
* if supported by native driver or if emulated using Propel.
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public static function doDelete($values, ConnectionInterface $con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = Propel::getServiceContainer()->getWriteConnection(RestockingAlertTableMap::DATABASE_NAME);
|
||||
}
|
||||
|
||||
if ($values instanceof Criteria) {
|
||||
// rename for clarity
|
||||
$criteria = $values;
|
||||
} elseif ($values instanceof \StockAlert\Model\RestockingAlert) { // it's a model object
|
||||
// create criteria based on pk values
|
||||
$criteria = $values->buildPkeyCriteria();
|
||||
} else { // it's a primary key, or an array of pks
|
||||
$criteria = new Criteria(RestockingAlertTableMap::DATABASE_NAME);
|
||||
$criteria->add(RestockingAlertTableMap::ID, (array) $values, Criteria::IN);
|
||||
}
|
||||
|
||||
$query = RestockingAlertQuery::create()->mergeWith($criteria);
|
||||
|
||||
if ($values instanceof Criteria) { RestockingAlertTableMap::clearInstancePool();
|
||||
} elseif (!is_object($values)) { // it's a primary key, or an array of pks
|
||||
foreach ((array) $values as $singleval) { RestockingAlertTableMap::removeInstanceFromPool($singleval);
|
||||
}
|
||||
}
|
||||
|
||||
return $query->delete($con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all rows from the restocking_alert table.
|
||||
*
|
||||
* @param ConnectionInterface $con the connection to use
|
||||
* @return int The number of affected rows (if supported by underlying database driver).
|
||||
*/
|
||||
public static function doDeleteAll(ConnectionInterface $con = null)
|
||||
{
|
||||
return RestockingAlertQuery::create()->doDeleteAll($con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an INSERT on the database, given a RestockingAlert or Criteria object.
|
||||
*
|
||||
* @param mixed $criteria Criteria or RestockingAlert object containing data that is used to create the INSERT statement.
|
||||
* @param ConnectionInterface $con the ConnectionInterface connection to use
|
||||
* @return mixed The new primary key.
|
||||
* @throws PropelException Any exceptions caught during processing will be
|
||||
* rethrown wrapped into a PropelException.
|
||||
*/
|
||||
public static function doInsert($criteria, ConnectionInterface $con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = Propel::getServiceContainer()->getWriteConnection(RestockingAlertTableMap::DATABASE_NAME);
|
||||
}
|
||||
|
||||
if ($criteria instanceof Criteria) {
|
||||
$criteria = clone $criteria; // rename for clarity
|
||||
} else {
|
||||
$criteria = $criteria->buildCriteria(); // build Criteria from RestockingAlert object
|
||||
}
|
||||
|
||||
if ($criteria->containsKey(RestockingAlertTableMap::ID) && $criteria->keyContainsValue(RestockingAlertTableMap::ID) ) {
|
||||
throw new PropelException('Cannot insert a value for auto-increment primary key ('.RestockingAlertTableMap::ID.')');
|
||||
}
|
||||
|
||||
|
||||
// Set the correct dbName
|
||||
$query = RestockingAlertQuery::create()->mergeWith($criteria);
|
||||
|
||||
try {
|
||||
// use transaction because $criteria could contain info
|
||||
// for more than one table (I guess, conceivably)
|
||||
$con->beginTransaction();
|
||||
$pk = $query->doInsert($con);
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $pk;
|
||||
}
|
||||
|
||||
} // RestockingAlertTableMap
|
||||
// This is the static code needed to register the TableMap for this table with the main Propel class.
|
||||
//
|
||||
RestockingAlertTableMap::buildTableMap();
|
||||
10
local/modules/StockAlert/Model/RestockingAlert.php
Normal file
10
local/modules/StockAlert/Model/RestockingAlert.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace StockAlert\Model;
|
||||
|
||||
use StockAlert\Model\Base\RestockingAlert as BaseRestockingAlert;
|
||||
|
||||
class RestockingAlert extends BaseRestockingAlert
|
||||
{
|
||||
|
||||
}
|
||||
21
local/modules/StockAlert/Model/RestockingAlertQuery.php
Normal file
21
local/modules/StockAlert/Model/RestockingAlertQuery.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace StockAlert\Model;
|
||||
|
||||
use StockAlert\Model\Base\RestockingAlertQuery as BaseRestockingAlertQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'restocking_alert' table.
|
||||
*
|
||||
*
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
class RestockingAlertQuery extends BaseRestockingAlertQuery
|
||||
{
|
||||
|
||||
} // RestockingAlertQuery
|
||||
57
local/modules/StockAlert/README.md
Normal file
57
local/modules/StockAlert/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
Stock Alert
|
||||
|
||||
This module has two different features :
|
||||
|
||||
- send email notifications when the quantity in stock is under a certain limit.
|
||||
- allow customers to subscribe to an unavailable product to be notified when it will be available again.
|
||||
|
||||
## Installation
|
||||
|
||||
### Manually
|
||||
|
||||
This module requires Thelia in version 2.1
|
||||
|
||||
It must be placed into your modules/ directory (local/modules/).
|
||||
|
||||
You can download the .zip file of this module or create a git submodule into your project like this :
|
||||
|
||||
cd /path-to-thelia
|
||||
git submodule add https://github.com/thelia-modules/StockAlert.git local/modules/StockAlert
|
||||
|
||||
Next, go to your Thelia admin panel for module activation.
|
||||
|
||||
### Composer
|
||||
|
||||
Add it in your main thelia composer.json file
|
||||
|
||||
```
|
||||
composer require thelia/stock-alert-module:~1.0
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
You can activate or not the admin notifications on the configuration page of the module. You can also define
|
||||
a threshold for product quantity and a list of emails.
|
||||
|
||||
For the customer, the display is managed by hooks. So if you deactivate the hook `product.details-bottom` and
|
||||
`product.javascript-initialization` this feature will be deactivated for customers.
|
||||
You can also customize the display in redefining the html templates in your frontOffice template. You have to copy
|
||||
the files inside `templates/frontOffice/default/` in your template, in directory `modules/StockAlert/`. Files should
|
||||
have the same names.
|
||||
|
||||
You can also customize emails sent by the module. You have to copy files from `templates/email/default/`
|
||||
in your email template directory, edit them, and select this template in the **Mailing templates** configuration page.
|
||||
|
||||
## Hooks
|
||||
|
||||
This module adds a new hook:
|
||||
|
||||
```
|
||||
product.stock-alert
|
||||
```
|
||||
|
||||
You can place it anywhere in your template and use it instead of the ```product.details-bottom``` hook if you don't want to use it.
|
||||
|
||||
It calls the same function as the ```product.details-bottom``` hook and renders the ```product-details-bottom.html`` template`
|
||||
|
||||
**Important:** don't forget to disable the hook you don't want to use (```product.details-bottom``` for example).
|
||||
150
local/modules/StockAlert/StockAlert.php
Normal file
150
local/modules/StockAlert/StockAlert.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace StockAlert;
|
||||
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use StockAlert\Model\RestockingAlertQuery;
|
||||
use Thelia\Core\Template\TemplateDefinition;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Install\Database;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\LangQuery;
|
||||
use Thelia\Model\Message;
|
||||
use Thelia\Model\MessageQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
/**
|
||||
* Class StockAlert
|
||||
* @package StockAlert
|
||||
* @author Baixas Alban <abaixas@openstudio.fr>
|
||||
*/
|
||||
class StockAlert extends BaseModule
|
||||
{
|
||||
const MESSAGE_DOMAIN = "stockalert";
|
||||
|
||||
const CONFIG_ENABLED = "stockalert_enabled";
|
||||
const CONFIG_THRESHOLD = "stockalert_threshold";
|
||||
const CONFIG_EMAILS = "stockalert_emails";
|
||||
|
||||
const DEFAULT_ENABLED = "1";
|
||||
const DEFAULT_THRESHOLD = "1";
|
||||
const DEFAULT_EMAILS = "";
|
||||
|
||||
/** @var Translator */
|
||||
protected $translator = null;
|
||||
|
||||
public static function getConfig()
|
||||
{
|
||||
$config = [
|
||||
'enabled' => ("1" == ConfigQuery::read(self::CONFIG_ENABLED, self::DEFAULT_ENABLED)),
|
||||
'threshold' => intval(ConfigQuery::read(self::CONFIG_THRESHOLD, self::DEFAULT_THRESHOLD)),
|
||||
'emails' => explode(',', ConfigQuery::read(self::CONFIG_EMAILS, self::DEFAULT_EMAILS))
|
||||
];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConnectionInterface|null $con
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function postActivation(ConnectionInterface $con = null)
|
||||
{
|
||||
ConfigQuery::write(self::CONFIG_ENABLED, self::DEFAULT_ENABLED);
|
||||
ConfigQuery::write(self::CONFIG_THRESHOLD, self::DEFAULT_THRESHOLD);
|
||||
ConfigQuery::write(self::CONFIG_EMAILS, ConfigQuery::read('store_notification_emails'));
|
||||
|
||||
// create new message
|
||||
if (null === MessageQuery::create()->findOneByName('stockalert_customer')) {
|
||||
(new Message())
|
||||
->setName('stockalert_customer')
|
||||
->setHtmlTemplateFileName('alert-customer.html')
|
||||
->setTextTemplateFileName('alert-customer.txt')
|
||||
->setSecured(0)
|
||||
->setLocale('en_US')
|
||||
->setTitle('Stock Alert - Customer')
|
||||
->setSubject('Product {$product_title} is available again')
|
||||
->setLocale('fr_FR')
|
||||
->setTitle('Alerte Stock - Client')
|
||||
->setSubject('Le produit {$product_title} est à nouveau disponible')
|
||||
->save();
|
||||
|
||||
(new Message())
|
||||
->setName('stockalert_administrator')
|
||||
->setHtmlTemplateFileName('alert-administrator.html')
|
||||
->setTextTemplateFileName('alert-administrator.txt')
|
||||
->setSecured(0)
|
||||
->setLocale('en_US')
|
||||
->setTitle('Stock Alert - Administrator')
|
||||
->setSubject('List of products nearly out of stock')
|
||||
->setLocale('fr_FR')
|
||||
->setTitle('Alerte Stock - Administrateur')
|
||||
->setSubject('Liste des produits qui seront bientôt en rupture de stock')
|
||||
->save();
|
||||
}
|
||||
|
||||
try {
|
||||
RestockingAlertQuery::create()->findOne();
|
||||
} catch (\Exception $e) {
|
||||
$database = new Database($con);
|
||||
$database->insertSql(null, [__DIR__ . '/Config/thelia.sql']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConnectionInterface|null $con
|
||||
* @param bool $deleteModuleData
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
public function destroy(ConnectionInterface $con = null, $deleteModuleData = false)
|
||||
{
|
||||
if (null !== $msg = MessageQuery::create()->findOneByName('stockalert_customer')) {
|
||||
$msg->delete();
|
||||
}
|
||||
if (null !== $msg = MessageQuery::create()->findOneByName('stockalert_administrator')) {
|
||||
$msg->delete();
|
||||
}
|
||||
|
||||
ConfigQuery::create()
|
||||
->filterByName([ self::CONFIG_ENABLED, self::CONFIG_THRESHOLD, self::CONFIG_EMAILS ])
|
||||
->delete()
|
||||
;
|
||||
|
||||
$database = new Database($con);
|
||||
$database->insertSql(null, [__DIR__ . '/Config/destroy.sql']);
|
||||
}
|
||||
|
||||
protected function trans($id, array $parameters = [], $locale = null)
|
||||
{
|
||||
if (null === $this->translator) {
|
||||
$this->translator = Translator::getInstance();
|
||||
}
|
||||
|
||||
return $this->translator->trans($id, $parameters, StockAlert::MESSAGE_DOMAIN, $locale);
|
||||
}
|
||||
|
||||
public function getHooks()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'code' => 'product.stock-alert',
|
||||
'type' => TemplateDefinition::FRONT_OFFICE,
|
||||
"title" => array(
|
||||
"fr_FR" => "Hook alertes stock",
|
||||
"en_US" => "Stock alert hook",
|
||||
),
|
||||
"active" => true
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
11
local/modules/StockAlert/composer.json
Normal file
11
local/modules/StockAlert/composer.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "thelia/stock-alert-module",
|
||||
"license": "LGPL-3.0+",
|
||||
"type": "thelia-module",
|
||||
"require": {
|
||||
"thelia/installer": "~1.1"
|
||||
},
|
||||
"extra": {
|
||||
"installer-name": "StockAlert"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<!-- Configuration -->
|
||||
<div class="general-block-decorator">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12 title title-without-tabs">
|
||||
{intl d='stockalert.bo.default' l='Configuration.'}
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<div class="col-md-12">
|
||||
|
||||
{form name="stockalert.configuration.form"}
|
||||
<form method="POST" id="stockalert-form" action="{url path="/admin/module/stockalert/configuration"}"
|
||||
{form_enctype form=$form} class="clearfix">
|
||||
|
||||
{form_hidden_fields form=$form}
|
||||
|
||||
{render_form_field form=$form field="success_url" value={url path='/admin/module/StockAlert'}}
|
||||
|
||||
{if {config key="check-available-stock"} != "1"}
|
||||
<p class="alert alert-info">
|
||||
{intl d='stockalert.bo.default' l='The stock is not not use on the site. Please set the config variable check-available-stock to 1.'}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{if $form_error}
|
||||
<div class="alert alert-danger">{$form_error_message}</div>
|
||||
{/if}
|
||||
|
||||
{render_form_field form=$form field="enabled"}
|
||||
|
||||
{render_form_field form=$form field="threshold"}
|
||||
|
||||
{render_form_field form=$form field="emails"}
|
||||
|
||||
<button type="submit" id="stockalert-save" name="stockalert_save" value="save" class="form-submit-button btn btn-primary" title="{intl d='stockalert.bo.default' l='Save'}">{intl d='stockalert.bo.default' l='Save'}</button>
|
||||
</form>
|
||||
{/form}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="general-block-decorator">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12 title title-without-tabs">
|
||||
{intl d='stockalert.bo.default' l='List of current subscriptions.'}
|
||||
</div>
|
||||
{$limit={$smarty.get.limit|default:100}}
|
||||
{$page={$smarty.get.page|default:1}}
|
||||
|
||||
{if {count type="restocking-alert"} < $limit * $page}
|
||||
{$page=1}
|
||||
{/if}
|
||||
|
||||
<div class="col-md-12">
|
||||
{ifloop rel="restocking-alert"}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="alert_list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{intl d='stockalert.bo.default' l='Date'}</th>
|
||||
<th>{intl d='stockalert.bo.default' l='Email'}</th>
|
||||
<th>{intl d='stockalert.bo.default' l='Product'}</th>
|
||||
{*<th class="actions">{intl l='Actions'}</th>*}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{loop type="restocking-alert" name="restocking-alert" limit=$limit page=$page}
|
||||
<tr>
|
||||
<td>{format_date date=$CREATE_DATE output="date"}</td>
|
||||
<td>{$EMAIL}</td>
|
||||
<td>
|
||||
{loop type="product_sale_elements" name="pse" id=$PRODUCT_SALE_ELEMENTS_ID limit="1"}
|
||||
{loop type="product" name="product" id=$PRODUCT_ID limit="1"}
|
||||
<a href="{url path='/admin/products/update' product_id=$ID}">{$ID}. {$TITLE}</a>
|
||||
{/loop}
|
||||
{/loop}
|
||||
</td>
|
||||
</tr>
|
||||
{/loop}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="100">
|
||||
{include
|
||||
file = "includes/pagination.html"
|
||||
|
||||
loop_ref = "restocking-alert"
|
||||
max_page_count = 10
|
||||
page_url = {url path='/admin/module/StockAlert'}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{/ifloop}
|
||||
{elseloop rel="restocking-alert"}
|
||||
<div class="alert alert-warning">
|
||||
<p>
|
||||
{intl d='stockalert.bo.default' l='There is no subscriptions.'}
|
||||
</p>
|
||||
</div>
|
||||
{/elseloop}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
{default_translation_domain domain="stockalert.email.default"}
|
||||
|
||||
<p>{intl l="Hi" },</p>
|
||||
|
||||
<p>{intl l="Some product(s) is (are) going to be out of stock :"}</p>
|
||||
{$products={','|implode:$products_id}}
|
||||
{loop type="product" name="product" id=$products visible="*" backend_context="yes" lang=$locale}
|
||||
<p>{$ID}: {$REF} - {$TITLE} :</p>
|
||||
<ul>
|
||||
<li>url : <a href="{$URL}">{$URL}</a></li>
|
||||
<li>admin url : <a href="{url path='/admin/products/update' product_id=$ID}">{url path='/admin/products/update' product_id=$ID}</a></li>
|
||||
</ul>
|
||||
{/loop}
|
||||
|
||||
<p>{intl l="Best Regards."}</p>
|
||||
@@ -0,0 +1,15 @@
|
||||
{default_translation_domain domain="stockalert.email.default"}
|
||||
|
||||
{intl l="Hi" },
|
||||
|
||||
{intl l="Some product(s) is (are) going to be out of stock :"}
|
||||
{$products={','|implode:$products_id}}
|
||||
{loop type="product" name="product" id=$products visible="*" backend_context="yes" lang=$locale}
|
||||
{$ID}. {$TITLE} :
|
||||
|
||||
url : {$URL}
|
||||
admin url : {url path='/admin/products/update' product_id=$ID}
|
||||
|
||||
{/loop}
|
||||
|
||||
{intl l="Best Regards."}
|
||||
@@ -0,0 +1,21 @@
|
||||
{default_translation_domain domain="stockalert.email.default"}
|
||||
|
||||
<p>{intl l="Hi" },</p>
|
||||
|
||||
{loop type="product" name="product" id=$product_id limit="1" lang=$locale}
|
||||
{$pse=[]}
|
||||
{loop name="pse" type="product_sale_elements" id=$pse_id|default:0}
|
||||
{loop name="combi" type="attribute_combination" product_sale_elements="$ID"}
|
||||
{$pse[]=$ATTRIBUTE_AVAILABILITY_TITLE}{*$ATTRIBUTE_TITLE*}
|
||||
{/loop}
|
||||
{/loop}
|
||||
|
||||
{$pse={', '|implode:$pse}}
|
||||
<p>{intl l="The product %title (%pse) is now available." title=$TITLE pse=$pse}</p>
|
||||
|
||||
<p>{intl l='You can now <a href="%url">order this product here</a>.' url=$URL}</p>
|
||||
{/loop}
|
||||
|
||||
<p>{intl l="Feel free to contact us for any further information"}</p>
|
||||
|
||||
<p>{intl l="Best Regards."}</p>
|
||||
@@ -0,0 +1,21 @@
|
||||
{default_translation_domain domain="stockalert.email.default"}
|
||||
|
||||
{intl l="Hi" },
|
||||
|
||||
{loop type="product" name="product" id=$product_id limit="1" lang=$locale}
|
||||
|
||||
{$pse=[]}
|
||||
{loop name="pse" type="product_sale_elements" id=$pse_id}
|
||||
{loop name="combi" type="attribute_combination" product_sale_elements="$ID"}
|
||||
{$pse[]=$ATTRIBUTE_AVAILABILITY_TITLE}{*$ATTRIBUTE_TITLE*}
|
||||
{/loop}
|
||||
{/loop}
|
||||
{$pse={', '|implode:$pse}}
|
||||
{intl l="The product %title (%pse) is available again." title=$TITLE pse=$pse}
|
||||
|
||||
{intl l="You can now order this product : %url" url=$URL}
|
||||
{/loop}
|
||||
|
||||
{intl l="Feel free to contact us for any further information"}
|
||||
|
||||
{intl l="Best Regards."}
|
||||
@@ -0,0 +1,29 @@
|
||||
<div id="product-stock-alert" class="product-stock-alert hidden panel panel-default">
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
{intl l="This product is not available for now." d="stockalert.fo.default"}<br>
|
||||
{intl l="Register your email to be notified when it will be available again." d="stockalert.fo.default"}
|
||||
</p>
|
||||
{form name="stockalert.subscribe.form"}
|
||||
<form method="post" action="{url path='/module/stockalert/subscribe'}" {form_enctype form=$form} class="inline">
|
||||
|
||||
{form_hidden_fields form=$form}
|
||||
|
||||
{form_field form=$form field="product_sale_elements_id"}
|
||||
<input id="stock-alert-id" type="hidden" name="{$name}" value="">
|
||||
{/form_field}
|
||||
|
||||
<div id="product-stock-notify" class="alert hidden"></div>
|
||||
|
||||
<div class="form-group">
|
||||
{form_field form=$form field="email"}
|
||||
<label>{$label}</label>
|
||||
<input id="stock-alert-email" type="{$type}" name="{$name}" value="{$value}" class="form-control">
|
||||
{/form_field}
|
||||
</div>
|
||||
|
||||
<input type="submit" class="btn btn-default" name="stock-alert-submit" value="{intl l="Notify me !" d="stockalert.fo.default"}" />
|
||||
</form>
|
||||
{/form}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
<script type="text/javascript">
|
||||
(function ($, undefined) {
|
||||
$(document).ready(function () {
|
||||
|
||||
var $section = $('#product-stock-alert'),
|
||||
$pseId = $('#pse-id'),
|
||||
$alertPseId = $('#stock-alert-id'),
|
||||
$pseSelector = $('select.pse-option'),
|
||||
$cartSubmit = $('#pse-submit'),
|
||||
$notify = $('#product-stock-notify')
|
||||
;
|
||||
|
||||
/* Check if add to cart is disabled or not */
|
||||
var checkStock = function checkStock() {
|
||||
if ($cartSubmit.prop("disabled")) {
|
||||
$section.removeClass('hidden');
|
||||
} else {
|
||||
$section.addClass('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
var saveStockAlert = function saveStockAlert($form) {
|
||||
|
||||
$alertPseId.val($pseId.val());
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
type: $form.attr('method'),
|
||||
data: $form.serializeArray(),
|
||||
dataType: 'json'
|
||||
}).done(function(data, textStatus, jqXHR){
|
||||
$notify.removeClass('hidden alert-success alert-warning');
|
||||
if (data.success) {
|
||||
$notify
|
||||
.addClass('alert-success')
|
||||
.html(data.message)
|
||||
;
|
||||
$('#stock-alert-email').val("");
|
||||
} else {
|
||||
$notify
|
||||
.addClass('alert-warning')
|
||||
.html(data.message)
|
||||
;
|
||||
}
|
||||
}).fail(function(jqXHR, textStatus, errorThrown){
|
||||
bootbox.alert(textStatus);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$pseSelector.on('change', function(ev) {
|
||||
checkStock();
|
||||
});
|
||||
|
||||
$section.on('submit', 'form', function(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
saveStockAlert($(this));
|
||||
});
|
||||
|
||||
setTimeout(checkStock, 1000);
|
||||
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user