diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php index 2bbfce8a8..15940082a 100644 --- a/core/lib/Thelia/Action/Administrator.php +++ b/core/lib/Thelia/Action/Administrator.php @@ -25,6 +25,7 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\Administrator\AdministratorEvent; +use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Model\Admin as AdminModel; use Thelia\Model\AdminQuery; @@ -92,15 +93,23 @@ class Administrator extends BaseAction implements EventSubscriberInterface } } + public function updatePassword(AdministratorUpdatePasswordEvent $event) + { + $admin = $event->getAdmin(); + $admin->setPassword($event->getPassword()) + ->save(); + } + /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( - TheliaEvents::ADMINISTRATOR_CREATE => array("create", 128), - TheliaEvents::ADMINISTRATOR_UPDATE => array("update", 128), - TheliaEvents::ADMINISTRATOR_DELETE => array("delete", 128), + TheliaEvents::ADMINISTRATOR_CREATE => array('create', 128), + TheliaEvents::ADMINISTRATOR_UPDATE => array('update', 128), + TheliaEvents::ADMINISTRATOR_DELETE => array('delete', 128), + TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD => array('updatePassword', 128) ); } } diff --git a/core/lib/Thelia/Action/Attribute.php b/core/lib/Thelia/Action/Attribute.php index 7db04518a..30ceea0e8 100644 --- a/core/lib/Thelia/Action/Attribute.php +++ b/core/lib/Thelia/Action/Attribute.php @@ -63,7 +63,7 @@ class Attribute extends BaseAction implements EventSubscriberInterface // Add atribute to all product templates if required if ($event->getAddToAllTemplates() != 0) { - // TODO: add to all product template + $this->doAddToAllTemplates($attribute); } } diff --git a/core/lib/Thelia/Action/Feature.php b/core/lib/Thelia/Action/Feature.php index 6ae7645e3..36853f444 100644 --- a/core/lib/Thelia/Action/Feature.php +++ b/core/lib/Thelia/Action/Feature.php @@ -63,7 +63,7 @@ class Feature extends BaseAction implements EventSubscriberInterface // Add atribute to all product templates if required if ($event->getAddToAllTemplates() != 0) { - // TODO: add to all product template + $this->doAddToAllTemplates($feature); } } diff --git a/core/lib/Thelia/Action/ProductSaleElement.php b/core/lib/Thelia/Action/ProductSaleElement.php index 8349eb1bf..9c40025d8 100644 --- a/core/lib/Thelia/Action/ProductSaleElement.php +++ b/core/lib/Thelia/Action/ProductSaleElement.php @@ -40,6 +40,8 @@ use Thelia\Model\AttributeAvQuery; use Thelia\Model\Currency; use Thelia\Model\Map\AttributeCombinationTableMap; use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; +use Propel\Runtime\Connection\ConnectionInterface; class ProductSaleElement extends BaseAction implements EventSubscriberInterface { @@ -65,7 +67,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface if ($salesElement == null) { // Create a new default product sale element - $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true); + $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true); } else { // This (new) one is the default $salesElement->setIsDefault(true)->save($con); @@ -87,7 +89,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface ->setAttributeAvId($attributeAvId) ->setAttribute($attributeAv->getAttribute()) ->setProductSaleElements($salesElement) - ->save(); + ->save($con); } } } @@ -206,8 +208,9 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface if ($product->countSaleElements() <= 0) { // If we just deleted the last PSE, create a default one - $product->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true); - } elseif ($pse->getIsDefault()) { + $product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true); + } + elseif ($pse->getIsDefault()) { // If we deleted the default PSE, make the last created one the default $pse = ProductSaleElementsQuery::create() @@ -230,6 +233,83 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface } } + /** + * Generate combinations. All existing combinations for the product are deleted. + * + * @param ProductCombinationGenerationEvent $event + */ + public function generateCombinations(ProductCombinationGenerationEvent $event) { + + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + + // Delete all product's productSaleElement + ProductSaleElementsQuery::create()->filterByProductId($event->product->getId())->delete(); + + $isDefault = true; + + // Create all combinations + foreach($event->getCombinations() as $combinationAttributesAvIds) { + + // Create the PSE + $saleElement = $event->getProduct()->createProductSaleElement( + $con, + $event->getWeight(), + $event->getPrice(), + $event->getSalePrice(), + $event->getCurrencyId(), + $isDefault, + $event->getOnsale(), + $event->getIsnew(), + $event->getQuantity(), + $event->getEanCode(), + $event->getReference() + ); + + $isDefault = false; + + $this->createCombination($con, $saleElement, $combinationAttributesAvIds); + } + + // Store all the stuff ! + $con->commit(); + } + catch (\Exception $ex) { + + $con->rollback(); + + throw $ex; + } + } + + /** + * Create a combination for a given product sale element + * + * @param ConnectionInterface $con the Propel connection + * @param ProductSaleElement $salesElement the product sale element + * @param unknown $combinationAttributes an array oif attributes av IDs + */ + protected function createCombination(ConnectionInterface $con, ProductSaleElements $salesElement, $combinationAttributes) + { + foreach ($combinationAttributes as $attributeAvId) { + + $attributeAv = AttributeAvQuery::create()->findPk($attributeAvId); + + if ($attributeAv !== null) { + $attributeCombination = new AttributeCombination(); + + $attributeCombination + ->setAttributeAvId($attributeAvId) + ->setAttribute($attributeAv->getAttribute()) + ->setProductSaleElements($salesElement) + ->save($con); + } + } + } + /** * {@inheritDoc} */ @@ -239,6 +319,8 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT => array("create", 128), TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => array("update", 128), TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT => array("delete", 128), + TheliaEvents::PRODUCT_COMBINATION_GENERATION => array("generateCombinations", 128), + ); } } diff --git a/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php new file mode 100644 index 000000000..cab25d13f --- /dev/null +++ b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php @@ -0,0 +1,102 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Command; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\AdminQuery; +use Thelia\Tools\Password; + + +/** + * command line for updating admin password + * + * php Thelia admin:updatePassword + * + * Class AdminUpdatePasswordCommand + * @package Thelia\Command + * @author Manuel Raynaud + */ +class AdminUpdatePasswordCommand extends ContainerAwareCommand +{ + + /** + * Configures the current command. + */ + protected function configure() + { + $this + ->setName('admin:updatePassword') + ->setDescription('change administrator password') + ->setHelp('The admin:updatePassword command allows you to change the password for a given administrator') + ->addArgument( + 'login', + InputArgument::REQUIRED, + 'Login for administrator you want to change the password' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'Desired password. If this option is omitted, a random password is generated and shown in this prompt after' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $login = $input->getArgument('login'); + + + if (null === $admin = AdminQuery::create()->filterByLogin($login)->findOne()) { + throw new \RuntimeException(sprintf('Admin with login %s does not exists', $login)); + } + + + $password = $input->getOption('password') ?: Password::generateRandom(); + + $event = new AdministratorUpdatePasswordEvent($admin); + $event->setPassword($password); + + + $this-> + getContainer() + ->get('event_dispatcher') + ->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event); + + $output->writeln(array( + '', + sprintf('admin %s password updated', $login), + sprintf('new password is : %s', $password), + '' + )); + + } + +} + diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index 857790141..988122e7a 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -38,9 +38,9 @@ class CreateAdminUser extends ContainerAwareCommand protected function configure() { $this - ->setName("thelia:create-admin") - ->setDescription("Create a new adminsitration user") - ->setHelp("The thelia:create-admin command create a new administration user.") + ->setName("admin:create") + ->setDescription("Create a new administrator user") + ->setHelp("The admin:create command create a new administration user.") ->addOption( 'login_name', null, diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index c0af99896..0cf616126 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -90,6 +90,8 @@
+ + @@ -182,6 +184,7 @@ + @@ -208,7 +211,7 @@ - + null diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index e051fb3e5..03ec1856d 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -384,6 +384,10 @@ Thelia\Controller\Admin\ProductController::updateProductSaleElementsAction + + Thelia\Controller\Admin\ProductController::buildCombinationsAction + + Thelia\Controller\Admin\ProductController::updateProductDefaultSaleElementAction diff --git a/core/lib/Thelia/Controller/Admin/AttributeController.php b/core/lib/Thelia/Controller/Admin/AttributeController.php index 00162ffcf..9644d6651 100644 --- a/core/lib/Thelia/Controller/Admin/AttributeController.php +++ b/core/lib/Thelia/Controller/Admin/AttributeController.php @@ -157,23 +157,6 @@ class AttributeController extends AbstractCrudController 'postscriptum' => $object->getPostscriptum() ); - // Setup attributes values - /* - * FIXME : doesn't work. "We get a This form should not contain extra fields." error - $attr_av_list = AttributeAvQuery::create() - ->joinWithI18n($this->getCurrentEditionLocale()) - ->filterByAttributeId($object->getId()) - ->find(); - - $attr_array = array(); - - foreach ($attr_av_list as $attr_av) { - $attr_array[$attr_av->getId()] = $attr_av->getTitle(); - } - - $data['attribute_values'] = $attr_array; - */ - // Setup the object form return new AttributeModificationForm($this->getRequest(), "form", $data); } diff --git a/core/lib/Thelia/Controller/Admin/FeatureController.php b/core/lib/Thelia/Controller/Admin/FeatureController.php index 7696b9c6e..1be5dfeec 100644 --- a/core/lib/Thelia/Controller/Admin/FeatureController.php +++ b/core/lib/Thelia/Controller/Admin/FeatureController.php @@ -157,23 +157,6 @@ class FeatureController extends AbstractCrudController 'postscriptum' => $object->getPostscriptum() ); - // Setup features values - /* - * FIXME : doesn't work. "We get a This form should not contain extra fields." error - $attr_av_list = FeatureAvQuery::create() - ->joinWithI18n($this->getCurrentEditionLocale()) - ->filterByFeatureId($object->getId()) - ->find(); - - $attr_array = array(); - - foreach ($attr_av_list as $attr_av) { - $attr_array[$attr_av->getId()] = $attr_av->getTitle(); - } - - $data['feature_values'] = $attr_array; - */ - // Setup the object form return new FeatureModificationForm($this->getRequest(), "form", $data); } diff --git a/core/lib/Thelia/Controller/Admin/FileController.php b/core/lib/Thelia/Controller/Admin/FileController.php index 38b8d74fb..ced780181 100755 --- a/core/lib/Thelia/Controller/Admin/FileController.php +++ b/core/lib/Thelia/Controller/Admin/FileController.php @@ -136,9 +136,9 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Saving images for %parentName% parent id %parentId% (%parentType%)', array( - '%parentName%' => $event->getParentName(), - '%parentId%' => $event->getParentId(), - '%parentType%' => $event->getImageType() + '%parentName%' => $imageCreateOrUpdateEvent->getParentName(), + '%parentId%' => $imageCreateOrUpdateEvent->getParentId(), + '%parentType%' => $imageCreateOrUpdateEvent->getImageType() ), 'image' ) @@ -214,9 +214,9 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Saving documents for %parentName% parent id %parentId% (%parentType%)', array( - '%parentName%' => $event->getParentName(), - '%parentId%' => $event->getParentId(), - '%parentType%' => $event->getDocumentType() + '%parentName%' => $documentCreateOrUpdateEvent->getParentName(), + '%parentId%' => $documentCreateOrUpdateEvent->getParentId(), + '%parentType%' => $documentCreateOrUpdateEvent->getDocumentType() ), 'document' ) @@ -549,8 +549,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Deleting image for %id% with parent id %parentId%', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $imageDeleteEvent->getImageToDelete()->getId(), + '%parentId%' => $imageDeleteEvent->getImageToDelete()->getParentId(), ), 'image' ) @@ -562,8 +562,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Fail to delete image for %id% with parent id %parentId% (Exception : %e%)', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $imageDeleteEvent->getImageToDelete()->getId(), + '%parentId%' => $imageDeleteEvent->getImageToDelete()->getParentId(), '%e%' => $e->getMessage() ), 'image' @@ -621,8 +621,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Deleting document for %id% with parent id %parentId%', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $documentDeleteEvent->getDocumentToDelete()->getId(), + '%parentId%' => $documentDeleteEvent->getDocumentToDelete()->getParentId(), ), 'document' ) @@ -634,8 +634,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Fail to delete document for %id% with parent id %parentId% (Exception : %e%)', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $documentDeleteEvent->getDocumentToDelete()->getId(), + '%parentId%' => $documentDeleteEvent->getDocumentToDelete()->getParentId(), '%e%' => $e->getMessage() ), 'document' diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php index 88baf75f7..1279dbff7 100644 --- a/core/lib/Thelia/Controller/Admin/ProductController.php +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -64,6 +64,8 @@ use Thelia\Model\Country; use Thelia\Tools\NumberFormat; use Thelia\Model\Product; use Thelia\Model\CurrencyQuery; +use Thelia\Form\ProductCombinationGenerationForm; +use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; /** * Manages products @@ -1025,6 +1027,108 @@ class ProductController extends AbstractCrudController ); } + // Create combinations + protected function combine($input, &$output, &$tmp) { + $current = array_shift($input); + + if (count($input) > 0) { + foreach($current as $element) { + $tmp[] = $element; + $this->combine($input, $output, $tmp); + array_pop($tmp); + } + } else { + foreach($current as $element) { + $tmp[] = $element; + $output[] = $tmp; + array_pop($tmp); + } + } + } + + /** + * Build combinations from the combination output builder + */ + public function buildCombinationsAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, AccessManager::UPDATE)) return $response; + + $error_msg = false; + + $changeForm = new ProductCombinationGenerationForm($this->getRequest()); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Rework attributes_av array, to build an array which contains all combinations, + // in the form combination[] = array of combination attributes av IDs + // + // First, create an array of attributes_av ID in the form $attributes_av_list[$attribute_id] = array of attributes_av ID + // from the list of attribute_id:attributes_av ID from the form. + $combinations = $attributes_av_list = array(); + + foreach($data['attribute_av'] as $item) { + list($attribute_id, $attribute_av_id) = explode(':', $item); + + if (! isset($attributes_av_list[$attribute_id])) + $attributes_av_list[$attribute_id] = array(); + + + $attributes_av_list[$attribute_id][] = $attribute_av_id; + } + + // Next, recursively combine array + $combinations = $tmp = array(); + + $this->combine($attributes_av_list, $combinations, $tmp); + + // Create event + $event = new ProductCombinationGenerationEvent( + $this->getExistingObject(), + $data['currency'], + $combinations + ); + + $event + ->setReference($data['reference'] == null ? '' : $data['reference']) + ->setPrice($data['price'] == null ? 0 : $data['price']) + ->setWeight($data['weight'] == null ? 0 : $data['weight']) + ->setQuantity($data['quantity'] == null ? 0 : $data['quantity']) + ->setSalePrice($data['sale_price'] == null ? 0 : $data['sale_price']) + ->setOnsale($data['onsale'] == null ? false : $data['onsale']) + ->setIsnew($data['isnew'] == null ? false : $data['isnew']) + ->setEanCode($data['ean_code'] == null ? '' : $data['ean_code']) + ; + + $this->dispatch(TheliaEvents::PRODUCT_COMBINATION_GENERATION, $event); + + // Log object modification + $this->adminLogAppend(sprintf("Combination generation for product reference %s", $event->getProduct()->getRef())); + + // Redirect to the success URL + $this->redirect($changeForm->getSuccessUrl()); + + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("Combination builder"), $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + /** * Invoked through Ajax; this method calculates the taxed price from the unaxed price, and * vice versa. diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php new file mode 100644 index 000000000..f155a9dce --- /dev/null +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -0,0 +1,85 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event\Administrator; +use Thelia\Core\Event\ActionEvent; +use Thelia\Model\Admin; + + +/** + * Class AdministratorUpdatePasswordEvent + * @package Thelia\Core\Event\Administrator + * @author Manuel Raynaud + */ +class AdministratorUpdatePasswordEvent extends ActionEvent +{ + + /** + * @var \Thelia\Model\Admin + */ + protected $admin; + + /** + * @var string new administrator password + */ + protected $password; + + public function __construct(Admin $admin) + { + $this->admin = $admin; + } + + /** + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param \Thelia\Model\Admin $admin + */ + public function setAdmin(Admin $admin) + { + $this->admin = $admin; + } + + /** + * @return \Thelia\Model\Admin + */ + public function getAdmin() + { + return $this->admin; + } + +} + diff --git a/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php new file mode 100644 index 000000000..05b55d733 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php @@ -0,0 +1,159 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event\Product; +use Thelia\Model\Product; + +class ProductCombinationGenerationEvent extends ProductEvent +{ + protected $reference; + protected $price; + protected $currency_id; + protected $weight; + protected $quantity; + protected $sale_price; + protected $onsale; + protected $isnew; + protected $ean_code; + protected $combinations; + + public function __construct(Product $product, $currency_id, $combinations) + { + parent::__construct($product); + + $this->setCombinations($combinations); + $this->setCurrencyId($currency_id); + } + + public function getCurrencyId() + { + return $this->currency_id; + } + + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } + + public function getReference() + { + return $this->reference; + } + + public function setReference($reference) + { + $this->reference = $reference; + return $this; + } + + public function getPrice() + { + return $this->price; + } + + public function setPrice($price) + { + $this->price = $price; + return $this; + } + + public function getWeight() + { + return $this->weight; + } + + public function setWeight($weight) + { + $this->weight = $weight; + return $this; + } + + public function getQuantity() + { + return $this->quantity; + } + + public function setQuantity($quantity) + { + $this->quantity = $quantity; + return $this; + } + + public function getSalePrice() + { + return $this->sale_price; + } + + public function setSalePrice($sale_price) + { + $this->sale_price = $sale_price; + return $this; + } + + public function getOnsale() + { + return $this->onsale; + } + + public function setOnsale($onsale) + { + $this->onsale = $onsale; + return $this; + } + + public function getIsnew() + { + return $this->isnew; + } + + public function setIsnew($isnew) + { + $this->isnew = $isnew; + return $this; + } + + public function getEanCode() + { + return $this->ean_code; + } + + public function setEanCode($ean_code) + { + $this->ean_code = $ean_code; + return $this; + return $this; + } + + public function getCombinations() + { + return $this->combinations; + } + + public function setCombinations($combinations) + { + $this->combinations = $combinations; + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 42b20d8cd..f72668fc3 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -285,6 +285,8 @@ final class TheliaEvents const PRODUCT_DELETE_PRODUCT_SALE_ELEMENT = "action.deleteProductSaleElement"; const PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT = "action.updateProductSaleElement"; + const PRODUCT_COMBINATION_GENERATION = "action.productCombineationGeneration"; + const PRODUCT_SET_TEMPLATE = "action.productSetTemplate"; const PRODUCT_ADD_ACCESSORY = "action.productAddProductAccessory"; @@ -565,6 +567,7 @@ final class TheliaEvents const ADMINISTRATOR_CREATE = "action.createAdministrator"; const ADMINISTRATOR_UPDATE = "action.updateAdministrator"; const ADMINISTRATOR_DELETE = "action.deleteAdministrator"; + const ADMINISTRATOR_UPDATEPASSWORD = 'action.generatePassword'; // -- Mailing System management --------------------------------------------- diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php index e9a7d9eb8..10c1dda00 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php @@ -128,14 +128,17 @@ class AttributeAvailability extends BaseI18nLoop foreach ($attributesAv as $attributeAv) { $loopResultRow = new LoopResultRow($loopResult, $attributeAv, $this->versionable, $this->timestampable, $this->countable); - $loopResultRow->set("ID", $attributeAv->getId()) - ->set("IS_TRANSLATED",$attributeAv->getVirtualColumn('IS_TRANSLATED')) - ->set("LOCALE",$locale) - ->set("TITLE",$attributeAv->getVirtualColumn('i18n_TITLE')) - ->set("CHAPO", $attributeAv->getVirtualColumn('i18n_CHAPO')) - ->set("DESCRIPTION", $attributeAv->getVirtualColumn('i18n_DESCRIPTION')) - ->set("POSTSCRIPTUM", $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set("POSITION", $attributeAv->getPosition()); + $loopResultRow + ->set("ID" , $attributeAv->getId()) + ->set("ATTRIBUTE_ID" , $attributeAv->getAttributeId()) + ->set("IS_TRANSLATED", $attributeAv->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE" , $locale) + ->set("TITLE" , $attributeAv->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO" , $attributeAv->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION" , $attributeAv->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM" , $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("POSITION" , $attributeAv->getPosition()) + ; $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Core/Template/Loop/Feed.php b/core/lib/Thelia/Core/Template/Loop/Feed.php index cf29cf3b7..11f872432 100755 --- a/core/lib/Thelia/Core/Template/Loop/Feed.php +++ b/core/lib/Thelia/Core/Template/Loop/Feed.php @@ -29,6 +29,7 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Tools\DateTimeFormat; /** * @@ -90,15 +91,15 @@ class Feed extends BaseLoop $author = $item->get_author(); $description = $item->get_description(); - $date = $item->get_date('d/m/Y'); - $loopResultRow = new LoopResultRow($loopResult, null, $this->versionable, $this->timestampable, $this->countable); - $loopResultRow->set("URL", $item->get_permalink()); - $loopResultRow->set("TITLE", $item->get_title()); - $loopResultRow->set("AUTHOR", $item->get_author()); - $loopResultRow->set("DESCRIPTION", $item->get_description()); - $loopResultRow->set("DATE", $item->get_date('d/m/Y')); // FIXME - date format should be an intl parameter + $loopResultRow + ->set("URL" , $item->get_permalink()) + ->set("TITLE" , $item->get_title()) + ->set("AUTHOR" , $item->get_author()) + ->set("DESCRIPTION" , $item->get_description()) + ->set("DATE" , $item->get_date('U')) // FIXME - date format should be an intl parameter + ; $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index 494e219eb..ee49fe1ec 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -199,30 +199,29 @@ class Form extends AbstractSmartyPlugin { if ($repeat) { - $formFieldView = $this->getFormFieldView($params); - $formFieldConfig = $this->getFormFieldConfig($params); + $formFieldView = $this->getFormFieldView($params); + $formFieldConfig = $this->getFormFieldConfig($params); - $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView); + $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView); $value = $formFieldView->vars["value"]; - // We have a collection - if (0 < $value_count = count($formFieldView->children)) { + $key = $this->getParam($params, 'value_key', null); - $key = $this->getParam($params, 'value_key', null); + // We (may) have a collection + if ($key !== null) { - if ($key !== null) { - // If the field is not found, use an empty value - $val = array_key_exists($key, $value) ? $value[$key] : ''; + // Force array + if (! is_array($value)) $value = array(); - $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key); + // If the field is not found, use an empty value + $val = array_key_exists($key, $value) ? $value[$key] : ''; - $val = $value[$key]; + $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key); - $this->assignFieldValues($template, $name, $val, $formFieldView->vars, $value_count); - } else { - throw new \InvalidArgumentException(sprintf("Missing or empty parameter 'value_key' for field '%s'", $formFieldView->vars["name"])); - } + $val = $value[$key]; + + $this->assignFieldValues($template, $name, $val, $formFieldView->vars, count($formFieldView->children)); } else { $this->assignFieldValues($template, $formFieldView->vars["full_name"], $formFieldView->vars["value"], $formFieldView->vars); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php index 05c7bb0f6..d0f021ef5 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php @@ -73,7 +73,17 @@ class Format extends AbstractSmartyPlugin $date = $this->getParam($params, "date", false); if ($date === false) { - return ""; + + // Check if we have a timestamp + $timestamp = $this->getParam($params, "timestamp", false); + + if ($timestamp === false) { + // No timestamp => error + throw new SmartyPluginException("Either date or timestamp is a mandatory parameter in format_date function"); + } else { + $date = new \DateTime(); + $date->setTimestamp($timestamp); + } } if (!($date instanceof \DateTime)) { @@ -87,7 +97,6 @@ class Format extends AbstractSmartyPlugin } return $date->format($format); - } /** diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php index 1c6ab4fd1..23f9ed231 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php @@ -53,7 +53,11 @@ class Module extends AbstractSmartyPlugin } } } - return $template->fetch(sprintf("string:%s", $content)); + + if (! empty($content)) + return $template->fetch(sprintf("string:%s", $content)); + + return ""; } /** diff --git a/core/lib/Thelia/Form/ProductCombinationGenerationForm.php b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php new file mode 100644 index 000000000..8e4b155b9 --- /dev/null +++ b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php @@ -0,0 +1,91 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\GreaterThan; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Model\Currency; +use Thelia\Core\Translation\Translator; + +class ProductCombinationGenerationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add('product_id', 'integer', array( + 'label' => Translator::getInstance()->trans('Product ID'), + 'label_attr' => array('for' => 'combination_builder_id_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))) + )) + ->add('currency', 'integer', array( + 'label' => Translator::getInstance()->trans('Price currency *'), + 'label_attr' => array('for' => 'combination_builder_currency_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))) + )) + ->add('reference', 'text', array( + 'label' => Translator::getInstance()->trans('Reference'), + 'label_attr' => array('for' => 'combination_builder_reference_field') + )) + ->add('price', 'number', array( + 'label' => Translator::getInstance()->trans('Product price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_field') + )) + ->add('weight', 'number', array( + 'label' => Translator::getInstance()->trans('Weight'), + 'label_attr' => array('for' => 'combination_builder_weight_field') + )) + ->add('quantity', 'number', array( + 'label' => Translator::getInstance()->trans('Available quantity'), + 'label_attr' => array('for' => 'combination_builder_quantity_field') + )) + ->add('sale_price', 'number', array( + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_with_tax_field') + )) + ->add('onsale', 'integer', array( + 'label' => Translator::getInstance()->trans('This product is on sale'), + 'label_attr' => array('for' => 'combination_builder_onsale_field') + )) + ->add('isnew', 'integer', array( + 'label' => Translator::getInstance()->trans('Advertise this product as new'), + 'label_attr' => array('for' => 'combination_builder_isnew_field') + )) + ->add('ean_code', 'text', array( + 'label' => Translator::getInstance()->trans('EAN Code'), + 'label_attr' => array('for' => 'combination_builder_ean_code_field') + )) + ->add('attribute_av', 'collection', array( + 'type' => 'text', + 'label' => Translator::getInstance()->trans('Attribute ID:Attribute AV ID'), + 'label_attr' => array('for' => 'combination_builder_attribute_av_id'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ; + } + + public function getName() + { + return 'thelia_product_combination_generation_form'; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php index 2643692a2..54fb2fdc1 100644 --- a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php +++ b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php @@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator; class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm { - use StandardDescriptionFieldsTrait; - protected function buildForm() { $this->formBuilder @@ -77,7 +75,7 @@ class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm "label_attr" => array("for" => "quantity_field") )) ->add("sale_price", "number", array( - "label" => Translator::getInstance()->trans("Sale price without taxes"), + "label" => Translator::getInstance()->trans("Sale price excluding taxes"), "label_attr" => array("for" => "price_with_tax_field") )) ->add("sale_price_with_tax", "number", array( diff --git a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php index da831545a..cda72cc72 100644 --- a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php +++ b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php @@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator; class ProductSaleElementUpdateForm extends BaseForm { - use StandardDescriptionFieldsTrait; - protected function buildForm() { $this->formBuilder @@ -112,7 +110,7 @@ class ProductSaleElementUpdateForm extends BaseForm ) )) ->add('sale_price', 'collection', array( - 'label' => Translator::getInstance()->trans('Sale price without taxes'), + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), 'label_attr' => array('for' => 'price_with_tax_field'), 'allow_add' => true, 'allow_delete' => true, diff --git a/core/lib/Thelia/Model/Attribute.php b/core/lib/Thelia/Model/Attribute.php index 615fa643e..3439cac06 100755 --- a/core/lib/Thelia/Model/Attribute.php +++ b/core/lib/Thelia/Model/Attribute.php @@ -20,7 +20,7 @@ class Attribute extends BaseAttribute { $this->dispatchEvent(TheliaEvents::BEFORE_CREATEATTRIBUTE, new AttributeEvent($this)); // Set the current position for the new object - //$this->setPosition($this->getNextPosition()); + $this->setPosition($this->getNextPosition()); return true; } diff --git a/core/lib/Thelia/Model/Feature.php b/core/lib/Thelia/Model/Feature.php index 800ff832a..2627d5190 100755 --- a/core/lib/Thelia/Model/Feature.php +++ b/core/lib/Thelia/Model/Feature.php @@ -20,7 +20,7 @@ class Feature extends BaseFeature { $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE, new FeatureEvent($this)); // Set the current position for the new object - //$this->setPosition($this->getNextPosition()); + $this->setPosition($this->getNextPosition()); return true; } diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index f16a8a776..1b3f1eefa 100755 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -167,7 +167,7 @@ class Product extends BaseProduct $this->setTaxRuleId($taxRuleId); // Create the default product sale element of this product - $sale_elements = $this->createDefaultProductSaleElement($con, $baseWeight, $basePrice, $priceCurrencyId, true); + $sale_elements = $this->createProductSaleElement($con, $baseWeight, $basePrice, $basePrice, $priceCurrencyId, true); // Store all the stuff ! $con->commit(); @@ -185,19 +185,20 @@ class Product extends BaseProduct /** * Create a basic product sale element attached to this product. */ - public function createDefaultProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $currencyId, $isDefault) { + public function createProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $salePrice, $currencyId, $isDefault, $isPromo = false, $isNew = false, $quantity = 0, $eanCode = '', $ref = false) { // Create an empty product sale element $sale_elements = new ProductSaleElements(); $sale_elements ->setProduct($this) - ->setRef($this->getRef()) - ->setPromo(0) - ->setNewness(0) + ->setRef($ref == false ? $this->getRef() : $ref) + ->setPromo($isPromo) + ->setNewness($isNew) ->setWeight($weight) ->setIsDefault($isDefault) - ->setEanCode('') + ->setEanCode($eanCode) + ->setQuantity($quantity) ->save($con) ; @@ -206,7 +207,7 @@ class Product extends BaseProduct $product_price ->setProductSaleElements($sale_elements) - ->setPromoPrice($basePrice) + ->setPromoPrice($salePrice) ->setPrice($basePrice) ->setCurrencyId($currencyId) ->save($con) diff --git a/core/lib/Thelia/Tests/Core/Template/Smarty/Plugins/FormatTest.php b/core/lib/Thelia/Tests/Core/Template/Smarty/Plugins/FormatTest.php index 979642677..a673b805b 100644 --- a/core/lib/Thelia/Tests/Core/Template/Smarty/Plugins/FormatTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Smarty/Plugins/FormatTest.php @@ -155,6 +155,7 @@ class FormatTest extends \PHPUnit_Framework_TestCase * test formatDate without mandatory parameters * * @covers ::formatDate + * @expectedException Thelia\Core\Template\Smarty\Exception\SmartyPluginException */ public function testFormatDateWithoutDate() { diff --git a/local/modules/Cheque/Config/config.xml b/local/modules/Cheque/Config/config.xml index 2430f5027..cac3f6b7b 100755 --- a/local/modules/Cheque/Config/config.xml +++ b/local/modules/Cheque/Config/config.xml @@ -1,4 +1,4 @@ - +string

