diff --git a/.gitignore b/.gitignore index 8cf78452c..be8430509 100755 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ coverage .buildpath .project .settings/ -local/cache/* local/media/documents/* local/media/images/* web/assets/* diff --git a/.travis.yml b/.travis.yml index 84e25866b..184a98fbe 100755 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ env: - DB_USER=root before_script: + - phpenv config-add travis.php.ini - composer self-update - composer install --prefer-dist --dev - sh -c "mysql -u$DB_USER -e 'SET FOREIGN_KEY_CHECKS = 0; DROP DATABASE IF EXISTS thelia;SET FOREIGN_KEY_CHECKS = 1;'; fi" diff --git a/Readme.md b/Readme.md index 66d831f94..1134ccb68 100755 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,16 @@ Requirements ------------ * php 5.4 + * Required extensions : + * PDO_Mysql + * mcrypt + * intl + * gd + * curl + * safe_mode off + * memory_limit at least 150M, preferably 256. + * post_max_size 20M + * upload_max_filesize 2M * apache 2 * mysql 5 diff --git a/composer.json b/composer.json index afef9e30b..0a4fc0629 100755 --- a/composer.json +++ b/composer.json @@ -38,7 +38,8 @@ "imagine/imagine": "dev-master", "symfony/icu": "1.0", "swiftmailer/swiftmailer": "5.0.*", - "symfony/serializer": "2.3.*" + "symfony/serializer": "2.3.*", + "ensepar/html2pdf": "1.0.1" }, "require-dev" : { "phpunit/phpunit": "3.7.*", diff --git a/composer.lock b/composer.lock index a89768ef1..f50fb4a4d 100755 --- a/composer.lock +++ b/composer.lock @@ -3,8 +3,112 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "097481390dc87b3482d895b3b6a65479", + "hash": "852879ecc2e39e5cf283a3b1c5051a8e", "packages": [ + { + "name": "ensepar/html2pdf", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/OwlyCode/html2pdf.git", + "reference": "b53a27430cc35b29bbe2faaa55ed4a7d5c156cd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/OwlyCode/html2pdf/zipball/b53a27430cc35b29bbe2faaa55ed4a7d5c156cd3", + "reference": "b53a27430cc35b29bbe2faaa55ed4a7d5c156cd3", + "shasum": "" + }, + "require": { + "ensepar/tcpdf": "5.0.003", + "php": ">=5.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "HTML2PDF": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Spipu", + "homepage": "http://sourceforge.net/users/spipu", + "role": "Developer" + }, + { + "name": "OwlyCode", + "homepage": "http://www.github.com/OwlyCode", + "role": "Developer" + } + ], + "description": "Unofficial fork of 'html2pdf' with Composer support. (Fixed composer dependency problem)", + "homepage": "https://github.com/jwronsky/html2pdf", + "keywords": [ + "html", + "html2pdf", + "pdf" + ], + "time": "2013-09-13 12:23:43" + }, + { + "name": "ensepar/tcpdf", + "version": "5.0.003", + "source": { + "type": "git", + "url": "https://github.com/OwlyCode/tcpdf.git", + "reference": "ae578409e9454fdf6c794cce6f063b0c95bfa518" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/OwlyCode/tcpdf/zipball/ae578409e9454fdf6c794cce6f063b0c95bfa518", + "reference": "ae578409e9454fdf6c794cce6f063b0c95bfa518", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "fonts", + "config/lang", + "config", + "2dbarcodes.php", + "barcodes.php", + "htmlcolors.php", + "qrcode.php", + "tcpdf.php", + "unicode_data.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPLv3" + ], + "authors": [ + { + "name": "Nicola Asuni", + "email": "info@tecnick.com", + "homepage": "http://nicolaasuni.tecnick.com" + }, + { + "name": "Tristan Maindron", + "email": "tmaindron@gmail.com", + "homepage": "http://www.github.com/OwlyCode" + } + ], + "description": "TCPDF is a PHP class for generating PDF documents.", + "homepage": "http://www.tcpdf.org/", + "keywords": [ + "TCPDF", + "pdf" + ], + "time": "2013-09-12 17:00:40" + }, { "name": "imagine/imagine", "version": "dev-master", @@ -1763,6 +1867,40 @@ ], "time": "2013-09-11 13:01:19" }, + { + "name": "phenx/php-font-lib", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/PhenX/php-font-lib.git", + "reference": "42a1ca6d19f14076911a118705b771c3a5a8b179" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/42a1ca6d19f14076911a118705b771c3a5a8b179", + "reference": "42a1ca6d19f14076911a118705b771c3a5a8b179", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "classes/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", + "time": "2013-02-22 23:30:49" + }, { "name": "phpunit/php-code-coverage", "version": "1.2.12", diff --git a/core/lib/Thelia/Action/Address.php b/core/lib/Thelia/Action/Address.php index b25c9c4ba..f6c6a81ad 100644 --- a/core/lib/Thelia/Action/Address.php +++ b/core/lib/Thelia/Action/Address.php @@ -60,6 +60,13 @@ class Address extends BaseAction implements EventSubscriberInterface $address->delete(); } + public function useDefault(AddressEvent $event) + { + $address = $event->getAddress(); + + $address->makeItDefault(); + } + protected function createOrUpdate(AddressModel $addressModel, AddressCreateOrUpdateEvent $event) { $addressModel->setDispatcher($this->getDispatcher()); @@ -125,7 +132,8 @@ class Address extends BaseAction implements EventSubscriberInterface return array( TheliaEvents::ADDRESS_CREATE => array("create", 128), TheliaEvents::ADDRESS_UPDATE => array("update", 128), - TheliaEvents::ADDRESS_DELETE => array("delete", 128) + TheliaEvents::ADDRESS_DELETE => array("delete", 128), + TheliaEvents::ADDRESS_DEFAULT => array('useDefault', 128), ); } } diff --git a/core/lib/Thelia/Action/Customer.php b/core/lib/Thelia/Action/Customer.php index 061dba028..85643cb88 100755 --- a/core/lib/Thelia/Action/Customer.php +++ b/core/lib/Thelia/Action/Customer.php @@ -25,6 +25,7 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\ActionEvent; +use Thelia\Core\Event\Customer\CustomerAddressEvent; use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\Customer\CustomerEvent; use Thelia\Core\Event\TheliaEvents; @@ -148,11 +149,11 @@ class Customer extends BaseAction implements EventSubscriberInterface public static function getSubscribedEvents() { return array( - TheliaEvents::CUSTOMER_CREATEACCOUNT => array("create", 128), - TheliaEvents::CUSTOMER_UPDATEACCOUNT => array("modify", 128), - TheliaEvents::CUSTOMER_LOGOUT => array("logout", 128), - TheliaEvents::CUSTOMER_LOGIN => array("login" , 128), - TheliaEvents::CUSTOMER_DELETEACCOUNT => array("delete", 128), + TheliaEvents::CUSTOMER_CREATEACCOUNT => array('create', 128), + TheliaEvents::CUSTOMER_UPDATEACCOUNT => array('modify', 128), + TheliaEvents::CUSTOMER_LOGOUT => array('logout', 128), + TheliaEvents::CUSTOMER_LOGIN => array('login', 128), + TheliaEvents::CUSTOMER_DELETEACCOUNT => array('delete', 128), ); } } diff --git a/core/lib/Thelia/Action/Pdf.php b/core/lib/Thelia/Action/Pdf.php new file mode 100644 index 000000000..52ce0b92d --- /dev/null +++ b/core/lib/Thelia/Action/Pdf.php @@ -0,0 +1,75 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Core\Event\PdfEvent; +use Thelia\Core\Event\TheliaEvents; + + +/** + * Class Pdf + * @package Thelia\Action + * @author Manuel Raynaud + */ +class Pdf extends BaseAction implements EventSubscriberInterface +{ + + public function generatePdf(PdfEvent $event) + { + + $html2pdf = new \HTML2PDF($event->getOrientation(), $event->getFormat(), $event->getLang(), $event->getUnicode(), $event->getEncoding(), $event->getMarges()); + + $html2pdf->pdf->SetDisplayMode('real'); + + $html2pdf->writeHTML($event->getContent()); + $event->setPdf($html2pdf->output(null, 'S')); + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::GENERATE_PDF => array("generatePdf", 128) + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Command/Install.php b/core/lib/Thelia/Command/Install.php index 03b7fda48..6423d861a 100755 --- a/core/lib/Thelia/Command/Install.php +++ b/core/lib/Thelia/Command/Install.php @@ -28,6 +28,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; use Thelia\Command\ContainerAwareCommand; +use Thelia\Install\CheckPermission; use Thelia\Install\Database; /** @@ -82,6 +83,9 @@ class Install extends ContainerAwareCommand '', 'Welcome to Thelia install process', 'You need information about your database configuration (host, username, password, database name, etc)', + '', + 'Caution : You are installing Thelia in cli mode, we verify some information, but this information are only available for the cli php sapi', + 'This informations can be different in your apache or cgi php.ini files', '' )); @@ -136,40 +140,35 @@ class Install extends ContainerAwareCommand "Checking some permissions" )); - $confDir = THELIA_ROOT . "local/config"; - $cacheDir = THELIA_ROOT . "cache"; - $logDir = THELIA_ROOT . "log"; + $permissions = new CheckPermission(false, $this->getContainer()->get('thelia.translator')); + $isValid = $permissions->exec(); - $conf = is_writable($confDir); - $cache = is_writable($cacheDir); - $log = is_writable($logDir); + foreach($permissions->getValidationMessages() as $item => $data) { + if($data['status']) { + $output->writeln(array( + sprintf("%s ... %s", + $data['text'], + "Ok") + ) + ); + } else { + $output->writeln(array( + sprintf("%s %s", + $data['text'], + sprintf("%s", $data["hint"]) + ) + )); + } - $output->writeln(array( - sprintf( - "config directory(%s)... %s", - $confDir, - $conf ? "Ok" : "Fail" - ), - sprintf( - "cache directory(%s)... %s" - ,$cacheDir, - $cache ? "Ok" : "Fail" - ), - sprintf( - "log directory(%s)... %s", - $logDir, - $log ? "Ok" : "Fail" - ), - )); - - if ($conf === false || $cache === false || $log === false) { - $output->writeln(array( - "", - "Please put correct permission and reload install process" - )); - exit; } + if(false === $isValid) { + $output->writeln(array( + "", + "Please put correct permissions and reload install process" + )); + exit; + } } /** diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index f153a8de0..87575f59b 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -111,6 +111,11 @@ + + + + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 5639c0b38..ffecb9512 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -123,6 +123,32 @@ + + + + Thelia\Controller\Admin\AddressController::deleteAction + + + + Thelia\Controller\Admin\AddressController::useAddressAction + + + + Thelia\Controller\Admin\AddressController::createAction + + + + Thelia\Controller\Admin\AddressController::updateAction + \d+ + + + + Thelia\Controller\Admin\AddressController::processUpdateAction + \d+ + + + + @@ -150,6 +176,16 @@ Thelia\Controller\Admin\OrderController::updateAddress + + Thelia\Controller\Admin\OrderController::generateInvoicePdf + \d+ + + + + Thelia\Controller\Admin\OrderController::generateDeliveryPdf + \d+ + + @@ -370,7 +406,7 @@ - + Thelia\Controller\Admin\ContentController::createAction diff --git a/core/lib/Thelia/Controller/Admin/AddressController.php b/core/lib/Thelia/Controller/Admin/AddressController.php new file mode 100644 index 000000000..38ec9cb6b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AddressController.php @@ -0,0 +1,306 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; +use Thelia\Core\Event\Address\AddressCreateOrUpdateEvent; +use Thelia\Core\Event\Address\AddressEvent; +use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Form\AddressCreateForm; +use Thelia\Form\AddressUpdateForm; +use Thelia\Model\AddressQuery; +use Thelia\Model\CustomerQuery; + + +/** + * Class AddressController + * @package Thelia\Controller\Admin + * @author Manuel Raynaud + */ +class AddressController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'address', + null, + null, + + 'admin.customer.update.view', + 'admin.address.create', + 'admin.address.update', + 'admin.address.delete', + + TheliaEvents::ADDRESS_CREATE, + TheliaEvents::ADDRESS_UPDATE, + TheliaEvents::ADDRESS_DELETE, + null, + null + + ); + } + + public function useAddressAction() + { + if (null !== $response = $this->checkAuth("admin.customer.update")) return $response; + + $address_id = $this->getRequest()->request->get('address_id'); + + try { + $address = AddressQuery::create()->findPk($address_id); + + if (null === $address) { + throw new \InvalidArgumentException(sprintf('%d address does not exists', $address_id)); + } + + $addressEvent = new AddressEvent($address); + + $this->dispatch(TheliaEvents::ADDRESS_DEFAULT, $addressEvent); + + $this->adminLogAppend(sprintf("address %d for customer %d removal", $address_id, $address->getCustomerId())); + } catch(\Exception $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("error during address removal with message %s", $e->getMessage())); + } + + $this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId())); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return new AddressCreateForm($this->getRequest()); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return new AddressUpdateForm($this->getRequest()); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\Address $object + */ + protected function hydrateObjectForm($object) + { + $data = array( + "label" => $object->getLabel(), + "title" => $object->getTitleId(), + "firstname" => $object->getFirstname(), + "lastname" => $object->getLastname(), + "address1" => $object->getAddress1(), + "address2" => $object->getAddress2(), + "address3" => $object->getAddress3(), + "zipcode" => $object->getZipcode(), + "city" => $object->getCity(), + "country" => $object->getCountryId(), + "cellphone" => $object->getCellphone(), + "phone" => $object->getPhone(), + "company" => $object->getCompany() + ); + + return new AddressUpdateForm($this->getRequest(), "form", $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param unknown $formData + */ + protected function getCreationEvent($formData) + { + $event = $this->getCreateOrUpdateEvent($formData); + + $customer = CustomerQuery::create()->findPk($this->getRequest()->get("customer_id")); + + $event->setCustomer($customer); + + return $event; + } + + /** + * Creates the update event with the provided form data + * + * @param unknown $formData + */ + protected function getUpdateEvent($formData) + { + $event = $this->getCreateOrUpdateEvent($formData); + + $event->setAddress($this->getExistingObject()); + + return $event; + } + + protected function getCreateOrUpdateEvent($formData) + { + $event = new AddressCreateOrUpdateEvent( + $formData["label"], + $formData["title"], + $formData["firstname"], + $formData["lastname"], + $formData["address1"], + $formData["address2"], + $formData["address3"], + $formData["zipcode"], + $formData["city"], + $formData["country"], + $formData["cellphone"], + $formData["phone"], + $formData["company"], + $formData["is_default"] + ); + + + + return $event; + + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new AddressEvent($this->getExistingObject()); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param unknown $event + */ + protected function eventContainsObject($event) + { + return null !== $event->getAddress(); + } + + /** + * Get the created object from an event. + * + * @param unknown $createEvent + */ + protected function getObjectFromEvent($event) + { + return null; + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + return AddressQuery::create()->findPk($this->getRequest()->get('address_id')); + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param unknown $object + */ + protected function getObjectLabel($object) + { + return $object->getLabel(); + } + + /** + * Returns the object ID from the object + * + * @param unknown $object + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param unknown $currentOrder, if any, null otherwise. + */ + protected function renderListTemplate($currentOrder) + { + // TODO: Implement renderListTemplate() method. + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('ajax/address-update-modal', array( + "address_id" => $this->getRequest()->get('address_id'), + "customer_id" => $this->getExistingObject()->getCustomerId() + )); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + $address = $this->getExistingObject(); + $this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId())); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + // TODO: Implement redirectToListTemplate() method. + } + + /** + * Put in this method post object delete processing if required. + * + * @param \Thelia\Core\Event\AddressEvent $deleteEvent the delete event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + $address = $deleteEvent->getAddress(); + $this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId())); + } + + /** + * Put in this method post object creation processing if required. + * + * @param AddressCreateOrUpdateEvent $createEvent the create event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalCreateAction($createEvent) + { + $this->redirectToEditionTemplate(); + } + + protected function performAdditionalUpdateAction($event) + { + $this->redirectToEditionTemplate(); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/BaseAdminController.php b/core/lib/Thelia/Controller/Admin/BaseAdminController.php index d80d8ce9f..5d99a877b 100755 --- a/core/lib/Thelia/Controller/Admin/BaseAdminController.php +++ b/core/lib/Thelia/Controller/Admin/BaseAdminController.php @@ -51,7 +51,7 @@ class BaseAdminController extends BaseController /** * Helper to append a message to the admin log. * - * @param unknown $message + * @param string $message */ public function adminLogAppend($message) { @@ -187,12 +187,12 @@ class BaseAdminController extends BaseController /** * @return a ParserInterface instance parser */ - protected function getParser() + protected function getParser($template = null) { $parser = $this->container->get("thelia.parser"); // Define the template thant shoud be used - $parser->setTemplate(ConfigQuery::read('base_admin_template', 'admin/default')); + $parser->setTemplate($template ?: ConfigQuery::read('base_admin_template', 'admin/default')); return $parser; } @@ -246,9 +246,9 @@ class BaseAdminController extends BaseController * @param unknown $routeId the route ID, as found in Config/Resources/routing/admin.xml * @param unknown $urlParameters the URL parametrs, as a var/value pair array */ - public function redirectToRoute($routeId, $urlParameters = array()) + public function redirectToRoute($routeId, $urlParameters = array(), $routeParameters = array()) { - $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId), $urlParameters)); + $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId, $routeParameters), $urlParameters)); } /** @@ -378,10 +378,12 @@ class BaseAdminController extends BaseController * Render the given template, and returns the result as a string. * * @param $templateName the complete template name, with extension - * @param array $args the template arguments + * @param array $args the template arguments + * @param null $templateDir + * * @return \Symfony\Component\HttpFoundation\Response */ - protected function renderRaw($templateName, $args = array()) + protected function renderRaw($templateName, $args = array(), $templateDir = null) { // Add the template standard extension @@ -417,7 +419,7 @@ class BaseAdminController extends BaseController // Render the template. try { - $data = $this->getParser()->render($templateName, $args); + $data = $this->getParser($templateDir)->render($templateName, $args); return $data; } catch (AuthenticationException $ex) { diff --git a/core/lib/Thelia/Controller/Admin/CustomerController.php b/core/lib/Thelia/Controller/Admin/CustomerController.php index f559a5bb0..e4d24e9ad 100644 --- a/core/lib/Thelia/Controller/Admin/CustomerController.php +++ b/core/lib/Thelia/Controller/Admin/CustomerController.php @@ -22,13 +22,17 @@ /*************************************************************************************/ namespace Thelia\Controller\Admin; + use Propel\Runtime\Exception\PropelException; use Symfony\Component\Form\Form; +use Thelia\Core\Event\Address\AddressEvent; +use Thelia\Core\Event\Customer\CustomerAddressEvent; use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\Customer\CustomerEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Form\CustomerModification; use Thelia\Form\Exception\FormValidationException; +use Thelia\Model\AddressQuery; use Thelia\Model\CustomerQuery; use Thelia\Core\Translation\Translator; @@ -53,6 +57,8 @@ class CustomerController extends BaseAdminController )); } + + /** * update customer action * diff --git a/core/lib/Thelia/Controller/Admin/OrderController.php b/core/lib/Thelia/Controller/Admin/OrderController.php index 77df4f9b3..1df0679f0 100644 --- a/core/lib/Thelia/Controller/Admin/OrderController.php +++ b/core/lib/Thelia/Controller/Admin/OrderController.php @@ -23,10 +23,13 @@ namespace Thelia\Controller\Admin; +use Symfony\Component\HttpFoundation\Response; use Thelia\Core\Event\Order\OrderAddressEvent; use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\PdfEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Form\OrderUpdateAddress; +use Thelia\Model\ConfigQuery; use Thelia\Model\Base\OrderAddressQuery; use Thelia\Model\OrderQuery; use Thelia\Model\OrderStatusQuery; @@ -193,4 +196,52 @@ class OrderController extends BaseAdminController $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params))); } + + public function generateInvoicePdf($order_id) + { + return $this->generatePdf($order_id, ConfigQuery::read('pdf_invoice_file', 'invoice')); + } + + public function generateDeliveryPdf($order_id) + { + return $this->generatePdf($order_id, ConfigQuery::read('pdf_delivery_file', 'delivery')); + } + + protected function generatePdf($order_id, $fileName) + { + if (null !== $response = $this->checkAuth("admin.order.update")) return $response; + + + $html = $this->renderRaw( + $fileName, + array( + 'order_id' => $order_id + ), + ConfigQuery::read('pdf_template', 'pdf') + ); + + $order = OrderQuery::create()->findPk($order_id); + + try { + $pdfEvent = new PdfEvent($html); + + $this->dispatch(TheliaEvents::GENERATE_PDF, $pdfEvent); + + if($pdfEvent->hasPdf()) { + return Response::create($pdfEvent->getPdf(), 200, + array( + 'Content-type' => "application/pdf", + 'Content-Disposition' => sprintf('Attachment;filename=%s.pdf', $order->getRef()), + )); + } + + } catch (\Exception $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf('error during generating invoice pdf for order id : %d with message "%s"', $order_id, $e->getMessage())); + + } + + $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", array( + 'order_id' => $order_id + )))); + } } diff --git a/core/lib/Thelia/Core/Event/PdfEvent.php b/core/lib/Thelia/Core/Event/PdfEvent.php new file mode 100644 index 000000000..e0f873e04 --- /dev/null +++ b/core/lib/Thelia/Core/Event/PdfEvent.php @@ -0,0 +1,193 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + + +/** + * Class PdfEvent + * @package Thelia\Core\Event + * @author Manuel Raynaud + */ +class PdfEvent extends ActionEvent +{ + protected $content; + + protected $pdf; + + protected $orientation; + protected $format; + protected $lang; + protected $unicode; + protected $encoding; + protected $marges; + + /** + * @param $content html content to transform into pdf + * @param string $orientation page orientation, same as TCPDF + * @param string $format The format used for pages, same as TCPDF + * @param string $lang Lang : fr, en, it... + * @param bool $unicode TRUE means that the input text is unicode (default = true) + * @param string $encoding charset encoding; default is UTF-8 + * @param array $marges Default marges (left, top, right, bottom) + */ + public function __construct($content, $orientation = 'P', $format = 'A4', $lang='fr', $unicode=true, $encoding='UTF-8',array $marges = array(0, 0, 0, 0)) + { + $this->content = $content; + $this->orientation = $orientation; + $this->format = $format; + $this->lang = $lang; + $this->unicode = $unicode; + $this->encoding = $encoding; + $this->marges = $marges; + } + + /** + * @param mixed $content + */ + public function setContent($content) + { + $this->content = $content; + } + + /** + * @return mixed + */ + public function getContent() + { + return $this->content; + } + + public function setPdf($pdf) + { + $this->pdf = $pdf; + } + + public function getPdf() + { + return $this->pdf; + } + + public function hasPdf() + { + return null !== $this->pdf; + } + + /** + * @param mixed $encoding + */ + public function setEncoding($encoding) + { + $this->encoding = $encoding; + } + + /** + * @return mixed + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * @param mixed $format + */ + public function setFormat($format) + { + $this->format = $format; + } + + /** + * @return mixed + */ + public function getFormat() + { + return $this->format; + } + + /** + * @param mixed $lang + */ + public function setLang($lang) + { + $this->lang = $lang; + } + + /** + * @return mixed + */ + public function getLang() + { + return $this->lang; + } + + /** + * @param mixed $marges + */ + public function setMarges($marges) + { + $this->marges = $marges; + } + + /** + * @return mixed + */ + public function getMarges() + { + return $this->marges; + } + + /** + * @param mixed $orientation + */ + public function setOrientation($orientation) + { + $this->orientation = $orientation; + } + + /** + * @return mixed + */ + public function getOrientation() + { + return $this->orientation; + } + + /** + * @param mixed $unicode + */ + public function setUnicode($unicode) + { + $this->unicode = $unicode; + } + + /** + * @return mixed + */ + public function getUnicode() + { + return $this->unicode; + } + + +} \ 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 29f45dd6d..f0dc68702 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -76,6 +76,11 @@ final class TheliaEvents */ const CUSTOMER_DELETEACCOUNT = "action.deleteCustomer"; + /** + * sent on customer address removal + */ + const CUSTOMER_ADDRESS_DELETE = "action.customer.deleteAddress"; + /** * sent when a customer need a new password */ @@ -134,6 +139,11 @@ final class TheliaEvents */ const ADDRESS_DELETE = "action.deleteAddress"; + /** + * sent when an address is tag as default + */ + const ADDRESS_DEFAULT = "action.defaultAddress"; + const BEFORE_CREATEADDRESS = "action.before_createAddress"; const AFTER_CREATEADDRESS = "action.after_createAddress"; @@ -597,4 +607,6 @@ final class TheliaEvents */ const GENERATE_REWRITTENURL = 'action.generate_rewritenurl'; + const GENERATE_PDF = 'thelia.generatePdf'; + } diff --git a/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php b/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php index 349fa178a..12ed85ad2 100755 --- a/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php +++ b/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php @@ -72,7 +72,7 @@ class AsseticHelper break; case 'sass' : - $fm->set('less', new Filter\Sass\SassFilter()); + $fm->set('sass', new Filter\Sass\SassFilter()); break; case 'cssembed' : @@ -87,6 +87,10 @@ class AsseticHelper $fm->set('cssimport', new Filter\CssImportFilter()); break; + case 'compass': + $fm->set('compass', new Filter\CompassFilter()); + break; + default : throw new \InvalidArgumentException("Unsupported Assetic filter: '$filter_name'"); break; diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php index 315adf37e..17d9e37a3 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php @@ -30,6 +30,7 @@ use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Security\SecurityContext; use Thelia\Core\Template\ParserContext; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; +use Thelia\Model\ConfigQuery; use Thelia\Model\CategoryQuery; use Thelia\Model\ContentQuery; use Thelia\Model\CountryQuery; @@ -234,6 +235,17 @@ class DataAccessFunctions extends AbstractSmartyPlugin return $this->dataAccess("Lang", $params, $this->request->getSession()->getLang()); } + public function ConfigDataAccess($params, $smarty) + { + if(false === array_key_exists("key", $params)) { + return null; + } + + $key = $params['key']; + + return ConfigQuery::read($key); + } + /** * @param $objectLabel * @param $params @@ -344,6 +356,7 @@ class DataAccessFunctions extends AbstractSmartyPlugin new SmartyPluginDescriptor('function', 'lang', $this, 'langDataAccess'), new SmartyPluginDescriptor('function', 'cart', $this, 'cartDataAccess'), new SmartyPluginDescriptor('function', 'order', $this, 'orderDataAccess'), + new SmartyPluginDescriptor('function', 'config', $this, 'ConfigDataAccess'), ); } diff --git a/core/lib/Thelia/Install/CheckPermission.php b/core/lib/Thelia/Install/CheckPermission.php index 15317211b..b8c4e9888 100644 --- a/core/lib/Thelia/Install/CheckPermission.php +++ b/core/lib/Thelia/Install/CheckPermission.php @@ -45,6 +45,7 @@ class CheckPermission extends BaseInstall const DIR_LOG = 'log'; const DIR_CACHE = 'cache'; const DIR_WEB = 'web'; + const DIR_SESSION = 'local/session'; /** @var array Directory needed to be writable */ protected $directoriesToBeWritable = array( @@ -52,11 +53,12 @@ class CheckPermission extends BaseInstall self::DIR_LOG, self::DIR_CACHE, self::DIR_WEB, + self::DIR_SESSION, ); /** @var array Minimum server configuration necessary */ protected $minServerConfigurationNecessary = array( - 'memory_limit' => 134217728, + 'memory_limit' => 157286400, 'post_max_size' => 20971520, 'upload_max_filesize' => 2097152 ); @@ -187,9 +189,9 @@ class CheckPermission extends BaseInstall { if ($this->translator !== null) { if ($isValid) { - $sentence = 'Your directory %directory% is writable'; + $sentence = 'Your directory %directory% is writable'; } else { - $sentence = 'Your directory %directory% is not writable'; + $sentence = 'Your directory %directory% is not writable'; } $translatedText = $this->translator->trans( @@ -216,7 +218,7 @@ class CheckPermission extends BaseInstall protected function getI18nDirectoryHint($directory) { if ($this->translator !== null) { - $sentence = 'chmod 777 %directory% on your server with admin rights could help'; + $sentence = 'chmod 777 %directory% on your server with admin rights could help'; $translatedText = $this->translator->trans( $sentence, array( @@ -246,9 +248,9 @@ class CheckPermission extends BaseInstall protected function getI18nConfigText($key, $expectedValue, $currentValue, $isValid) { if ($isValid) { - $sentence = 'Your %key% server configuration (currently %currentValue%) is well enough to run Thelia2 (%expectedValue% needed)'; + $sentence = 'Your %key% server configuration (currently %currentValue%) is well enough to run Thelia2 (%expectedValue% needed)'; } else { - $sentence = 'Your %key% server configuration (currently %currentValue%) is not sufficient enough in order to run Thelia2 (%expectedValue% needed)'; + $sentence = 'Your %key% server configuration (currently %currentValue%) is not sufficient enough in order to run Thelia2 (%expectedValue% needed)'; } $translatedText = $this->translator->trans( @@ -271,7 +273,7 @@ class CheckPermission extends BaseInstall */ protected function getI18nConfigHint() { - $sentence = 'Modifying this value on your server php.ini file with admin rights could help'; + $sentence = 'Modifying this value on your server php.ini file with admin rights could help'; $translatedText = $this->translator->trans( $sentence, array(), @@ -294,9 +296,9 @@ class CheckPermission extends BaseInstall { if ($this->translator !== null) { if ($isValid) { - $sentence = 'Your PHP version %currentValue% is well enough to run Thelia2 (%expectedValue% needed)'; + $sentence = 'Your PHP version %currentValue% is well enough to run Thelia2 (%expectedValue% needed)'; } else { - $sentence = 'Your PHP version %currentValue% is not sufficient enough to run Thelia2 (%expectedValue% needed)'; + $sentence = 'Your PHP version %currentValue% is not sufficient enough to run Thelia2 (%expectedValue% needed)'; } $translatedText = $this->translator->trans( @@ -343,6 +345,10 @@ class CheckPermission extends BaseInstall { $serverValueInBytes = $this->returnBytes(ini_get($key)); + if($serverValueInBytes == -1) { + return true; + } + return ($serverValueInBytes >= $necessaryValueInBytes); } diff --git a/core/lib/Thelia/Install/Database.php b/core/lib/Thelia/Install/Database.php index 648a6431a..d17bd7c3d 100644 --- a/core/lib/Thelia/Install/Database.php +++ b/core/lib/Thelia/Install/Database.php @@ -40,21 +40,33 @@ class Database /** * Insert all sql needed in database + * Default insert /install/thelia.sql and /install/insert.sql * - * @param $dbName + * @param string $dbName Database name + * @param array $extraSqlFiles SQL Files uri to insert */ - public function insertSql($dbName = null) + public function insertSql($dbName = null, array $extraSqlFiles = null) { - if($dbName) { + if ($dbName) { $this->connection->query(sprintf("use %s", $dbName)); } $sql = array(); - $sql = array_merge( - $sql, - $this->prepareSql(file_get_contents(THELIA_ROOT . "/install/thelia.sql")), - $this->prepareSql(file_get_contents(THELIA_ROOT . "/install/insert.sql")) - ); + + if (null === $extraSqlFiles) { + $sql = array_merge( + $sql, + $this->prepareSql(file_get_contents(THELIA_ROOT . '/install/thelia.sql')), + $this->prepareSql(file_get_contents(THELIA_ROOT . '/install/insert.sql')) + ); + } else { + foreach ($extraSqlFiles as $fileToInsert) { + $sql = array_merge( + $sql, + $this->prepareSql(file_get_contents($fileToInsert)) + ); + } + } for ($i = 0; $i < count($sql); $i ++) { if (!empty($sql[$i])) { @@ -75,7 +87,7 @@ class Database $sql = trim($sql); $query = array(); - $tab = explode(";", $sql); + $tab = explode(";\n", $sql); for ($i=0; $i{intl l="Orders"} -