Merge remote-tracking branch 'origin/master'

This commit is contained in:
gmorel
2013-09-17 17:39:22 +02:00
24 changed files with 2611 additions and 1217 deletions

View 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),
);
}
}

View File

@@ -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"/>

View File

@@ -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/">

View File

@@ -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)
));
}

View 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();
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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
{
}

View 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;
}
}

View File

@@ -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
*/

View File

@@ -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'
),
@@ -539,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;

View File

@@ -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")
))
;

View File

@@ -47,7 +47,7 @@ class ProductCreationForm extends BaseForm
"for" => "title"
)
))
->add("parent", "integer", array(
->add("default_category", "integer", array(
"constraints" => array(
new NotBlank()
)
@@ -57,7 +57,11 @@ class ProductCreationForm extends BaseForm
new NotBlank()
)
))
;
->add("visible", "integer", array(
"label" => Translator::getInstance()->trans("This product is online."),
"label_attr" => array("for" => "visible_create")
))
;
}
public function getName()

View 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";
}
}

View File

@@ -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()
/**

View File

@@ -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();
}

View File

@@ -7,6 +7,8 @@ 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;
class Product extends BaseProduct
{
@@ -41,14 +43,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 getDefaultCategory()
{
// Find default category
$default_category = ProductCategoryQuery::create()
->filterByProductId($this->getId())
->filterByDefaultCategory(true)
->findOne();
return $default_category;
}
/**
* 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)
{
// Retrourver les produits qui ont la même categorie par defaut
$produits = ProductCategoryQuery::create()
->filterByCategory($this->getDefaultCategory())
->filterByDefaultCategory(true)
->select('product_id')
->find();
// Filtrer la requete sur ces produits
if ($produits != null) $query->filterById($produits);
}
/**
@@ -60,6 +108,53 @@ class Product extends BaseProduct
$this->generateRewritenUrl($this->getLocale());
$this->dispatchEvent(TheliaEvents::BEFORE_CREATEPRODUCT, new ProductEvent($this));
return true;
}
/**
* {@inheritDoc}
*/
public function postInsert(ConnectionInterface $con = null)
{
$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));
}
}