- {$TITLE|strip_tags nofilter} - {$DATE} + {$TITLE|strip_tags nofilter} - {format_date timestamp=$DATE output='date'}

@@ -20,7 +20,7 @@ {intl l='Lire la suite'} - + {/loop} \ No newline at end of file diff --git a/templates/admin/default/assets/js/document-upload.js b/templates/admin/default/assets/js/document-upload.js index dc35ea943..7843f5b44 100644 --- a/templates/admin/default/assets/js/document-upload.js +++ b/templates/admin/default/assets/js/document-upload.js @@ -4,7 +4,7 @@ $(function($){ Dropzone.autoDiscover = false; - + // Remove image on click $.documentUploadManager.initDocumentDropZone = function() { @@ -14,7 +14,7 @@ $(function($){ dictDefaultMessage : $('.btn-browse').html(), uploadMultiple: false, maxFilesize: 8 - }); + }); var totalFiles = 0, completedFiles = 0; @@ -40,8 +40,8 @@ $(function($){ $.documentUploadManager.updateDocumentListAjax(); $.documentUploadManager.onClickDeleteDocument(); }); - - + + }; diff --git a/templates/admin/default/assets/less/thelia/modals.less b/templates/admin/default/assets/less/thelia/modals.less index 2d371e6c0..ee6b3c662 100755 --- a/templates/admin/default/assets/less/thelia/modals.less +++ b/templates/admin/default/assets/less/thelia/modals.less @@ -9,7 +9,22 @@ } } +.modal-header { + h3 { + margin-bottom: 0; + } +} + // Body (where all modal content resides) .modal-body { max-height: none; + .scrollable { + border: 1px solid @input-border; + border-radius: @input-border-radius; + height: 458px; + overflow: auto; + padding-bottom: 5px; + padding-left: 10px; + padding-top: 5px; + } } \ No newline at end of file diff --git a/templates/admin/default/assets/less/thelia/thelia.less b/templates/admin/default/assets/less/thelia/thelia.less index 0d42273e9..2189b9307 100644 --- a/templates/admin/default/assets/less/thelia/thelia.less +++ b/templates/admin/default/assets/less/thelia/thelia.less @@ -336,9 +336,16 @@ } } +.existing-document { + + .loading{ + margin: 0; + } +} + // -- Drag & drop -- .take{ - + .draggable{ border: 2px dashed @gray-light; margin-bottom: 10px; @@ -346,9 +353,9 @@ &:last-child{ margin-bottom: 0; - } + } } - + .over{ .drop-message{ border-color: @brand-primary; @@ -358,8 +365,8 @@ } -.place{ - +.place{ + .over{ .drop-message{ border-color: @brand-primary; @@ -368,10 +375,10 @@ } .panel-body{ - + .draggable, .drag{ margin: 5px 0; - padding: 10px; + padding: 10px; border: 1px dashed @gray-light; } @@ -390,7 +397,7 @@ } .take, .place{ - + .drop-message{ width: 50%; margin: 10px auto; @@ -410,4 +417,11 @@ .ui-draggable-dragging{ z-index: 100; } +} + +// -- File Upoload drop zone --------------------------------------------------- + +.dropzone { + border: 1px dashed #ddd; + padding: 20px; } \ No newline at end of file diff --git a/templates/admin/default/category-edit.html b/templates/admin/default/category-edit.html index 340e7cbbd..200098d69 100755 --- a/templates/admin/default/category-edit.html +++ b/templates/admin/default/category-edit.html @@ -42,7 +42,7 @@