Merge branch 'master' into template
This commit is contained in:
199
core/lib/Thelia/Action/Product.php
Normal file
199
core/lib/Thelia/Action/Product.php
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Action;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Model\Product as ProductModel;
|
||||
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
use Thelia\Core\Event\ProductUpdateEvent;
|
||||
use Thelia\Core\Event\ProductCreateEvent;
|
||||
use Thelia\Core\Event\ProductDeleteEvent;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\ProductToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\ProductAddContentEvent;
|
||||
use Thelia\Core\Event\ProductDeleteContentEvent;
|
||||
use Thelia\Model\ProductAssociatedContent;
|
||||
use Thelia\Model\ProductAssociatedContentQuery;
|
||||
|
||||
class Product extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Create a new product entry
|
||||
*
|
||||
* @param ProductCreateEvent $event
|
||||
*/
|
||||
public function create(ProductCreateEvent $event)
|
||||
{
|
||||
$product = new ProductModel();
|
||||
|
||||
$product
|
||||
->setDispatcher($this->getDispatcher())
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
|
||||
->save()
|
||||
;
|
||||
|
||||
$event->setProduct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product
|
||||
*
|
||||
* @param ProductUpdateEvent $event
|
||||
*/
|
||||
public function update(ProductUpdateEvent $event)
|
||||
{
|
||||
$search = ProductQuery::create();
|
||||
|
||||
if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) {
|
||||
|
||||
$product
|
||||
->setDispatcher($this->getDispatcher())
|
||||
|
||||
->setLocale($event->getLocale())
|
||||
->setTitle($event->getTitle())
|
||||
->setDescription($event->getDescription())
|
||||
->setChapo($event->getChapo())
|
||||
->setPostscriptum($event->getPostscriptum())
|
||||
|
||||
->setParent($event->getParent())
|
||||
->setVisible($event->getVisible())
|
||||
|
||||
->save();
|
||||
|
||||
$event->setProduct($product);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product entry
|
||||
*
|
||||
* @param ProductDeleteEvent $event
|
||||
*/
|
||||
public function delete(ProductDeleteEvent $event)
|
||||
{
|
||||
if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) {
|
||||
|
||||
$product
|
||||
->setDispatcher($this->getDispatcher())
|
||||
->delete()
|
||||
;
|
||||
|
||||
$event->setProduct($product);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle product visibility. No form used here
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
*/
|
||||
public function toggleVisibility(ProductToggleVisibilityEvent $event)
|
||||
{
|
||||
$product = $event->getProduct();
|
||||
|
||||
$product
|
||||
->setDispatcher($this->getDispatcher())
|
||||
->setVisible($product->getVisible() ? false : true)
|
||||
->save()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes position, selecting absolute ou relative change.
|
||||
*
|
||||
* @param ProductChangePositionEvent $event
|
||||
*/
|
||||
public function updatePosition(UpdatePositionEvent $event)
|
||||
{
|
||||
if (null !== $product = ProductQuery::create()->findPk($event->getObjectId())) {
|
||||
|
||||
$product->setDispatcher($this->getDispatcher());
|
||||
|
||||
$mode = $event->getMode();
|
||||
|
||||
if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE)
|
||||
return $product->changeAbsolutePosition($event->getPosition());
|
||||
else if ($mode == UpdatePositionEvent::POSITION_UP)
|
||||
return $product->movePositionUp();
|
||||
else if ($mode == UpdatePositionEvent::POSITION_DOWN)
|
||||
return $product->movePositionDown();
|
||||
}
|
||||
}
|
||||
|
||||
public function addContent(ProductAddContentEvent $event) {
|
||||
|
||||
if (ProductAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByProduct($event->getProduct())->count() <= 0) {
|
||||
|
||||
$content = new ProductAssociatedContent();
|
||||
|
||||
$content
|
||||
->setProduct($event->getProduct())
|
||||
->setContentId($event->getContentId())
|
||||
->save()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeContent(ProductDeleteContentEvent $event) {
|
||||
|
||||
$content = ProductAssociatedContentQuery::create()
|
||||
->filterByContentId($event->getContentId())
|
||||
->filterByProduct($event->getProduct())->findOne()
|
||||
;
|
||||
|
||||
if ($content !== null) $content->delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
TheliaEvents::PRODUCT_CREATE => array("create", 128),
|
||||
TheliaEvents::PRODUCT_UPDATE => array("update", 128),
|
||||
TheliaEvents::PRODUCT_DELETE => array("delete", 128),
|
||||
TheliaEvents::PRODUCT_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_UPDATE_POSITION => array("updatePosition", 128),
|
||||
|
||||
TheliaEvents::PRODUCT_ADD_CONTENT => array("addContent", 128),
|
||||
TheliaEvents::PRODUCT_REMOVE_CONTENT => array("removeContent", 128),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,11 @@
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.action.product" class="Thelia\Action\Product">
|
||||
<argument type="service" id="service_container"/>
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.action.config" class="Thelia\Action\Config">
|
||||
<argument type="service" id="service_container"/>
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
|
||||
@@ -114,6 +114,50 @@
|
||||
<requirement key="_format">xml|json</requirement>
|
||||
</route>
|
||||
|
||||
<!-- Product Management -->
|
||||
|
||||
<route id="admin.products.default" path="/admin/products">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::defaultAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.create" path="/admin/products/create">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::createAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.update" path="/admin/products/update">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::updateAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.save" path="/admin/products/save">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::processUpdateAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.set-default" path="/admin/products/toggle-online">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::setToggleVisibilityAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.delete" path="/admin/products/delete">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::deleteAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.update-position" path="/admin/products/update-position">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::updatePositionAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.related-content.add" path="/admin/products/related-content/add">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::addRelatedContentAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.products.related-content.delete" path="/admin/products/related-content/delete">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::deleteRelatedContentAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.product.available-related-content" path="/admin/product/{productId}/available-related-content/{folderId}.{_format}" methods="GET">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::getAvailableRelatedContentAction</default>
|
||||
<requirement key="_format">xml|json</requirement>
|
||||
</route>
|
||||
|
||||
|
||||
<!-- Route to the Coupon controller (process Coupon browsing) -->
|
||||
|
||||
<route id="admin.coupon.list" path="/admin/coupon/">
|
||||
|
||||
@@ -169,9 +169,14 @@ class CategoryController extends AbstractCrudController
|
||||
}
|
||||
|
||||
protected function renderListTemplate($currentOrder) {
|
||||
|
||||
// Get product order
|
||||
$product_order = $this->getListOrderFromSession('product', 'product_order', 'manual');
|
||||
|
||||
return $this->render('categories',
|
||||
array(
|
||||
'category_order' => $currentOrder,
|
||||
'product_order' => $product_order,
|
||||
'category_id' => $this->getRequest()->get('category_id', 0)
|
||||
));
|
||||
}
|
||||
|
||||
350
core/lib/Thelia/Controller/Admin/ProductController.php
Normal file
350
core/lib/Thelia/Controller/Admin/ProductController.php
Normal file
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Controller\Admin;
|
||||
|
||||
use Thelia\Core\Event\ProductDeleteEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\ProductUpdateEvent;
|
||||
use Thelia\Core\Event\ProductCreateEvent;
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Form\ProductModificationForm;
|
||||
use Thelia\Form\ProductCreationForm;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Core\Event\ProductToggleVisibilityEvent;
|
||||
use Thelia\Core\Event\ProductDeleteContentEvent;
|
||||
use Thelia\Core\Event\ProductAddContentEvent;
|
||||
use Thelia\Model\ProductAssociatedContent;
|
||||
use Thelia\Model\FolderQuery;
|
||||
use Thelia\Model\ContentQuery;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Thelia\Model\ProductAssociatedContentQuery;
|
||||
|
||||
/**
|
||||
* Manages products
|
||||
*
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class ProductController extends AbstractCrudController
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
'product',
|
||||
'manual',
|
||||
'product_order',
|
||||
|
||||
'admin.products.default',
|
||||
'admin.products.create',
|
||||
'admin.products.update',
|
||||
'admin.products.delete',
|
||||
|
||||
TheliaEvents::PRODUCT_CREATE,
|
||||
TheliaEvents::PRODUCT_UPDATE,
|
||||
TheliaEvents::PRODUCT_DELETE,
|
||||
|
||||
TheliaEvents::PRODUCT_TOGGLE_VISIBILITY,
|
||||
TheliaEvents::PRODUCT_UPDATE_POSITION
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCreationForm()
|
||||
{
|
||||
return new ProductCreationForm($this->getRequest());
|
||||
}
|
||||
|
||||
protected function getUpdateForm()
|
||||
{
|
||||
return new ProductModificationForm($this->getRequest());
|
||||
}
|
||||
|
||||
protected function getCreationEvent($formData)
|
||||
{
|
||||
$createEvent = new ProductCreateEvent();
|
||||
|
||||
$createEvent
|
||||
->setTitle($formData['title'])
|
||||
->setLocale($formData["locale"])
|
||||
->setParent($formData['parent'])
|
||||
->setVisible($formData['visible'])
|
||||
;
|
||||
|
||||
return $createEvent;
|
||||
}
|
||||
|
||||
protected function getUpdateEvent($formData)
|
||||
{
|
||||
$changeEvent = new ProductUpdateEvent($formData['id']);
|
||||
|
||||
// Create and dispatch the change event
|
||||
$changeEvent
|
||||
->setLocale($formData['locale'])
|
||||
->setTitle($formData['title'])
|
||||
->setChapo($formData['chapo'])
|
||||
->setDescription($formData['description'])
|
||||
->setPostscriptum($formData['postscriptum'])
|
||||
->setVisible($formData['visible'])
|
||||
->setUrl($formData['url'])
|
||||
->setParent($formData['parent'])
|
||||
;
|
||||
|
||||
return $changeEvent;
|
||||
}
|
||||
|
||||
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
|
||||
{
|
||||
return new UpdatePositionEvent(
|
||||
$this->getRequest()->get('product_id', null),
|
||||
$positionChangeMode,
|
||||
$positionValue
|
||||
);
|
||||
}
|
||||
|
||||
protected function getDeleteEvent()
|
||||
{
|
||||
return new ProductDeleteEvent($this->getRequest()->get('product_id', 0));
|
||||
}
|
||||
|
||||
protected function eventContainsObject($event)
|
||||
{
|
||||
return $event->hasProduct();
|
||||
}
|
||||
|
||||
protected function hydrateObjectForm($object)
|
||||
{
|
||||
// Prepare the data that will hydrate the form
|
||||
$data = array(
|
||||
'id' => $object->getId(),
|
||||
'locale' => $object->getLocale(),
|
||||
'title' => $object->getTitle(),
|
||||
'chapo' => $object->getChapo(),
|
||||
'description' => $object->getDescription(),
|
||||
'postscriptum' => $object->getPostscriptum(),
|
||||
'visible' => $object->getVisible(),
|
||||
'url' => $object->getRewritenUrl($this->getCurrentEditionLocale()),
|
||||
'parent' => $object->getParent()
|
||||
);
|
||||
|
||||
// Setup the object form
|
||||
return new ProductModificationForm($this->getRequest(), "form", $data);
|
||||
}
|
||||
|
||||
protected function getObjectFromEvent($event)
|
||||
{
|
||||
return $event->hasProduct() ? $event->getProduct() : null;
|
||||
}
|
||||
|
||||
protected function getExistingObject()
|
||||
{
|
||||
return ProductQuery::create()
|
||||
->joinWithI18n($this->getCurrentEditionLocale())
|
||||
->findOneById($this->getRequest()->get('product_id', 0));
|
||||
}
|
||||
|
||||
protected function getObjectLabel($object)
|
||||
{
|
||||
return $object->getTitle();
|
||||
}
|
||||
|
||||
protected function getObjectId($object)
|
||||
{
|
||||
return $object->getId();
|
||||
}
|
||||
|
||||
protected function getEditionArguments()
|
||||
{
|
||||
return array(
|
||||
'product_id' => $this->getRequest()->get('product_id', 0),
|
||||
'folder_id' => $this->getRequest()->get('folder_id', 0),
|
||||
'current_tab' => $this->getRequest()->get('current_tab', 'general')
|
||||
);
|
||||
}
|
||||
|
||||
protected function renderListTemplate($currentOrder)
|
||||
{
|
||||
$this->getListOrderFromSession('product', 'product_order', 'manual');
|
||||
|
||||
return $this->render('categories',
|
||||
array(
|
||||
'product_order' => $currentOrder,
|
||||
'product_id' => $this->getRequest()->get('product_id', 0)
|
||||
));
|
||||
}
|
||||
|
||||
protected function redirectToListTemplate()
|
||||
{
|
||||
// Redirect to the product default category list
|
||||
$product = $this->getExistingObject();
|
||||
|
||||
$this->redirectToRoute(
|
||||
'admin.products.default',
|
||||
array('category_id' => $product != null ? $product->getDefaultCategory() : 0)
|
||||
);
|
||||
}
|
||||
|
||||
protected function renderEditionTemplate()
|
||||
{
|
||||
return $this->render('product-edit', $this->getEditionArguments());
|
||||
}
|
||||
|
||||
protected function redirectToEditionTemplate()
|
||||
{
|
||||
$this->redirectToRoute("admin.products.update", $this->getEditionArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* Online status toggle product
|
||||
*/
|
||||
public function setToggleVisibilityAction()
|
||||
{
|
||||
// Check current user authorization
|
||||
if (null !== $response = $this->checkAuth("admin.products.update")) return $response;
|
||||
|
||||
$event = new ProductToggleVisibilityEvent($this->getExistingObject());
|
||||
|
||||
try {
|
||||
$this->dispatch(TheliaEvents::PRODUCT_TOGGLE_VISIBILITY, $event);
|
||||
} catch (\Exception $ex) {
|
||||
// Any error
|
||||
return $this->errorPage($ex);
|
||||
}
|
||||
|
||||
// Ajax response -> no action
|
||||
return $this->nullResponse();
|
||||
}
|
||||
|
||||
protected function performAdditionalDeleteAction($deleteEvent)
|
||||
{
|
||||
// Redirect to parent product list
|
||||
$this->redirectToRoute(
|
||||
'admin.products.default',
|
||||
array('category_id' => $deleteEvent->getProduct()->getDefaultCategory())
|
||||
);
|
||||
}
|
||||
|
||||
protected function performAdditionalUpdateAction($updateEvent)
|
||||
{
|
||||
if ($this->getRequest()->get('save_mode') != 'stay') {
|
||||
|
||||
// Redirect to parent product list
|
||||
$this->redirectToRoute(
|
||||
'admin.categories.default',
|
||||
array('category_id' => $product->getDefaultCategory())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function performAdditionalUpdatePositionAction($event)
|
||||
{
|
||||
$product = ProductQuery::create()->findPk($event->getObjectId());
|
||||
|
||||
if ($product != null) {
|
||||
// Redirect to parent product list
|
||||
$this->redirectToRoute(
|
||||
'admin.categories.default',
|
||||
array('category_id' => $product->getDefaultCategory())
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getAvailableRelatedContentAction($productId, $folderId)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$folders = FolderQuery::create()->filterById($folderId)->find();
|
||||
|
||||
if ($folders !== null) {
|
||||
|
||||
$list = ContentQuery::create()
|
||||
->joinWithI18n($this->getCurrentEditionLocale())
|
||||
->filterByFolder($folders, Criteria::IN)
|
||||
->filterById(ProductAssociatedContentQuery::create()->select('content_id')->findByProductId($productId), Criteria::NOT_IN)
|
||||
->find();
|
||||
;
|
||||
|
||||
if ($list !== null) {
|
||||
foreach($list as $item) {
|
||||
$result[] = array('id' => $item->getId(), 'title' => $item->getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->jsonResponse(json_encode($result));
|
||||
}
|
||||
|
||||
public function addRelatedContentAction()
|
||||
{
|
||||
|
||||
// Check current user authorization
|
||||
if (null !== $response = $this->checkAuth("admin.products.update")) return $response;
|
||||
|
||||
$content_id = intval($this->getRequest()->get('content_id'));
|
||||
|
||||
if ($content_id > 0) {
|
||||
|
||||
$event = new ProductAddContentEvent(
|
||||
$this->getExistingObject(),
|
||||
$content_id
|
||||
);
|
||||
|
||||
try {
|
||||
$this->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $event);
|
||||
}
|
||||
catch (\Exception $ex) {
|
||||
// Any error
|
||||
return $this->errorPage($ex);
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirectToEditionTemplate();
|
||||
}
|
||||
|
||||
public function deleteRelatedContentAction()
|
||||
{
|
||||
|
||||
// Check current user authorization
|
||||
if (null !== $response = $this->checkAuth("admin.products.update")) return $response;
|
||||
|
||||
$content_id = intval($this->getRequest()->get('content_id'));
|
||||
|
||||
if ($content_id > 0) {
|
||||
|
||||
$event = new ProductDeleteContentEvent(
|
||||
$this->getExistingObject(),
|
||||
$content_id
|
||||
);
|
||||
|
||||
try {
|
||||
$this->dispatch(TheliaEvents::PRODUCT_REMOVE_CONTENT, $event);
|
||||
}
|
||||
catch (\Exception $ex) {
|
||||
// Any error
|
||||
return $this->errorPage($ex);
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirectToEditionTemplate();
|
||||
}
|
||||
}
|
||||
48
core/lib/Thelia/Core/Event/ProductAddContentEvent.php
Normal file
48
core/lib/Thelia/Core/Event/ProductAddContentEvent.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
use Thelia\Model\Product;
|
||||
|
||||
class ProductAddContentEvent extends ProductEvent
|
||||
{
|
||||
protected $content_id;
|
||||
|
||||
public function __construct(Product $product, $content_id)
|
||||
{
|
||||
parent::__construct($product);
|
||||
|
||||
$this->content_id = $content_id;
|
||||
}
|
||||
|
||||
public function getContentId()
|
||||
{
|
||||
return $this->content_id;
|
||||
}
|
||||
|
||||
public function setContentId($content_id)
|
||||
{
|
||||
$this->content_id = $content_id;
|
||||
}
|
||||
}
|
||||
80
core/lib/Thelia/Core/Event/ProductCreateEvent.php
Normal file
80
core/lib/Thelia/Core/Event/ProductCreateEvent.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
class ProductCreateEvent extends ProductEvent
|
||||
{
|
||||
protected $title;
|
||||
protected $parent;
|
||||
protected $locale;
|
||||
protected $visible;
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function setParent($parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLocale()
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
public function setLocale($locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVisible()
|
||||
{
|
||||
return $this->visible;
|
||||
}
|
||||
|
||||
public function setVisible($visible)
|
||||
{
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
48
core/lib/Thelia/Core/Event/ProductDeleteContentEvent.php
Normal file
48
core/lib/Thelia/Core/Event/ProductDeleteContentEvent.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
use Thelia\Model\Product;
|
||||
|
||||
class ProductDeleteContentEvent extends ProductEvent
|
||||
{
|
||||
protected $content_id;
|
||||
|
||||
public function __construct(Product $product, $content_id)
|
||||
{
|
||||
parent::__construct($product);
|
||||
|
||||
$this->content_id = $content_id;
|
||||
}
|
||||
|
||||
public function getContentId()
|
||||
{
|
||||
return $this->content_id;
|
||||
}
|
||||
|
||||
public function setContentId($content_id)
|
||||
{
|
||||
$this->content_id = $content_id;
|
||||
}
|
||||
}
|
||||
44
core/lib/Thelia/Core/Event/ProductDeleteEvent.php
Normal file
44
core/lib/Thelia/Core/Event/ProductDeleteEvent.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
class ProductDeleteEvent extends ProductEvent
|
||||
{
|
||||
public function __construct($product_id)
|
||||
{
|
||||
$this->product_id = $product_id;
|
||||
}
|
||||
|
||||
public function getProductId()
|
||||
{
|
||||
return $this->product_id;
|
||||
}
|
||||
|
||||
public function setProductId($product_id)
|
||||
{
|
||||
$this->product_id = $product_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
54
core/lib/Thelia/Core/Event/ProductEvent.php
Normal file
54
core/lib/Thelia/Core/Event/ProductEvent.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
use Thelia\Model\Product;
|
||||
use Thelia\Core\Event\ActionEvent;
|
||||
|
||||
class ProductEvent extends ActionEvent
|
||||
{
|
||||
public $product = null;
|
||||
|
||||
public function __construct(Product $product = null)
|
||||
{
|
||||
$this->product = $product;
|
||||
}
|
||||
|
||||
public function hasProduct()
|
||||
{
|
||||
return ! is_null($this->product);
|
||||
}
|
||||
|
||||
public function getProduct()
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(Product $product)
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
28
core/lib/Thelia/Core/Event/ProductToggleVisibilityEvent.php
Normal file
28
core/lib/Thelia/Core/Event/ProductToggleVisibilityEvent.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
class ProductToggleVisibilityEvent extends ProductEvent
|
||||
{
|
||||
}
|
||||
113
core/lib/Thelia/Core/Event/ProductUpdateEvent.php
Normal file
113
core/lib/Thelia/Core/Event/ProductUpdateEvent.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Event;
|
||||
|
||||
class ProductUpdateEvent extends ProductCreateEvent
|
||||
{
|
||||
protected $product_id;
|
||||
|
||||
protected $chapo;
|
||||
protected $description;
|
||||
protected $postscriptum;
|
||||
|
||||
protected $url;
|
||||
protected $parent;
|
||||
|
||||
public function __construct($product_id)
|
||||
{
|
||||
$this->product_id = $product_id;
|
||||
}
|
||||
|
||||
public function getProductId()
|
||||
{
|
||||
return $this->product_id;
|
||||
}
|
||||
|
||||
public function setProductId($product_id)
|
||||
{
|
||||
$this->product_id = $product_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChapo()
|
||||
{
|
||||
return $this->chapo;
|
||||
}
|
||||
|
||||
public function setChapo($chapo)
|
||||
{
|
||||
$this->chapo = $chapo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPostscriptum()
|
||||
{
|
||||
return $this->postscriptum;
|
||||
}
|
||||
|
||||
public function setPostscriptum($postscriptum)
|
||||
{
|
||||
$this->postscriptum = $postscriptum;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function setParent($parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -165,6 +165,26 @@ final class TheliaEvents
|
||||
const BEFORE_UPDATECATEGORY = "action.before_updateCategory";
|
||||
const AFTER_UPDATECATEGORY = "action.after_updateCategory";
|
||||
|
||||
// -- Product management -----------------------------------------------
|
||||
|
||||
const PRODUCT_CREATE = "action.createProduct";
|
||||
const PRODUCT_UPDATE = "action.updateProduct";
|
||||
const PRODUCT_DELETE = "action.deleteProduct";
|
||||
const PRODUCT_TOGGLE_VISIBILITY = "action.toggleProductVisibility";
|
||||
const PRODUCT_UPDATE_POSITION = "action.updateProductPosition";
|
||||
|
||||
const PRODUCT_ADD_CONTENT = "action.productAddContent";
|
||||
const PRODUCT_REMOVE_CONTENT = "action.productRemoveContent";
|
||||
|
||||
const BEFORE_CREATEPRODUCT = "action.before_createproduct";
|
||||
const AFTER_CREATEPRODUCT = "action.after_createproduct";
|
||||
|
||||
const BEFORE_DELETEPRODUCT = "action.before_deleteproduct";
|
||||
const AFTER_DELETEPRODUCT = "action.after_deleteproduct";
|
||||
|
||||
const BEFORE_UPDATEPRODUCT = "action.before_updateProduct";
|
||||
const AFTER_UPDATEPRODUCT = "action.after_updateProduct";
|
||||
|
||||
/**
|
||||
* sent when a new existing cat id duplicated. This append when current customer is different from current cart
|
||||
*/
|
||||
|
||||
@@ -102,14 +102,16 @@ class Content extends BaseI18nLoop
|
||||
|
||||
if (!is_null($folder) || !is_null($folderDefault)) {
|
||||
|
||||
if (!is_null($folder)) {
|
||||
$folders = FolderQuery::create()->filterById($folder, Criteria::IN)->find();
|
||||
}
|
||||
|
||||
if (!is_null($folderDefault)) {
|
||||
$folders = FolderQuery::create()->filterById($folderDefault, Criteria::IN)->find();
|
||||
$foldersIds = array();
|
||||
if (!is_array($folder)) {
|
||||
$folder = array();
|
||||
}
|
||||
if (!is_array($folderDefault)) {
|
||||
$folderDefault = array();
|
||||
}
|
||||
|
||||
$foldersIds = array_merge($foldersIds, $folder, $folderDefault);
|
||||
$folders =FolderQuery::create()->filterById($foldersIds, Criteria::IN)->find();
|
||||
|
||||
$depth = $this->getDepth();
|
||||
|
||||
@@ -174,12 +176,12 @@ class Content extends BaseI18nLoop
|
||||
$search->addDescendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
case "manual":
|
||||
if(null === $folder || count($folder) != 1)
|
||||
if(null === $foldersIds || count($foldersIds) != 1)
|
||||
throw new \InvalidArgumentException('Manual order cannot be set without single folder argument');
|
||||
$search->orderByPosition(Criteria::ASC);
|
||||
break;
|
||||
case "manual_reverse":
|
||||
if(null === $folder || count($folder) != 1)
|
||||
if(null === $foldersIds || count($foldersIds) != 1)
|
||||
throw new \InvalidArgumentException('Manual order cannot be set without single folder argument');
|
||||
$search->orderByPosition(Criteria::DESC);
|
||||
break;
|
||||
|
||||
@@ -89,7 +89,7 @@ class Product extends BaseI18nLoop
|
||||
new Argument(
|
||||
'order',
|
||||
new TypeCollection(
|
||||
new Type\EnumListType(array('alpha', 'alpha_reverse', 'min_price', 'max_price', 'manual', 'manual_reverse', 'ref', 'promo', 'new', 'random', 'given_id'))
|
||||
new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse', 'min_price', 'max_price', 'manual', 'manual_reverse', 'ref', 'promo', 'new', 'random', 'given_id'))
|
||||
),
|
||||
'alpha'
|
||||
),
|
||||
@@ -175,13 +175,17 @@ class Product extends BaseI18nLoop
|
||||
|
||||
if (!is_null($category) ||!is_null($categoryDefault)) {
|
||||
|
||||
if (!is_null($category)) {
|
||||
$categories = CategoryQuery::create()->filterById($category, Criteria::IN)->find();
|
||||
$categoryIds = array();
|
||||
if (!is_array($category)) {
|
||||
$category = array();
|
||||
}
|
||||
if (!is_null($categoryDefault)) {
|
||||
$categories = CategoryQuery::create()->filterById($categoryDefault, Criteria::IN)->find();
|
||||
if (!is_array($categoryDefault)) {
|
||||
$categoryDefault = array();
|
||||
}
|
||||
|
||||
$categoryIds = array_merge($categoryIds, $category, $categoryDefault);
|
||||
$categories =CategoryQuery::create()->filterById($categoryIds, Criteria::IN)->find();
|
||||
|
||||
$depth = $this->getDepth();
|
||||
|
||||
if (null !== $depth) {
|
||||
@@ -535,6 +539,12 @@ class Product extends BaseI18nLoop
|
||||
|
||||
foreach ($orders as $order) {
|
||||
switch ($order) {
|
||||
case "id":
|
||||
$search->orderById(Criteria::ASC);
|
||||
break;
|
||||
case "id_reverse":
|
||||
$search->orderById(Criteria::DESC);
|
||||
break;
|
||||
case "alpha":
|
||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||
break;
|
||||
@@ -548,12 +558,12 @@ class Product extends BaseI18nLoop
|
||||
$search->addDescendingOrderByColumn('real_lowest_price');
|
||||
break;
|
||||
case "manual":
|
||||
if(null === $category || count($category) != 1)
|
||||
if(null === $categoryIds || count($categoryIds) != 1)
|
||||
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
||||
$search->orderByPosition(Criteria::ASC);
|
||||
break;
|
||||
case "manual_reverse":
|
||||
if(null === $category || count($category) != 1)
|
||||
if(null === $categoryIds || count($categoryIds) != 1)
|
||||
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
||||
$search->orderByPosition(Criteria::DESC);
|
||||
break;
|
||||
|
||||
@@ -53,7 +53,7 @@ class CategoryCreationForm extends BaseForm
|
||||
"label_attr" => array("for" => "locale_create")
|
||||
))
|
||||
->add("visible", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("This category is online on the front office."),
|
||||
"label" => Translator::getInstance()->trans("This category is online."),
|
||||
"label_attr" => array("for" => "visible_create")
|
||||
))
|
||||
;
|
||||
|
||||
@@ -47,7 +47,7 @@ class ProductCreationForm extends BaseForm
|
||||
"for" => "title"
|
||||
)
|
||||
))
|
||||
->add("parent", "integer", array(
|
||||
->add("default_category", "integer", array(
|
||||
"constraints" => array(
|
||||
new NotBlank()
|
||||
)
|
||||
@@ -57,6 +57,10 @@ class ProductCreationForm extends BaseForm
|
||||
new NotBlank()
|
||||
)
|
||||
))
|
||||
->add("visible", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("This product is online."),
|
||||
"label_attr" => array("for" => "visible_create")
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
64
core/lib/Thelia/Form/ProductModificationForm.php
Normal file
64
core/lib/Thelia/Form/ProductModificationForm.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Form;
|
||||
|
||||
use Symfony\Component\Validator\Constraints\GreaterThan;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
class ProductModificationForm extends ProductCreationForm
|
||||
{
|
||||
use StandardDescriptionFieldsTrait;
|
||||
|
||||
protected function buildForm()
|
||||
{
|
||||
parent::buildForm(true);
|
||||
|
||||
$this->formBuilder
|
||||
->add("id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Prodcut ID *"),
|
||||
"label_attr" => array("for" => "product_id_field"),
|
||||
"constraints" => array(new GreaterThan(array('value' => 0)))
|
||||
|
||||
))
|
||||
->add("template_id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Product template"),
|
||||
"label_attr" => array("for" => "product_template_field")
|
||||
|
||||
))
|
||||
->add("url", "text", array(
|
||||
"label" => Translator::getInstance()->trans("Rewriten URL *"),
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label_attr" => array("for" => "rewriten_url_field")
|
||||
))
|
||||
;
|
||||
|
||||
// Add standard description fields, excluding title and locale, which a re defined in parent class
|
||||
$this->addStandardDescFields(array('title', 'locale'));
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return "thelia_product_modification";
|
||||
}
|
||||
}
|
||||
@@ -857,7 +857,7 @@ abstract class ProductQuery extends ModelCriteria
|
||||
*
|
||||
* @return ChildProductQuery The current query, for fluid interface
|
||||
*/
|
||||
public function joinTemplate($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
public function joinTemplate($relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
$tableMap = $this->getTableMap();
|
||||
$relationMap = $tableMap->getRelation('Template');
|
||||
@@ -892,7 +892,7 @@ abstract class ProductQuery extends ModelCriteria
|
||||
*
|
||||
* @return \Thelia\Model\TemplateQuery A secondary query class using the current class as primary query
|
||||
*/
|
||||
public function useTemplateQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
public function useTemplateQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
return $this
|
||||
->joinTemplate($relationAlias, $joinType)
|
||||
|
||||
@@ -864,9 +864,10 @@ abstract class Template implements ActiveRecordInterface
|
||||
|
||||
if ($this->productsScheduledForDeletion !== null) {
|
||||
if (!$this->productsScheduledForDeletion->isEmpty()) {
|
||||
\Thelia\Model\ProductQuery::create()
|
||||
->filterByPrimaryKeys($this->productsScheduledForDeletion->getPrimaryKeys(false))
|
||||
->delete($con);
|
||||
foreach ($this->productsScheduledForDeletion as $product) {
|
||||
// need to save related object because we set the relation to null
|
||||
$product->save($con);
|
||||
}
|
||||
$this->productsScheduledForDeletion = null;
|
||||
}
|
||||
}
|
||||
@@ -1553,7 +1554,7 @@ abstract class Template implements ActiveRecordInterface
|
||||
$this->productsScheduledForDeletion = clone $this->collProducts;
|
||||
$this->productsScheduledForDeletion->clear();
|
||||
}
|
||||
$this->productsScheduledForDeletion[]= clone $product;
|
||||
$this->productsScheduledForDeletion[]= $product;
|
||||
$product->setTemplate(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ abstract class TemplateQuery extends ModelCriteria
|
||||
*
|
||||
* @return ChildTemplateQuery The current query, for fluid interface
|
||||
*/
|
||||
public function joinProduct($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
public function joinProduct($relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
$tableMap = $this->getTableMap();
|
||||
$relationMap = $tableMap->getRelation('Product');
|
||||
@@ -430,7 +430,7 @@ abstract class TemplateQuery extends ModelCriteria
|
||||
*
|
||||
* @return \Thelia\Model\ProductQuery A secondary query class using the current class as primary query
|
||||
*/
|
||||
public function useProductQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN)
|
||||
public function useProductQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
return $this
|
||||
->joinProduct($relationAlias, $joinType)
|
||||
|
||||
@@ -28,7 +28,7 @@ class Category extends BaseCategory
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
protected function getRewrittenUrlViewName() {
|
||||
return 'category';
|
||||
}
|
||||
|
||||
@@ -69,8 +69,6 @@ class Category extends BaseCategory
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_CREATECATEGORY, new CategoryEvent($this));
|
||||
|
||||
return true;
|
||||
@@ -81,6 +79,7 @@ class Category extends BaseCategory
|
||||
*/
|
||||
public function postInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
//$this->generateRewrittenUrl($this->getLocale());
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_CREATECATEGORY, new CategoryEvent($this));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Content extends BaseContent
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
protected function getRewrittenUrlViewName() {
|
||||
return 'content';
|
||||
}
|
||||
|
||||
@@ -37,8 +37,11 @@ class Content extends BaseContent
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
//$this->generateRewrittenUrl($this->getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class Folder extends BaseFolder
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
protected function getRewrittenUrlViewName() {
|
||||
return 'folder';
|
||||
}
|
||||
|
||||
@@ -67,8 +67,12 @@ class Folder extends BaseFolder
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
//$this->generateRewrittenUrl($this->getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ class AttributeCombinationTableMap extends TableMap
|
||||
{
|
||||
$this->addRelation('Attribute', '\\Thelia\\Model\\Attribute', RelationMap::MANY_TO_ONE, array('attribute_id' => 'id', ), 'CASCADE', 'RESTRICT');
|
||||
$this->addRelation('AttributeAv', '\\Thelia\\Model\\AttributeAv', RelationMap::MANY_TO_ONE, array('attribute_av_id' => 'id', ), 'CASCADE', 'RESTRICT');
|
||||
$this->addRelation('ProductSaleElements', '\\Thelia\\Model\\ProductSaleElements', RelationMap::MANY_TO_ONE, array('product_sale_elements_id' => 'id', ), null, null);
|
||||
$this->addRelation('ProductSaleElements', '\\Thelia\\Model\\ProductSaleElements', RelationMap::MANY_TO_ONE, array('product_sale_elements_id' => 'id', ), 'CASCADE', 'RESTRICT');
|
||||
} // buildRelations()
|
||||
|
||||
/**
|
||||
|
||||
@@ -182,7 +182,7 @@ class ProductSaleElementsTableMap extends TableMap
|
||||
public function buildRelations()
|
||||
{
|
||||
$this->addRelation('Product', '\\Thelia\\Model\\Product', RelationMap::MANY_TO_ONE, array('product_id' => 'id', ), 'CASCADE', 'RESTRICT');
|
||||
$this->addRelation('AttributeCombination', '\\Thelia\\Model\\AttributeCombination', RelationMap::ONE_TO_MANY, array('id' => 'product_sale_elements_id', ), null, null, 'AttributeCombinations');
|
||||
$this->addRelation('AttributeCombination', '\\Thelia\\Model\\AttributeCombination', RelationMap::ONE_TO_MANY, array('id' => 'product_sale_elements_id', ), 'CASCADE', 'RESTRICT', 'AttributeCombinations');
|
||||
$this->addRelation('CartItem', '\\Thelia\\Model\\CartItem', RelationMap::ONE_TO_MANY, array('id' => 'product_sale_elements_id', ), null, null, 'CartItems');
|
||||
$this->addRelation('ProductPrice', '\\Thelia\\Model\\ProductPrice', RelationMap::ONE_TO_MANY, array('id' => 'product_sale_elements_id', ), 'CASCADE', null, 'ProductPrices');
|
||||
} // buildRelations()
|
||||
@@ -206,6 +206,7 @@ class ProductSaleElementsTableMap extends TableMap
|
||||
{
|
||||
// Invalidate objects in ".$this->getClassNameFromBuilder($joinedTableTableMapBuilder)." instance pool,
|
||||
// since one or more of them may be deleted by ON DELETE CASCADE/SETNULL rule.
|
||||
AttributeCombinationTableMap::clearInstancePool();
|
||||
ProductPriceTableMap::clearInstancePool();
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ class ProductTableMap extends TableMap
|
||||
$this->addColumn('REF', 'Ref', 'VARCHAR', true, 255, null);
|
||||
$this->addColumn('VISIBLE', 'Visible', 'TINYINT', true, null, 0);
|
||||
$this->addColumn('POSITION', 'Position', 'INTEGER', true, null, null);
|
||||
$this->addForeignKey('TEMPLATE_ID', 'TemplateId', 'INTEGER', 'template', 'ID', true, null, null);
|
||||
$this->addForeignKey('TEMPLATE_ID', 'TemplateId', 'INTEGER', 'template', 'ID', false, null, null);
|
||||
$this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addColumn('VERSION', 'Version', 'INTEGER', false, null, 0);
|
||||
|
||||
@@ -180,7 +180,7 @@ class ProductVersionTableMap extends TableMap
|
||||
$this->addColumn('REF', 'Ref', 'VARCHAR', true, 255, null);
|
||||
$this->addColumn('VISIBLE', 'Visible', 'TINYINT', true, null, 0);
|
||||
$this->addColumn('POSITION', 'Position', 'INTEGER', true, null, null);
|
||||
$this->addColumn('TEMPLATE_ID', 'TemplateId', 'INTEGER', true, null, null);
|
||||
$this->addColumn('TEMPLATE_ID', 'TemplateId', 'INTEGER', false, null, null);
|
||||
$this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addPrimaryKey('VERSION', 'Version', 'INTEGER', true, null, 0);
|
||||
|
||||
@@ -7,6 +7,9 @@ use Thelia\Model\Base\Product as BaseProduct;
|
||||
use Thelia\Tools\URL;
|
||||
use Thelia\TaxEngine\Calculator;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\ProductEvent;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
|
||||
class Product extends BaseProduct
|
||||
{
|
||||
@@ -19,7 +22,7 @@ class Product extends BaseProduct
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
protected function getRewrittenUrlViewName() {
|
||||
return 'product';
|
||||
}
|
||||
|
||||
@@ -41,14 +44,60 @@ class Product extends BaseProduct
|
||||
return round($taxCalculator->load($this, $country)->getTaxedPrice($this->getRealLowestPrice()), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current default category for this product
|
||||
*/
|
||||
public function getDefaultCategoryId()
|
||||
{
|
||||
// Find default category
|
||||
$default_category = ProductCategoryQuery::create()
|
||||
->filterByProductId($this->getId())
|
||||
->filterByDefaultCategory(true)
|
||||
->findOne();
|
||||
|
||||
return $default_category == null ? 0 : $default_category->getCategoryId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default category for this product
|
||||
*
|
||||
* @param integer $categoryId the new default category id
|
||||
*/
|
||||
public function setDefaultCategory($categoryId)
|
||||
{
|
||||
// Unset previous category
|
||||
ProductCategoryQuery::create()
|
||||
->filterByProductId($this->getId())
|
||||
->filterByDefaultCategory(true)
|
||||
->find()
|
||||
->setByDefault(false)
|
||||
->save();
|
||||
|
||||
// Set new default category
|
||||
ProductCategoryQuery::create()
|
||||
->filterByProductId($this->getId())
|
||||
->filterByCategoryId($categoryId)
|
||||
->find()
|
||||
->setByDefault(true)
|
||||
->save();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our default category
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query) {
|
||||
|
||||
// TODO: Find the default category for this product,
|
||||
// and generate the position relative to this category
|
||||
protected function addCriteriaToPositionQuery($query)
|
||||
{
|
||||
// Find products in the same category
|
||||
$produits = ProductCategoryQuery::create()
|
||||
->filterByCategoryId($this->getDefaultCategoryId())
|
||||
->filterByDefaultCategory(true)
|
||||
->select('product_id')
|
||||
->find();
|
||||
|
||||
// Filtrer la requete sur ces produits
|
||||
if ($produits != null) $query->filterById($produits, Criteria::IN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,8 +107,56 @@ class Product extends BaseProduct
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_CREATEPRODUCT, new ProductEvent($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
//$this->generateRewrittenUrl($this->getLocale());
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_CREATEPRODUCT, new ProductEvent($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preUpdate(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_UPDATEPRODUCT, new ProductEvent($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postUpdate(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_UPDATEPRODUCT, new ProductEvent($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preDelete(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_DELETEPRODUCT, new ProductEvent($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postDelete(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_DELETEPRODUCT, new ProductEvent($this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Rewriting as BaseRewriting;
|
||||
|
||||
class Rewriting extends BaseRewriting {
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\RewritingQuery as BaseRewritingQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'rewriting' 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 RewritingQuery extends BaseRewritingQuery {
|
||||
|
||||
} // RewritingQuery
|
||||
@@ -2,8 +2,25 @@
|
||||
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Thelia\Model\Base\RewritingUrl as BaseRewritingUrl;
|
||||
use Thelia\Model\RewritingUrlQuery;
|
||||
|
||||
class RewritingUrl extends BaseRewritingUrl {
|
||||
|
||||
public function preSave(ConnectionInterface $con = null)
|
||||
{
|
||||
if($this->getRedirected() == 0) {
|
||||
//check if rewriting url alredy exists and put redirect to 1
|
||||
RewritingUrlQuery::create()
|
||||
->filterByView($this->getView())
|
||||
->filterByViewId($this->getViewId())
|
||||
->filterByViewLocale($this->getViewLocale())
|
||||
->update(array(
|
||||
"redirect" => 1
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
namespace Thelia\Model\Tools;
|
||||
|
||||
use Thelia\Exception\UrlRewritingException;
|
||||
use Thelia\Model\RewritingUrlQuery;
|
||||
use Thelia\Model\RewritingUrl;
|
||||
use Thelia\Tools\URL;
|
||||
/**
|
||||
* A trait for managing Rewriten URLs from model classes
|
||||
@@ -32,7 +35,7 @@ trait UrlRewritingTrait {
|
||||
/**
|
||||
* @returns string the view name of the rewriten object (e.g., 'category', 'product')
|
||||
*/
|
||||
protected abstract function getRewritenUrlViewName();
|
||||
protected abstract function getRewrittenUrlViewName();
|
||||
|
||||
/**
|
||||
* Get the object URL for the given locale, rewriten if rewriting is enabled.
|
||||
@@ -41,7 +44,7 @@ trait UrlRewritingTrait {
|
||||
*/
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::getInstance()->retrieve($this->getRewritenUrlViewName(), $this->getId(), $locale)->toString();
|
||||
return URL::getInstance()->retrieve($this->getRewrittenUrlViewName(), $this->getId(), $locale)->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,27 +52,84 @@ trait UrlRewritingTrait {
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
*/
|
||||
public function generateRewritenUrl($locale)
|
||||
public function generateRewrittenUrl($locale)
|
||||
{
|
||||
URL::getInstance()->generateRewritenUrl($this->getRewritenUrlViewName(), $this->getId(), $locale, $this->getTitle());
|
||||
if ($this->isNew()) {
|
||||
throw new \RuntimeException(sprintf('Object %s must be save before generating url', $this->getRewrittenUrlViewName()));
|
||||
}
|
||||
// Borrowed from http://stackoverflow.com/questions/2668854/sanitizing-strings-to-make-them-url-and-filename-safe
|
||||
|
||||
$this->setLocale($locale);
|
||||
|
||||
$title = $this->getTitle();
|
||||
|
||||
if (null === $title) {
|
||||
throw new \RuntimeException(sprintf('Impossible to generate url if title does not exists for the locale %s', $locale));
|
||||
}
|
||||
// Replace all weird characters with dashes
|
||||
$string = preg_replace('/[^\w\-~_\.]+/u', '-', $title);
|
||||
|
||||
// Only allow one dash separator at a time (and make string lowercase)
|
||||
$cleanString = mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
|
||||
|
||||
$urlFilePart = $cleanString . ".html";
|
||||
|
||||
// TODO :
|
||||
// check if URL url already exists, and add a numeric suffix, or the like
|
||||
try{
|
||||
$i=0;
|
||||
while(URL::getInstance()->resolve($urlFilePart)) {
|
||||
$i++;
|
||||
$urlFilePart = sprintf("%s-%d.html",$cleanString, $i);
|
||||
}
|
||||
} catch (UrlRewritingException $e) {
|
||||
$rewritingUrl = new RewritingUrl();
|
||||
$rewritingUrl->setUrl($urlFilePart)
|
||||
->setView($this->getRewrittenUrlViewName())
|
||||
->setViewId($this->getId())
|
||||
->setViewLocale($locale)
|
||||
->setRedirected(0)
|
||||
->save()
|
||||
;
|
||||
}
|
||||
|
||||
return $urlFilePart;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* return the rewriten URL for the given locale
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
* @return null
|
||||
*/
|
||||
public function getRewritenUrl($locale)
|
||||
public function getRewrittenUrl($locale)
|
||||
{
|
||||
return "fake url - TODO";
|
||||
$rewritingUrl = RewritingUrlQuery::create()
|
||||
->filterByViewLocale($locale)
|
||||
->filterByView($this->getRewrittenUrlViewName())
|
||||
->filterByViewId($this->getId())
|
||||
->filterByRedirected(0)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
if($rewritingUrl) {
|
||||
$url = $rewritingUrl->getUrl();
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rewriten URL for the given locale
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
* @param $url the wanted url
|
||||
* @return $this
|
||||
*/
|
||||
public function setRewritenUrl($locale, $url)
|
||||
public function setRewrittenUrl($locale, $url)
|
||||
{
|
||||
// TODO - code me !
|
||||
|
||||
|
||||
@@ -449,11 +449,14 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
echo "Generating coupns fixtures\n";
|
||||
echo "Generating coupons fixtures\n";
|
||||
|
||||
generateCouponFixtures($thelia);
|
||||
|
||||
$con->commit();
|
||||
|
||||
echo "Successfully terminated.\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "error : ".$e->getMessage()."\n";
|
||||
$con->rollBack();
|
||||
|
||||
@@ -36,7 +36,7 @@ CREATE TABLE `product`
|
||||
`ref` VARCHAR(255) NOT NULL,
|
||||
`visible` TINYINT DEFAULT 0 NOT NULL,
|
||||
`position` INTEGER NOT NULL,
|
||||
`template_id` INTEGER NOT NULL,
|
||||
`template_id` INTEGER,
|
||||
`created_at` DATETIME,
|
||||
`updated_at` DATETIME,
|
||||
`version` INTEGER DEFAULT 0,
|
||||
@@ -343,6 +343,8 @@ CREATE TABLE `attribute_combination`
|
||||
CONSTRAINT `fk_attribute_combination_product_sale_elements_id`
|
||||
FOREIGN KEY (`product_sale_elements_id`)
|
||||
REFERENCES `product_sale_elements` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
@@ -893,9 +895,8 @@ CREATE TABLE `area_delivery_module`
|
||||
`created_at` DATETIME,
|
||||
`updated_at` DATETIME,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `delivery_module_id_area_id_UNIQUE` (`area_id`, `delivery_module_id`),
|
||||
INDEX `idx_area_delivery_module_area_id` (`area_id`),
|
||||
INDEX `idx_area_delivery_module_delivery_module_id` (`delivery_module_id`),
|
||||
INDEX `idx_area_delivery_module_delivery_module_id_idx` (`delivery_module_id`),
|
||||
CONSTRAINT `fk_area_delivery_module_area_id`
|
||||
FOREIGN KEY (`area_id`)
|
||||
REFERENCES `area` (`id`)
|
||||
@@ -2166,7 +2167,7 @@ CREATE TABLE `product_version`
|
||||
`ref` VARCHAR(255) NOT NULL,
|
||||
`visible` TINYINT DEFAULT 0 NOT NULL,
|
||||
`position` INTEGER NOT NULL,
|
||||
`template_id` INTEGER NOT NULL,
|
||||
`template_id` INTEGER,
|
||||
`created_at` DATETIME,
|
||||
`updated_at` DATETIME,
|
||||
`version` INTEGER DEFAULT 0 NOT NULL,
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<column name="description" type="CLOB" />
|
||||
<column name="chapo" type="LONGVARCHAR" />
|
||||
<column name="postscriptum" type="LONGVARCHAR" />
|
||||
<column name="template_id" required="true" type="INTEGER" />
|
||||
<column name="template_id" type="INTEGER" />
|
||||
<foreign-key foreignTable="tax_rule" name="fk_product_tax_rule_id" onDelete="SET NULL" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="tax_rule_id" />
|
||||
</foreign-key>
|
||||
@@ -259,7 +259,7 @@
|
||||
<foreign-key foreignTable="attribute_av" name="fk_attribute_combination_attribute_av_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="attribute_av_id" />
|
||||
</foreign-key>
|
||||
<foreign-key foreignTable="product_sale_elements" name="fk_attribute_combination_product_sale_elements_id">
|
||||
<foreign-key foreignTable="product_sale_elements" name="fk_attribute_combination_product_sale_elements_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="product_sale_elements_id" />
|
||||
</foreign-key>
|
||||
<index name="idx_attribute_combination_attribute_id">
|
||||
@@ -692,13 +692,9 @@
|
||||
<index name="idx_area_delivery_module_area_id">
|
||||
<index-column name="area_id" />
|
||||
</index>
|
||||
<index name="idx_area_delivery_module_delivery_module_id">
|
||||
<index name="idx_area_delivery_module_delivery_module_id_idx">
|
||||
<index-column name="delivery_module_id" />
|
||||
</index>
|
||||
<unique name="delivery_module_id_area_id_UNIQUE">
|
||||
<unique-column name="area_id" />
|
||||
<unique-column name="delivery_module_id" />
|
||||
</unique>
|
||||
<behavior name="timestampable" />
|
||||
</table>
|
||||
<table name="group" namespace="Thelia\Model">
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="general-block-decorator">
|
||||
|
||||
<table class="table table-striped table-condensed" id="category_list">
|
||||
<caption>
|
||||
{* display parent category name, and get current cat ID *}
|
||||
@@ -175,9 +176,169 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* -- PRODUCT MANAGEMENT ---------------------------------------------------- *}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="general-block-decorator">
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<caption>
|
||||
{* display parent category name *}
|
||||
{loop name="category_title" type="category" visible="*" id=$category_id}
|
||||
{intl l="Products in %cat" cat=$TITLE}
|
||||
{/loop}
|
||||
|
||||
{elseloop rel="category_title"}
|
||||
{intl l="Top level Products"}
|
||||
{/elseloop}
|
||||
|
||||
{module_include location='product_list_caption'}
|
||||
|
||||
<a class="btn btn-default btn-primary action-btn" title="{intl l='Add a new product'}" href="#productAddModal" data-toggle="modal">
|
||||
<span class="glyphicon glyphicon-plus-sign"></span>
|
||||
</a>
|
||||
</caption>
|
||||
|
||||
{ifloop rel="product_list"}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="object-title">
|
||||
{admin_sortable_header
|
||||
current_order=$product_order
|
||||
order='id'
|
||||
reverse_order='id_reverse'
|
||||
path={url path='/admin/categories' id_category=$category_id target='products'}
|
||||
label="{intl l='ID'}"
|
||||
}
|
||||
|
||||
<th> </th>
|
||||
|
||||
<th class="object-title">
|
||||
{admin_sortable_header
|
||||
current_order=$product_order
|
||||
order='ref'
|
||||
reverse_order='ref_reverse'
|
||||
path={url path='/admin/categories' id_category=$category_id target='products'}
|
||||
label="{intl l='Reference'}"
|
||||
}
|
||||
</th>
|
||||
|
||||
<th class="object-title">
|
||||
{admin_sortable_header
|
||||
current_order=$product_order
|
||||
order='alpha'
|
||||
reverse_order='alpha_reverse'
|
||||
path={url path='/admin/categories' id_category=$category_id target='products'}
|
||||
label="{intl l='Product title'}"
|
||||
}
|
||||
|
||||
{module_include location='product_list_header'}
|
||||
|
||||
<th>
|
||||
{admin_sortable_header
|
||||
current_order=$product_order
|
||||
order='visible'
|
||||
reverse_order='visible_reverse'
|
||||
path={url path='/admin/categories' id_category=$category_id target='products'}
|
||||
label="{intl l='Online'}"
|
||||
}
|
||||
</th>
|
||||
|
||||
<th>
|
||||
{admin_sortable_header
|
||||
current_order=$product_order
|
||||
order='manual'
|
||||
reverse_order='manual_reverse'
|
||||
path={url path='/admin/categories' id_category=$category_id target='products'}
|
||||
label="{intl l='Position'}"
|
||||
}
|
||||
</th>
|
||||
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{loop name="product_list" type="product" visible="*" category_default=$category_id order=$product_order}
|
||||
<tr>
|
||||
<td>{$ID}</td>
|
||||
|
||||
<td>
|
||||
{loop type="image" name="cat_image" source="product" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"}
|
||||
<a href="{url path='admin/product/edit' id=$ID}" title="{intl l='Edit this product'}">
|
||||
<img src="{$IMAGE_URL}" alt="{$TITLE}" />
|
||||
</a>
|
||||
{/loop}
|
||||
|
||||
<td class="object-title"><a href="{url path="/admin/product/update/$ID"}" title="{intl l='Edit this product'}">{$REF}</a></td>
|
||||
|
||||
<td class="object-title"><a href="{url path="/admin/product/update/$ID"}" title="{intl l='Edit this product'}">{$TITLE}</a></td>
|
||||
|
||||
{module_include location='product_list_row'}
|
||||
|
||||
<td>
|
||||
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.products.edit"}
|
||||
<div class="make-switch switch-small" data-on="success" data-off="danger" data-on-label="<i class='glyphicon glyphicon-ok'></i>" data-off-label="<i class='glyphicon glyphicon-remove'></i>">
|
||||
<input type="checkbox" data-id="{$ID}" class="productVisibleToggle" {if $VISIBLE == 1}checked="checked"{/if}>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
{elseloop rel="can_delete"}
|
||||
<div class="make-switch switch-small" data-on="success" data-off="danger" data-on-label="<i class='glyphicon glyphicon-ok'></i>" data-off-label="<i class='glyphicon glyphicon-remove'></i>">
|
||||
<input type="checkbox" data-id="{$ID}" class="displayToggle" {if $VISIBLE == 1}checked="checked"{/if}>
|
||||
</div>
|
||||
{/elseloop}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{admin_position_block
|
||||
permission="admin.product.edit"
|
||||
path={url path='admin/product' category_id=$ID}
|
||||
url_parameter="product_id"
|
||||
in_place_edit_class="productPositionChange"
|
||||
position=$POSITION
|
||||
id=$ID
|
||||
}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.product.edit"}
|
||||
<a class="btn btn-default btn-xs" title="{intl l='Edit this product'}" href="{url path="admin/product/update/$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
|
||||
{/loop}
|
||||
|
||||
{loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.product.delete"}
|
||||
<a class="btn btn-default btn-xs product-delete" title="{intl l='Delete this product'}" href="#product_delete_dialog" data-id="{$ID}" data-toggle="modal"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
{/loop}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/loop}
|
||||
</tbody>
|
||||
{/ifloop}
|
||||
|
||||
{elseloop rel="product_list"}
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="message"><div class="alert alert-info">{intl l="This category doesn't contains any products. To add a new product, <strong>click the + button</strong> above."}</div></td>
|
||||
</tr>
|
||||
</thead>
|
||||
{/elseloop}
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{module_include location='categories_bottom'}
|
||||
|
||||
</div>
|
||||
|
||||
{module_include location='catalog_bottom'}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -251,7 +412,7 @@
|
||||
{/form}
|
||||
|
||||
|
||||
{* Delete confirmation dialog *}
|
||||
{* Delete category confirmation dialog *}
|
||||
|
||||
{capture "category_delete_dialog"}
|
||||
<input type="hidden" name="category_id" id="category_delete_id" value="" />
|
||||
@@ -270,6 +431,26 @@
|
||||
form_action = {url path='/admin/categories/delete'}
|
||||
form_content = {$smarty.capture.category_delete_dialog nofilter}
|
||||
}
|
||||
|
||||
{* Delete product confirmation dialog *}
|
||||
|
||||
{capture "product_delete_dialog"}
|
||||
<input type="hidden" name="product_id" id="product_delete_id" value="" />
|
||||
|
||||
{module_include location='product_delete_form'}
|
||||
|
||||
{/capture}
|
||||
|
||||
{include
|
||||
file = "includes/generic-confirm-dialog.html"
|
||||
|
||||
dialog_id = "product_delete_dialog"
|
||||
dialog_title = {intl l="Delete product"}
|
||||
dialog_message = {intl l="Do you really want to delete this product ?"}
|
||||
|
||||
form_action = {url path='/admin/products/delete'}
|
||||
form_content = {$smarty.capture.product_delete_dialog nofilter}
|
||||
}
|
||||
{/block}
|
||||
|
||||
{block name="javascript-initialization"}
|
||||
@@ -290,6 +471,11 @@
|
||||
$('#category_delete_id').val($(this).data('id'));
|
||||
});
|
||||
|
||||
// Set proper product ID in delete from
|
||||
$('a.product-delete').click(function(ev) {
|
||||
$('#product_delete_id').val($(this).data('id'));
|
||||
});
|
||||
|
||||
// JS stuff for creation form
|
||||
{include
|
||||
file = "includes/generic-js-dialog.html"
|
||||
|
||||
Reference in New Issue
Block a user