diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index 7b95d80fa..1958d556b 100755 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -25,10 +25,14 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\ActionEvent; +use Thelia\Core\Event\Coupon\CouponCreateEvent; +use Thelia\Core\Event\Coupon\CouponDisableEvent; +use Thelia\Core\Event\Coupon\CouponEnableEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Model\Category as CategoryModel; use Thelia\Form\CategoryCreationForm; use Thelia\Core\Event\CategoryEvent; +use Thelia\Model\CouponQuery; use Thelia\Tools\Redirect; use Thelia\Model\CategoryQuery; use Thelia\Model\AdminLog; @@ -40,8 +44,116 @@ use Propel\Runtime\Propel; use Thelia\Model\Map\CategoryTableMap; use Propel\Runtime\Exception\PropelException; +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Process Coupon Events + * + * @package Coupon + * @author Guillaume MOREL + * + */ class Coupon extends BaseAction implements EventSubscriberInterface { + /** + * Create a Coupon if a Coupon creation attempt is found + * + * @param CouponCreateEvent $event Coupon creation Event + */ + public function create(CouponCreateEvent $event) + { + $this->checkAuth("ADMIN", "admin.coupon.create"); + + $this->dispatch( + TheliaEvents::BEFORE_CREATE_COUPON, + $event + ); + + $event->getCreatedCoupon()->save(); + + $this->dispatch( + TheliaEvents::AFTER_CREATE_COUPON, + $event + ); + } + + /** + * Edit a Coupon if a Coupon edition attempt is found + * + * @param CouponEditEvent $event Coupon edition Event + */ + public function edit(CouponEditEvent $event) + { + $this->checkAuth("ADMIN", "admin.coupon.edit"); + + $this->dispatch( + TheliaEvents::BEFORE_EDIT_COUPON, + $event + ); + + $couponToUpdate = CouponQuery::create()->findPk($event->getId()); + + if ($couponToUpdate !== null) { + $event->getCreatedCoupon()->save(); + } + + $this->dispatch( + TheliaEvents::AFTER_EDIT_COUPON, + $event + ); + } + + /** + * Disable a Coupon if a Coupon disable attempt is found + * + * @param CouponDisableEvent $event Coupon disable Event + */ + public function disable(CouponDisableEvent $event) + { + $this->checkAuth("ADMIN", "admin.coupon.disable"); + + $couponToUpdate = CouponQuery::create()->findPk($event->getId()); + + if ($couponToUpdate !== null) { + $couponToUpdate->setIsEnabled(0); + $event->getDispatcher()->dispatch( + TheliaEvents::BEFORE_DISABLE_COUPON, $event + ); + + $couponToUpdate->save(); + + $event->getDispatcher()->dispatch( + TheliaEvents::AFTER_DISABLE_COUPON, $event + ); + } + } + + /** + * Enable a Coupon if a Coupon enable attempt is found + * + * @param CouponEnableEvent $event Coupon enable Event + */ + public function enable(CouponEnableEvent $event) + { + $this->checkAuth("ADMIN", "admin.coupon.enable"); + + $couponToUpdate = CouponQuery::create()->findPk($event->getId()); + + if ($couponToUpdate !== null) { + $couponToUpdate->setIsEnabled(1); + $event->getDispatcher()->dispatch( + TheliaEvents::BEFORE_ENABLE_COUPON, $event + ); + + $couponToUpdate->save(); + + $event->getDispatcher()->dispatch( + TheliaEvents::AFTER_ENABLE_COUPON, $event + ); + } + } /** * Returns an array of event names this subscriber listens to. diff --git a/core/lib/Thelia/Controller/Admin/CategoryController.php b/core/lib/Thelia/Controller/Admin/CategoryController.php index fda94191c..4e798d683 100755 --- a/core/lib/Thelia/Controller/Admin/CategoryController.php +++ b/core/lib/Thelia/Controller/Admin/CategoryController.php @@ -89,7 +89,7 @@ class CategoryController extends BaseAdminController $categoryDeletionForm = new CategoryDeletionForm($this->getRequest()); $data = $this->validateForm($categoryDeletionForm, "POST")->getData(); -var_dump($data); + $categoryDeleteEvent = new CategoryDeleteEvent($data['category_id']); $this->dispatch(TheliaEvents::CATEGORY_DELETE, $categoryDeleteEvent); @@ -151,8 +151,8 @@ var_dump($data); protected function positionDown($args) { $event = new CategoryChangePositionEvent( - $this->getRequest()->get('category_id', 0), - CategoryChangePositionEvent::POSITION_DOWN + $this->getRequest()->get('category_id', 0), + CategoryChangePositionEvent::POSITION_DOWN ); $this->dispatch(TheliaEvents::CATEGORY_CHANGE_POSITION, $event); diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php index b1cf197c8..ab018e245 100755 --- a/core/lib/Thelia/Controller/Admin/CouponController.php +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -23,8 +23,14 @@ namespace Thelia\Controller\Admin; +use Thelia\Core\Event\Coupon\CouponCreateEvent; +use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\AuthorizationException; +use Thelia\Coupon\CouponRuleCollection; +use Thelia\Form\CouponCreationForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Model\Coupon; /** * Created by JetBrains PhpStorm. @@ -74,7 +80,46 @@ class CouponController extends BaseAdminController { $this->checkAuth("ADMIN", "admin.coupon.view"); - return $this->render('coupon/edit', $args); + if ($this->getRequest()->isMethod('POST')) { + try { + $couponCreationForm = new CouponCreationForm($this->getRequest()); + $couponBeingCreated = $this->buildCouponFromForm( + $this->validateForm($couponCreationForm, "POST")->getData() + ); + + $couponCreateEvent = new CouponCreateEvent( + $couponBeingCreated + ); + + $this->dispatch( + TheliaEvents::CREATE_COUPON, + $couponCreateEvent + ); + $this->adminLogAppend( + sprintf( + 'Coupon %s (ID %s) created', + $couponBeingCreated->getTitle(), + $couponBeingCreated->getId() + ) + ); + // @todo redirect if successful + } catch (FormValidationException $e) { + $couponCreationForm->setErrorMessage($e->getMessage()); + $this->getParserContext()->setErrorForm($couponCreationForm); + } catch (\Exception $e) { + Tlog::getInstance()->error( + sprintf( + "Failed to create coupon: %s", + $e->getMessage() + ) + ); + $this->getParserContext()->setGeneralError($e->getMessage()); + } + } else { + + } + + return $this->render('coupon/edit', array()); } /** @@ -114,7 +159,6 @@ class CouponController extends BaseAdminController */ public function processAction() { - var_dump($this->getRequest()->attributes); // Get the current action $action = $this->getRequest()->get('action', 'browse'); @@ -146,4 +190,39 @@ class CouponController extends BaseAdminController // We did not recognized the action -> return a 404 page return $this->pageNotFound(); } + + /** + * Build a Coupon from its form + * + * @param array $data Form data + * + * @return Coupon + */ + protected function buildCouponFromForm(array $data) + { + $couponBeingCreated = new Coupon(); + $couponBeingCreated->setCode($data["code"]); + $couponBeingCreated->setType($data["type"]); + $couponBeingCreated->setTitle($data["title"]); + $couponBeingCreated->setShortDescription($data["shortDescription"]); + $couponBeingCreated->setDescription($data["description"]); + $couponBeingCreated->setAmount($data["amount"]); + $couponBeingCreated->setIsEnabled($data["isEnabled"]); + $couponBeingCreated->setExpirationDate($data["expirationDate"]); + $couponBeingCreated->setSerializedRules( + new CouponRuleCollection( + array() + ) + ); + $couponBeingCreated->setIsCumulative($data["isCumulative"]); + $couponBeingCreated->setIsRemovingPostage( + $data["isRemovingPostage"] + ); + $couponBeingCreated->setMaxUsage($data["maxUsage"]); + $couponBeingCreated->setIsAvailableOnSpecialOffers( + $data["isAvailableOnSpecialOffers"] + ); + + return $couponBeingCreated; + } } diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponCreateEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponCreateEvent.php new file mode 100644 index 000000000..9f0db34df --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponCreateEvent.php @@ -0,0 +1,81 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Core\Event\ActionEvent; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is created + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponCreateEvent extends ActionEvent +{ + /** + * @var Coupon Coupon being created + */ + protected $createdCoupon; + + /** + * Constructor + * + * @param Coupon $coupon Coupon being created + */ + public function __construct(Coupon $coupon) + { + $this->createdCoupon = $coupon; + } + + /** + * Modify Coupon being created + * + * @param Coupon $createdCoupon Coupon being created + * + * @return $this + */ + public function setCreatedCoupon(Coupon $createdCoupon) + { + $this->createdCoupon = $createdCoupon; + + return $this; + } + + /** + * Get Coupon being created + * + * @return Coupon + */ + public function getCreatedCoupon() + { + return clone $this->createdCoupon; + } + + +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php new file mode 100644 index 000000000..db8e14243 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php @@ -0,0 +1,103 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is disabled + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponDisableEvent extends ActionEvent +{ + /** @var int Coupon id */ + protected $couponId; + + /** @var Coupon Coupon being disabled */ + protected $disabledCoupon; + + /** + * Constructor + * + * @param int $id Coupon Id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * Get Coupon id + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set Coupon id + * + * @param int $id Coupon id + * + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * Get Coupon being disabled + * + * @return Coupon + */ + public function getDisabledCoupon() + { + return $this->disabledCoupon; + } + + /** + * Set Coupon to be disabled + * + * @param Coupon $disabledCoupon Coupon to disable + * + * @return $this + */ + public function setDisabledCoupon(Coupon $disabledCoupon) + { + $this->disabledCoupon = $disabledCoupon; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponEditEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponEditEvent.php new file mode 100644 index 000000000..bdde56c40 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponEditEvent.php @@ -0,0 +1,82 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Core\Event\ActionEvent; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is edited + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponEditEvent extends ActionEvent +{ + /** @var int Coupon being edited id */ + protected $couponId; + + /** @var Coupon Coupon being created */ + protected $editedCoupon; + + /** + * Constructor + * + * @param Coupon $coupon Coupon being edited + */ + public function __construct(Coupon $coupon) + { + $this->created_coupon = $coupon; + } + + /** + * Modify Coupon being created + * + * @param Coupon $editedCoupon Coupon being created + * + * @return $this + */ + public function setCreatedCoupon(Coupon $editedCoupon) + { + $this->editedCoupon = $editedCoupon; + + return $this; + } + + /** + * Get Coupon being created + * + * @return Coupon + */ + public function getCreatedCoupon() + { + return clone $this->editedCoupon; + } + + +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php new file mode 100644 index 000000000..ab06953e5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php @@ -0,0 +1,103 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is enabled + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponEnableEvent extends ActionEvent +{ + /** @var int Coupon id */ + protected $couponId; + + /** @var Coupon Coupon being enabled */ + protected $enabledCoupon; + + /** + * Constructor + * + * @param int $id Coupon Id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * Get Coupon id + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set Coupon id + * + * @param int $id Coupon id + * + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * Get Coupon being enabled + * + * @return Coupon + */ + public function getEnabledCoupon() + { + return $this->enabledCoupon; + } + + /** + * Set Coupon to be enabled + * + * @param Coupon $enabledCoupon Coupon to enabled + * + * @return $this + */ + public function setEnabledCoupon(Coupon $enabledCoupon) + { + $this->enabledCoupon = $enabledCoupon; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 2dd85905d..8460efda9 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -177,4 +177,76 @@ final class TheliaEvents * Sent on cimage cache clear request */ const IMAGE_CLEAR_CACHE = "action.clearImageCache"; + + + + /** + * Sent when creating a Coupon + */ + const COUPON_CREATE = "action.create_coupon"; + + /** + * Sent just before a successful insert of a new Coupon in the database. + */ + const BEFORE_CREATE_COUPON = "action.before_create_coupon"; + + /** + * Sent just after a successful insert of a new Coupon in the database. + */ + const AFTER_CREATE_COUPON = "action.after_create_coupon"; + + /** + * Sent when editing a Coupon + */ + const COUPON_EDIT = "action.edit_coupon"; + + /** + * Sent just before a successful update of a new Coupon in the database. + */ + const BEFORE_EDIT_COUPON = "action.before_edit_coupon"; + + /** + * Sent just after a successful update of a new Coupon in the database. + */ + const AFTER_EDIT_COUPON = "action.after_edit_coupon"; + + /** + * Sent when disabling a Coupon + */ + const COUPON_DISABLE = "action.disable_coupon"; + + /** + * Sent just before a successful disable of a new Coupon in the database. + */ + const BEFORE_DISABLE_COUPON = "action.before_disable_coupon"; + + /** + * Sent just after a successful disable of a new Coupon in the database. + */ + const AFTER_DISABLE_COUPON = "action.after_disable_coupon"; + + /** + * Sent when enabling a Coupon + */ + const COUPON_ENABLE = "action.enable_coupon"; + + /** + * Sent just before a successful enable of a new Coupon in the database. + */ + const BEFORE_ENABLE_COUPON = "action.before_enable_coupon"; + + /** + * Sent just after a successful enable of a new Coupon in the database. + */ + const AFTER_ENABLE_COUPON = "action.after_enable_coupon"; + + /** + * Sent just before an attempt to use a Coupon + */ + const BEFORE_USE_COUPON = "action.before_use_coupon"; + + /** + * Sent just after an attempt to use a Coupon + */ + const AFTER_USE_COUPON = "action.after_use_coupon"; } diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 72f782309..8861022e9 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -28,6 +28,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Thelia\Core\Template\Loop\Argument\Argument; use Propel\Runtime\ActiveQuery\ModelCriteria; use Thelia\Core\Security\SecurityContext; +use Thelia\Model\Tools\ModelCriteriaTools; /** * @@ -234,6 +235,28 @@ abstract class BaseLoop } } + /** + * Setup ModelCriteria for proper i18n processing + * + * @param ModelCriteria $search the Propel Criteria to configure + * @param array $columns the i18n columns + * @param string $foreignTable the specified table (default to criteria table) + * @param string $foreignKey the foreign key in this table (default to criteria table) + */ + protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') { + + /* manage translations */ + ModelCriteriaTools::getI18n( + $this->getBackend_context(), + $this->getLang(), + $search, + $this->request->getSession()->getLocale(), + $columns, + $foreignTable, + $foreignKey + ); + } + /** * * this function have to be implement in your own loop class. diff --git a/core/lib/Thelia/Core/Template/Loop/Attribute.php b/core/lib/Thelia/Core/Template/Loop/Attribute.php index 41721350b..0608732a4 100755 --- a/core/lib/Thelia/Core/Template/Loop/Attribute.php +++ b/core/lib/Thelia/Core/Template/Loop/Attribute.php @@ -34,7 +34,6 @@ use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; use Thelia\Model\Base\LangQuery; -use Thelia\Model\Tools\ModelCriteriaTools; use Thelia\Model\Base\CategoryQuery; use Thelia\Model\Base\ProductCategoryQuery; @@ -92,7 +91,7 @@ class Attribute extends BaseLoop $lang = $this->getLang(); /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php index be42f5dab..0664c7d56 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php @@ -33,8 +33,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\Base\AttributeAvQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; @@ -79,12 +77,8 @@ class AttributeAvailability extends BaseLoop { $search = AttributeAvQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php index 833f1abb3..556a5a1fd 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php @@ -33,8 +33,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\Base\AttributeCombinationQuery; use Thelia\Model\Map\AttributeAvTableMap; use Thelia\Model\Map\AttributeTableMap; @@ -59,6 +57,7 @@ class AttributeCombination extends BaseLoop { return new ArgumentCollection( Argument::createIntTypeArgument('product_sale_elements', null, true), + Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -79,20 +78,16 @@ class AttributeCombination extends BaseLoop $search = AttributeCombinationQuery::create(); /* manage attribute translations */ - ModelCriteriaTools::getFrontEndI18n( + $this->configureI18nProcessing( $search, - ConfigQuery::read("default_lang_without_translation", 1), - $this->request->getSession()->getLocale(), array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), AttributeTableMap::TABLE_NAME, 'ATTRIBUTE_ID' ); /* manage attributeAv translations */ - ModelCriteriaTools::getFrontEndI18n( + $this->configureI18nProcessing( $search, - ConfigQuery::read("default_lang_without_translation", 1), - $this->request->getSession()->getLocale(), array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), AttributeAvTableMap::TABLE_NAME, 'ATTRIBUTE_AV_ID' diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index 9b497bb1a..e01ce3df4 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -32,8 +32,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\CategoryQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; @@ -98,12 +96,8 @@ class Category extends BaseLoop { $search = CategoryQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); @@ -169,7 +163,6 @@ class Category extends BaseLoop $loopResult = new LoopResult(); foreach ($categories as $category) { - /* * no cause pagination lost : * if ($this->getNotEmpty() && $category->countAllProducts() == 0) continue; diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php index d6c0cd02c..30238c26d 100755 --- a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php +++ b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php @@ -65,7 +65,8 @@ class CategoryPath extends BaseLoop Argument::createIntTypeArgument('category', null, true), Argument::createIntTypeArgument('depth'), Argument::createIntTypeArgument('level'), - Argument::createBooleanOrBothTypeArgument('visible', true, false) + Argument::createBooleanOrBothTypeArgument('visible', true, false), + Argument::createIntTypeArgument('lang') ); } @@ -80,6 +81,9 @@ class CategoryPath extends BaseLoop $visible = $this->getVisible(); $search = CategoryQuery::create(); + + $this->configureI18nProcessing($search, array('TITLE')); + $search->filterById($id); if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); @@ -95,7 +99,7 @@ class CategoryPath extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow - ->set("TITLE",$category->getTitle()) + ->set("TITLE",$category->getVirtualColumn('i18n_TITLE')) ->set("URL", $category->getUrl()) ->set("ID", $category->getId()) ; @@ -114,8 +118,11 @@ class CategoryPath extends BaseLoop $ids[] = $parent; $search = CategoryQuery::create(); + + $this->configureI18nProcessing($search, array('TITLE')); + $search->filterById($parent); - if ($visible == true) $search->filterByVisible($visible); + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); } } } while ($category != null && $parent > 0); diff --git a/core/lib/Thelia/Core/Template/Loop/Content.php b/core/lib/Thelia/Core/Template/Loop/Content.php index 6632a184c..701206ea8 100755 --- a/core/lib/Thelia/Core/Template/Loop/Content.php +++ b/core/lib/Thelia/Core/Template/Loop/Content.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\FolderQuery; use Thelia\Model\Map\ContentTableMap; use Thelia\Model\ContentFolderQuery; @@ -88,12 +86,8 @@ class Content extends BaseLoop { $search = ContentQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/Country.php b/core/lib/Thelia/Core/Template/Loop/Country.php index c6f7d16de..d93d94cb4 100755 --- a/core/lib/Thelia/Core/Template/Loop/Country.php +++ b/core/lib/Thelia/Core/Template/Loop/Country.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\CountryQuery; use Thelia\Model\ConfigQuery; @@ -70,12 +68,8 @@ class Country extends BaseLoop { $search = CountryQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/Currency.php b/core/lib/Thelia/Core/Template/Loop/Currency.php index d833ff8ae..b793b86fd 100755 --- a/core/lib/Thelia/Core/Template/Loop/Currency.php +++ b/core/lib/Thelia/Core/Template/Loop/Currency.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\CurrencyQuery; use Thelia\Model\ConfigQuery; @@ -69,12 +67,8 @@ class Currency extends BaseLoop { $search = CurrencyQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale(), array('NAME')); + $this->configureI18nProcessing($search, array('NAME')); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/Feature.php b/core/lib/Thelia/Core/Template/Loop/Feature.php index 85d037080..e2de85dbc 100755 --- a/core/lib/Thelia/Core/Template/Loop/Feature.php +++ b/core/lib/Thelia/Core/Template/Loop/Feature.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\Base\CategoryQuery; use Thelia\Model\Base\ProductCategoryQuery; use Thelia\Model\Base\FeatureQuery; @@ -84,12 +82,8 @@ class Feature extends BaseLoop { $search = FeatureQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php index ce6f8767a..c04d70031 100755 --- a/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\Base\FeatureAvQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; @@ -77,12 +75,8 @@ class FeatureAvailability extends BaseLoop { $search = FeatureAvQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureValue.php b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php index 8a29d7c74..42d50c57b 100755 --- a/core/lib/Thelia/Core/Template/Loop/FeatureValue.php +++ b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php @@ -33,8 +33,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\Base\FeatureProductQuery; use Thelia\Model\ConfigQuery; use Thelia\Model\Map\FeatureAvTableMap; @@ -70,7 +68,8 @@ class FeatureValue extends BaseLoop new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse')) ), 'manual' - ) + ), + Argument::createIntTypeArgument('lang') ); } @@ -84,10 +83,8 @@ class FeatureValue extends BaseLoop $search = FeatureProductQuery::create(); /* manage featureAv translations */ - ModelCriteriaTools::getFrontEndI18n( + $this->configureI18nProcessing( $search, - ConfigQuery::read("default_lang_without_translation", 1), - $this->request->getSession()->getLocale(), array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), FeatureAvTableMap::TABLE_NAME, 'FEATURE_AV_ID' diff --git a/core/lib/Thelia/Core/Template/Loop/Folder.php b/core/lib/Thelia/Core/Template/Loop/Folder.php index c95b0dc42..327ce76d4 100755 --- a/core/lib/Thelia/Core/Template/Loop/Folder.php +++ b/core/lib/Thelia/Core/Template/Loop/Folder.php @@ -32,8 +32,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\FolderQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; @@ -80,12 +78,8 @@ class Folder extends BaseLoop { $search = FolderQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $id = $this->getId(); diff --git a/core/lib/Thelia/Core/Template/Loop/Image.php b/core/lib/Thelia/Core/Template/Loop/Image.php index a1e866cb2..638905dc2 100755 --- a/core/lib/Thelia/Core/Template/Loop/Image.php +++ b/core/lib/Thelia/Core/Template/Loop/Image.php @@ -207,16 +207,8 @@ class Image extends BaseLoop } - /** - * \Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation. - * - * @todo : verify here if we want results for row without translations. - */ - - $search->joinWithI18n( - $this->request->getSession()->getLocale(), - (ConfigQuery::read("default_lang_without_translation", 1)) ? Criteria::LEFT_JOIN : Criteria::INNER_JOIN - ); + /* manage translations */ + $this->configureI18nProcessing($search); $results = $this->search($search, $pagination); @@ -295,6 +287,7 @@ class Image extends BaseLoop ), 'manual' ), + Argument::createIntTypeArgument('lang'), Argument::createIntTypeArgument('width'), Argument::createIntTypeArgument('height'), diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index 10112ef28..1570acca8 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -33,8 +33,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\CategoryQuery; use Thelia\Model\Map\FeatureProductTableMap; use Thelia\Model\Map\ProductPriceTableMap; @@ -138,12 +136,8 @@ class Product extends BaseLoop { $search = ProductQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale()); + $this->configureI18nProcessing($search); $attributeNonStrictMatch = $this->getAttribute_non_strict_match(); $isPSELeftJoinList = array(); diff --git a/core/lib/Thelia/Core/Template/Loop/Title.php b/core/lib/Thelia/Core/Template/Loop/Title.php index caa5e7d87..c53be086a 100755 --- a/core/lib/Thelia/Core/Template/Loop/Title.php +++ b/core/lib/Thelia/Core/Template/Loop/Title.php @@ -31,8 +31,6 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Model\Tools\ModelCriteriaTools; - use Thelia\Model\CustomerTitleQuery; use Thelia\Model\ConfigQuery; @@ -67,12 +65,8 @@ class Title extends BaseLoop { $search = CustomerTitleQuery::create(); - $backendContext = $this->getBackend_context(); - - $lang = $this->getLang(); - /* manage translations */ - ModelCriteriaTools::getI18n($backendContext, $lang, $search, ConfigQuery::read("default_lang_without_translation", 1), $this->request->getSession()->getLocale(), array('SHORT', 'LONG')); + $this->configureI18nProcessing($search, array('SHORT', 'LONG')); $id = $this->getId(); diff --git a/core/lib/Thelia/Form/CouponCreationForm.php b/core/lib/Thelia/Form/CouponCreationForm.php new file mode 100755 index 000000000..39667cfdb --- /dev/null +++ b/core/lib/Thelia/Form/CouponCreationForm.php @@ -0,0 +1,168 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Allow to build a form Coupon + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponCreationForm extends BaseForm +{ + /** + * Build Coupon form + * + * @return void + */ + protected function buildForm() + { + $this->formBuilder + ->add( + "code", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "type", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "title", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "shortDescription", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "description", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "amount", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "isEnabled", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "expirationDate", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "isCumulative", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "isRemovingPostage", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "maxUsage", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add( + "isAvailableOnSpecialOffers", + "text", + array( + "constraints" => array( + new NotBlank() + ) + ) + ); + } + + /** + * Get form name + * + * @return string + */ + public function getName() + { + return "thelia_coupon_creation"; + } +} diff --git a/core/lib/Thelia/Model/Category.php b/core/lib/Thelia/Model/Category.php index 88e7cfc10..2ffd375dd 100755 --- a/core/lib/Thelia/Model/Category.php +++ b/core/lib/Thelia/Model/Category.php @@ -48,7 +48,7 @@ class Category extends BaseCategory ->findOne() ; - return $last->getPosition() + 1; + return $last != null ? $last->getPosition() + 1 : 1; } /** @@ -74,6 +74,4 @@ class Category extends BaseCategory return $countProduct; } - - -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index d135ccbb0..9718b5e36 100755 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -1,9 +1,77 @@ . */ +/* */ +/**********************************************************************************/ namespace Thelia\Model; +use Thelia\Coupon\CouponRuleCollection; use Thelia\Model\Base\Coupon as BaseCoupon; -class Coupon extends BaseCoupon { +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Used to provide an effect (mostly a discount) + * at the end of the Customer checkout tunnel + * It will be usable for a Customer only if it matches the Coupon criteria (Rules) + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class Coupon extends BaseCoupon +{ + /** + * Set the value of [serialized_rules] column. + * + * @param CouponRuleCollection $rules A set of Rules + * + * @return \Thelia\Model\Coupon The current object (for fluent API support) + */ + public function setSerializedRules(CouponRuleCollection $rules) + { + if ($rules !== null) { + $v = (string) base64_encode(serialize($rules)); + } + + if ($this->serialized_rules !== $v) { + $this->serialized_rules = $v; + $this->modifiedColumns[] = CouponTableMap::SERIALIZED_RULES; + } + + + return $this; + } // setSerializedRules() + + + /** + * Get the [serialized_rules] column value. + * + * @return CouponRuleCollection Rules ready to be processed + */ + public function getSerializedRules() + { + return unserialize(base64_decode($this->serialized_rules)); + } } diff --git a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php index e9323ebfa..3913b2890 100755 --- a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php +++ b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php @@ -6,6 +6,7 @@ use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; use Propel\Runtime\ActiveQuery\ModelCriteria; use Thelia\Model\Base\LangQuery; +use Thelia\Model\ConfigQuery; /** * Class ModelCriteriaTools @@ -17,13 +18,12 @@ class ModelCriteriaTools { /** * @param ModelCriteria $search - * @param $defaultLangWithoutTranslation - * @param $askedLocale + * @param $requestedLocale * @param array $columns * @param null $foreignTable * @param string $foreignKey */ - public static function getFrontEndI18n(ModelCriteria &$search, $defaultLangWithoutTranslation, $askedLocale, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') + public static function getFrontEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey) { if($foreignTable === null) { $foreignTable = $search->getTableMap()->getName(); @@ -32,21 +32,24 @@ class ModelCriteriaTools $aliasPrefix = $foreignTable . '_'; } - $askedLocaleI18nAlias = 'asked_locale_i18n'; + $defaultLangWithoutTranslation = ConfigQuery::read("default_lang_without_translation", 1); + + $requestedLocaleI18nAlias = 'requested_locale_i18n'; $defaultLocaleI18nAlias = 'default_locale_i18n'; - if($defaultLangWithoutTranslation == 0) { - $askedLocaleJoin = new Join(); - $askedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $askedLocaleI18nAlias); - $askedLocaleJoin->setJoinType(Criteria::INNER_JOIN); + if (!$defaultLangWithoutTranslation == 0) { - $search->addJoinObject($askedLocaleJoin, $askedLocaleI18nAlias) - ->addJoinCondition($askedLocaleI18nAlias ,'`' . $askedLocaleI18nAlias . '`.LOCALE = ?', $askedLocale, null, \PDO::PARAM_STR); + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $requestedLocaleI18nAlias); + $requestedLocaleJoin->setJoinType(Criteria::INNER_JOIN); - $search->withColumn('NOT ISNULL(`' . $askedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition($requestedLocaleI18nAlias ,'`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', $requestedLocale, null, \PDO::PARAM_STR); + + $search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); foreach($columns as $column) { - $search->withColumn('`' . $askedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); + $search->withColumn('`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); } } else { $defaultLocale = LangQuery::create()->findOneById($defaultLangWithoutTranslation)->getLocale(); @@ -58,24 +61,24 @@ class ModelCriteriaTools $search->addJoinObject($defaultLocaleJoin, $defaultLocaleI18nAlias) ->addJoinCondition($defaultLocaleI18nAlias ,'`' . $defaultLocaleI18nAlias . '`.LOCALE = ?', $defaultLocale, null, \PDO::PARAM_STR); - $askedLocaleJoin = new Join(); - $askedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $askedLocaleI18nAlias); - $askedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $requestedLocaleI18nAlias); + $requestedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); - $search->addJoinObject($askedLocaleJoin, $askedLocaleI18nAlias) - ->addJoinCondition($askedLocaleI18nAlias ,'`' . $askedLocaleI18nAlias . '`.LOCALE = ?', $askedLocale, null, \PDO::PARAM_STR); + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition($requestedLocaleI18nAlias ,'`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', $requestedLocale, null, \PDO::PARAM_STR); - $search->withColumn('NOT ISNULL(`' . $askedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); + $search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); - $search->where('NOT ISNULL(`' . $askedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)'); + $search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)'); foreach($columns as $column) { - $search->withColumn('CASE WHEN NOT ISNULL(`' . $askedLocaleI18nAlias . '`.ID) THEN `' . $askedLocaleI18nAlias . '`.`' . $column . '` ELSE `' . $defaultLocaleI18nAlias . '`.`' . $column . '` END', $aliasPrefix . 'i18n_' . $column); + $search->withColumn('CASE WHEN NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID) THEN `' . $requestedLocaleI18nAlias . '`.`' . $column . '` ELSE `' . $defaultLocaleI18nAlias . '`.`' . $column . '` END', $aliasPrefix . 'i18n_' . $column); } } } - public static function getBackEndI18n(ModelCriteria &$search, $askedLocale, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') + public static function getBackEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey) { if($foreignTable === null) { $foreignTable = $search->getTableMap()->getName(); @@ -84,35 +87,44 @@ class ModelCriteriaTools $aliasPrefix = $foreignTable . '_'; } - $askedLocaleI18nAlias = 'asked_locale_i18n'; + $requestedLocaleI18nAlias = 'requested_locale_i18n'; - $askedLocaleJoin = new Join(); - $askedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $askedLocaleI18nAlias); - $askedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $requestedLocaleI18nAlias); + $requestedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); - $search->addJoinObject($askedLocaleJoin, $askedLocaleI18nAlias) - ->addJoinCondition($askedLocaleI18nAlias ,'`' . $askedLocaleI18nAlias . '`.LOCALE = ?', $askedLocale, null, \PDO::PARAM_STR); + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition($requestedLocaleI18nAlias ,'`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', $requestedLocale, null, \PDO::PARAM_STR); - $search->withColumn('NOT ISNULL(`' . $askedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); + $search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); foreach($columns as $column) { - $search->withColumn('`' . $askedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); + $search->withColumn('`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); } } - public static function getI18n($backendContext, $lang, ModelCriteria &$search, $defaultLangWithoutTranslation, $currentLocale, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') + public static function getI18n($backendContext, $requestedLangId, ModelCriteria &$search, $currentLocale, $columns, $foreignTable, $foreignKey) { - if($lang !== null) { - $localeSearch = LangQuery::create()->findOneById($lang); - if($localeSearch === null) { - throw new \InvalidArgumentException('Incorrect lang argument given in attribute loop'); + // If a lang has been requested, find the related Lang object, and get the locale + if ($requestedLangId !== null) { + $localeSearch = LangQuery::create()->findOneById($requestedLangId); + + if ($localeSearch === null) { + throw new \InvalidArgumentException(sprintf('Incorrect lang argument given in attribute loop: lang ID %d not found', $requestedLangId)); } + + $locale = $localeSearch->getLocale(); + } + else { + // Use the currently defined locale + $locale = $currentLocale; } - if($backendContext) { - self::getBackEndI18n($search, $lang === null ? $currentLocale : $localeSearch->getLocale(), $columns, $foreignTable, $foreignKey); + // Call the proper method depending on the context: front or back + if ($backendContext) { + self::getBackEndI18n($search, $locale, $columns, $foreignTable, $foreignKey); } else { - self::getFrontEndI18n($search, $defaultLangWithoutTranslation, $lang === null ? $currentLocale : $localeSearch->getLocale(), $columns, $foreignTable, $foreignKey); + self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey); } } } diff --git a/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php new file mode 100644 index 000000000..2cdec7846 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php @@ -0,0 +1,161 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\CustomerParam; +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\QuantityParam; +use Thelia\Model\Customer; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CustomerParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class CustomerParamTest extends \PHPUnit_Framework_TestCase +{ + + /** @var CouponAdapterInterface $stubTheliaAdapter */ + protected $stubTheliaAdapter = null; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + /** @var CouponAdapterInterface $stubTheliaAdapter */ + $this->stubTheliaAdapter = $this->generateValidCouponBaseAdapterMock(); + } + + /** + * Generate valid CouponBaseAdapter + * + * @param int $customerId Customer id + * + * @return CouponAdapterInterface + */ + protected function generateValidCouponBaseAdapterMock($customerId = 4521) + { + $customer = new Customer(); + $customer->setId($customerId); + $customer->setFirstname('Firstname'); + $customer->setLastname('Lastname'); + $customer->setEmail('em@il.com'); + + /** @var CouponAdapterInterface $stubTheliaAdapter */ + $stubTheliaAdapter = $this->getMock( + 'Thelia\Coupon\CouponBaseAdapter', + array('getCustomer'), + array() + ); + $stubTheliaAdapter->expects($this->any()) + ->method('getCustomer') + ->will($this->returnValue($customer)); + + return $stubTheliaAdapter; + } + + /** + * + * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo + * + */ + public function testCanUseCoupon() + { + $customerId = 4521; + $couponValidForCustomerId = 4521; + + $adapter = $this->generateValidCouponBaseAdapterMock($customerId); + + $customerParam = new CustomerParam($adapter, $couponValidForCustomerId); + + $expected = 0; + $actual = $customerParam->compareTo($customerId); + $this->assertEquals($expected, $actual); + } + +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testCanNotUseCouponTest() +// { +// +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * @expectedException InvalidArgumentException +// * +// */ +// public function testCanNotUseCouponCustomerNotFoundTest() +// { +// +// } + + + + +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = -1; +// +// $param = new QuantityParam($adapter, $intValidator); +// +// $serialized = base64_encode(serialize($param)); +// /** @var QuantityParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getInteger(), $unserialized->getInteger()); +// +// $new = new QuantityParam($adapter, $unserialized->getInteger()); +// $this->assertEquals($param->getInteger(), $new->getInteger()); +// } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/install/sqldb.map b/install/sqldb.map deleted file mode 100644 index 63a93baa8..000000000 --- a/install/sqldb.map +++ /dev/null @@ -1,2 +0,0 @@ -# Sqlfile -> Database map -thelia.sql=thelia diff --git a/templates/admin/default/assets/bootstrap-editable/css/bootstrap-editable.css b/templates/admin/default/assets/bootstrap-editable/css/bootstrap-editable.css index faebd0543..92063da35 100755 --- a/templates/admin/default/assets/bootstrap-editable/css/bootstrap-editable.css +++ b/templates/admin/default/assets/bootstrap-editable/css/bootstrap-editable.css @@ -1,4 +1,4 @@ -/*! X-editable - v1.4.6 +/*! X-editable - v1.4.6 * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery * http://github.com/vitalets/x-editable * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ @@ -18,45 +18,45 @@ vertical-align: top; margin-left: 7px; /* inline-block emulation for IE7*/ - zoom: 1; + zoom: 1; *display: inline; } .editable-buttons.editable-buttons-bottom { - display: block; + display: block; margin-top: 7px; margin-left: 0; } .editable-input { - vertical-align: top; + vertical-align: top; display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ white-space: normal; /* reset white-space decalred in parent*/ /* display-inline emulation for IE7*/ - zoom: 1; - *display: inline; + zoom: 1; + *display: inline; } .editable-buttons .editable-cancel { - margin-left: 7px; + margin-left: 7px; } /*for jquery-ui buttons need set height to look more pretty*/ .editable-buttons button.ui-button-icon-only { - height: 24px; + height: 24px; width: 30px; } .editableform-loading { - background: url('../img/loading.gif') center center no-repeat; + background: url('../img/loading.gif') center center no-repeat; height: 25px; - width: auto; - min-width: 25px; + width: auto; + min-width: 25px; } .editable-inline .editableform-loading { - background-position: left 5px; + background-position: left 5px; } .editable-error-block { @@ -68,17 +68,17 @@ /*add padding for jquery ui*/ .editable-error-block.ui-state-error { - padding: 3px; -} + padding: 3px; +} .editable-error { - color: red; + color: red; } /* ---- For specific types ---- */ .editableform .editable-date { - padding: 0; + padding: 0; margin: 0; float: left; } @@ -86,25 +86,25 @@ /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */ .editable-inline .add-on .icon-th { margin-top: 3px; - margin-left: 1px; + margin-left: 1px; } /* checklist vertical alignment */ -.editable-checklist label input[type="checkbox"], +.editable-checklist label input[type="checkbox"], .editable-checklist label span { vertical-align: middle; margin: 0; } .editable-checklist label { - white-space: nowrap; + white-space: nowrap; } /* set exact width of textarea to fit buttons toolbar */ .editable-wysihtml5 { - width: 566px; - height: 250px; + width: 566px; + height: 250px; } /* clear button shown as link in date inputs */ @@ -119,16 +119,16 @@ .editable-clear-x { background: url('../img/clear.png') center center no-repeat; display: block; - width: 13px; + width: 13px; height: 13px; position: absolute; opacity: 0.6; z-index: 100; - + top: 50%; right: 6px; margin-top: -6px; - + } .editable-clear-x:hover { @@ -140,49 +140,49 @@ } .editable-container.editable-popup { max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ -} +} .editable-container.popover { width: auto; /* without this rule popover does not stretch */ } .editable-container.editable-inline { - display: inline-block; + display: inline-block; vertical-align: middle; width: auto; /* inline-block emulation for IE7*/ - zoom: 1; - *display: inline; + zoom: 1; + *display: inline; } .editable-container.ui-widget { font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */ } -.editable-click, -a.editable-click, +.editable-click, +a.editable-click, a.editable-click:hover { text-decoration: none; - border-bottom: dashed 1px #0088cc; + border-bottom: dotted 1px #0088cc; } -.editable-click.editable-disabled, -a.editable-click.editable-disabled, +.editable-click.editable-disabled, +a.editable-click.editable-disabled, a.editable-click.editable-disabled:hover { - color: #585858; + color: #585858; cursor: default; border-bottom: none; } .editable-empty, .editable-empty:hover, .editable-empty:focus{ - font-style: italic; - color: #DD1144; + font-style: italic; + color: #DD1144; /* border-bottom: none; */ text-decoration: none; } .editable-unsaved { - font-weight: bold; + font-weight: bold; } .editable-unsaved:after { @@ -194,12 +194,463 @@ a.editable-click.editable-disabled:hover { -moz-transition: background-color 1400ms ease-out; -o-transition: background-color 1400ms ease-out; -ms-transition: background-color 1400ms ease-out; - transition: background-color 1400ms ease-out; + transition: background-color 1400ms ease-out; } /*see https://github.com/vitalets/x-editable/issues/139 */ .form-horizontal .editable -{ +{ padding-top: 5px; display:inline-block; -} \ No newline at end of file +} + + +/*! + * Datepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.datepicker { + padding: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ + +} +.datepicker-inline { + width: 220px; +} +.datepicker.datepicker-rtl { + direction: rtl; +} +.datepicker.datepicker-rtl table tr td span { + float: right; +} +.datepicker-dropdown { + top: 0; + left: 0; +} +.datepicker-dropdown:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.datepicker-dropdown:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.datepicker > div { + display: none; +} +.datepicker.days div.datepicker-days { + display: block; +} +.datepicker.months div.datepicker-months { + display: block; +} +.datepicker.years div.datepicker-years { + display: block; +} +.datepicker table { + margin: 0; +} +.datepicker td, +.datepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} +.table-striped .datepicker table tr td, +.table-striped .datepicker table tr th { + background-color: transparent; +} +.datepicker table tr td.day:hover { + background: #eeeeee; + cursor: pointer; +} +.datepicker table tr td.old, +.datepicker table tr td.new { + color: #999999; +} +.datepicker table tr td.disabled, +.datepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td.today, +.datepicker table tr td.today:hover, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #000; +} +.datepicker table tr td.today:hover, +.datepicker table tr td.today:hover:hover, +.datepicker table tr td.today.disabled:hover, +.datepicker table tr td.today.disabled:hover:hover, +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today:hover.disabled, +.datepicker table tr td.today.disabled.disabled, +.datepicker table tr td.today.disabled:hover.disabled, +.datepicker table tr td.today[disabled], +.datepicker table tr td.today:hover[disabled], +.datepicker table tr td.today.disabled[disabled], +.datepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datepicker table tr td.today:hover:hover { + color: #000; +} +.datepicker table tr td.today.active:hover { + color: #fff; +} +.datepicker table tr td.range, +.datepicker table tr td.range:hover, +.datepicker table tr td.range.disabled, +.datepicker table tr td.range.disabled:hover { + background: #eeeeee; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today, +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today.disabled:hover { + background-color: #f3d17a; + background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a)); + background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -o-linear-gradient(top, #f3c17a, #f3e97a); + background-image: linear-gradient(top, #f3c17a, #f3e97a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0); + border-color: #f3e97a #f3e97a #edde34; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today:hover:hover, +.datepicker table tr td.range.today.disabled:hover, +.datepicker table tr td.range.today.disabled:hover:hover, +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today:hover.disabled, +.datepicker table tr td.range.today.disabled.disabled, +.datepicker table tr td.range.today.disabled:hover.disabled, +.datepicker table tr td.range.today[disabled], +.datepicker table tr td.range.today:hover[disabled], +.datepicker table tr td.range.today.disabled[disabled], +.datepicker table tr td.range.today.disabled:hover[disabled] { + background-color: #f3e97a; +} +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active { + background-color: #efe24b \9; +} +.datepicker table tr td.selected, +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected.disabled:hover { + background-color: #9e9e9e; + background-image: -moz-linear-gradient(top, #b3b3b3, #808080); + background-image: -ms-linear-gradient(top, #b3b3b3, #808080); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080)); + background-image: -webkit-linear-gradient(top, #b3b3b3, #808080); + background-image: -o-linear-gradient(top, #b3b3b3, #808080); + background-image: linear-gradient(top, #b3b3b3, #808080); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0); + border-color: #808080 #808080 #595959; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected:hover:hover, +.datepicker table tr td.selected.disabled:hover, +.datepicker table tr td.selected.disabled:hover:hover, +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected:hover.disabled, +.datepicker table tr td.selected.disabled.disabled, +.datepicker table tr td.selected.disabled:hover.disabled, +.datepicker table tr td.selected[disabled], +.datepicker table tr td.selected:hover[disabled], +.datepicker table tr td.selected.disabled[disabled], +.datepicker table tr td.selected.disabled:hover[disabled] { + background-color: #808080; +} +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active { + background-color: #666666 \9; +} +.datepicker table tr td.active, +.datepicker table tr td.active:hover, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.active:hover, +.datepicker table tr td.active:hover:hover, +.datepicker table tr td.active.disabled:hover, +.datepicker table tr td.active.disabled:hover:hover, +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active:hover.disabled, +.datepicker table tr td.active.disabled.disabled, +.datepicker table tr td.active.disabled:hover.disabled, +.datepicker table tr td.active[disabled], +.datepicker table tr td.active:hover[disabled], +.datepicker table tr td.active.disabled[disabled], +.datepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datepicker table tr td span:hover { + background: #eeeeee; +} +.datepicker table tr td span.disabled, +.datepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td span.active, +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active:hover:hover, +.datepicker table tr td span.active.disabled:hover, +.datepicker table tr td span.active.disabled:hover:hover, +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active:hover.disabled, +.datepicker table tr td span.active.disabled.disabled, +.datepicker table tr td span.active.disabled:hover.disabled, +.datepicker table tr td span.active[disabled], +.datepicker table tr td span.active:hover[disabled], +.datepicker table tr td span.active.disabled[disabled], +.datepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span.old, +.datepicker table tr td span.new { + color: #999999; +} +.datepicker th.datepicker-switch { + width: 145px; +} +.datepicker thead tr:first-child th, +.datepicker tfoot tr th { + cursor: pointer; +} +.datepicker thead tr:first-child th:hover, +.datepicker tfoot tr th:hover { + background: #eeeeee; +} +.datepicker .cw { + font-size: 10px; + width: 12px; + padding: 0 2px 0 5px; + vertical-align: middle; +} +.datepicker thead tr:first-child th.cw { + cursor: default; + background-color: transparent; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + display: block; + cursor: pointer; + width: 16px; + height: 16px; +} +.input-daterange input { + text-align: center; +} +.input-daterange input:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-daterange input:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-daterange .add-on { + display: inline-block; + width: auto; + min-width: 16px; + height: 18px; + padding: 4px 5px; + font-weight: normal; + line-height: 18px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #eeeeee; + border: 1px solid #ccc; + margin-left: -5px; + margin-right: -5px; +} diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index e2ef57293..ef52b73e7 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -1,31 +1,31 @@ // -- Tools -------------------------------------------------------------------- .rounded(@radius: 2px) { - -webkit-border-radius: @radius; - -moz-border-radius: @radius; - border-radius: @radius; + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; } .border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) { - -webkit-border-top-right-radius: @topright; - -webkit-border-bottom-right-radius: @bottomright; - -webkit-border-bottom-left-radius: @bottomleft; - -webkit-border-top-left-radius: @topleft; - -moz-border-radius-topright: @topright; - -moz-border-radius-bottomright: @bottomright; - -moz-border-radius-bottomleft: @bottomleft; - -moz-border-radius-topleft: @topleft; - border-top-right-radius: @topright; - border-bottom-right-radius: @bottomright; - border-bottom-left-radius: @bottomleft; - border-top-left-radius: @topleft; - .background-clip(padding-box); + -webkit-border-top-right-radius: @topright; + -webkit-border-bottom-right-radius: @bottomright; + -webkit-border-bottom-left-radius: @bottomleft; + -webkit-border-top-left-radius: @topleft; + -moz-border-radius-topright: @topright; + -moz-border-radius-bottomright: @bottomright; + -moz-border-radius-bottomleft: @bottomleft; + -moz-border-radius-topleft: @topleft; + border-top-right-radius: @topright; + border-bottom-right-radius: @bottomright; + border-bottom-left-radius: @bottomleft; + border-top-left-radius: @topleft; + .background-clip(padding-box); } .background-clip(@argument: padding-box) { - -moz-background-clip: @argument; - -webkit-background-clip: @argument; - background-clip: @argument; + -moz-background-clip: @argument; + -webkit-background-clip: @argument; + background-clip: @argument; } .box-shadow(@shadow: 0 1px 2px rgba(0,0,0,.05)) { @@ -158,13 +158,41 @@ hr { } .btn-primary, .btn-large { +<<<<<<< HEAD #gradient > .vertical(rgb(243,153,34), rgb(227,83,11)); +======= + background: #e9730f; + background-image: linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -o-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -moz-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -webkit-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -ms-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, rgb(227,83,11)), + color-stop(1, rgb(243,153,34)) + ); +>>>>>>> 180302e7cce643db7cda695b5cfaec3586ebb72c box-shadow: inset 0px 0px 2px rgba(250,250,250,0.5), 0px 1px 3px rgba(0,0,0,0.2); color: white; } .btn-large:hover, .btn-primary:hover { - #gradient > .vertical(rgb(243,153,34), rgb(227,83,11)); + background: #e9730f; + background-image: linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -o-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -moz-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -webkit-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -ms-linear-gradient(bottom, rgb(227,83,11) 0%, rgb(243,153,34) 100%); + background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, rgb(227,83,11)), + color-stop(1, rgb(243,153,34)) + ); box-shadow: inset 0px 0px 2px rgba(250,250,250,0.8), 0px 1px 3px rgba(0,0,0,0.2); color: white; } @@ -762,6 +790,7 @@ label { // Center the alert box (20px bottom margin) in the table cell padding: 20px 20px 0 20px; } +<<<<<<< HEAD } // -- Editable tweaks --------------------------------------------------------- @@ -889,3 +918,6 @@ label { } +======= +} +>>>>>>> 180302e7cce643db7cda695b5cfaec3586ebb72c diff --git a/templates/admin/default/includes/category_breadcrumb.html b/templates/admin/default/includes/category_breadcrumb.html index 0870a4c2e..cf03c4082 100755 --- a/templates/admin/default/includes/category_breadcrumb.html +++ b/templates/admin/default/includes/category_breadcrumb.html @@ -12,11 +12,11 @@ {if $action == 'edit'} {intl l='Editing %cat' cat="{$TITLE}"} {else} - {$TITLE} {intl l="(edit)"} + {$TITLE} {intl l="(edit)"} {/if} {else} -
  • {$TITLE} /
  • +
  • {$TITLE} /
  • {/if} {/loop} {/ifloop} diff --git a/templates/admin/default/includes/inner-form-toolbar.html b/templates/admin/default/includes/inner-form-toolbar.html index 8d6f65cc8..4d5570f6c 100755 --- a/templates/admin/default/includes/inner-form-toolbar.html +++ b/templates/admin/default/includes/inner-form-toolbar.html @@ -12,7 +12,7 @@