MAJ en Thelia 2.3.4
This commit is contained in:
190
CHANGELOG.md
190
CHANGELOG.md
@@ -1,3 +1,154 @@
|
|||||||
|
# 2.3.4
|
||||||
|
|
||||||
|
**WARNING** : Minimum PHP version for Thelia 2.3.4 is now **PHP 5.5**.
|
||||||
|
Do not upgrade if you're server is currently using a lower PHP version
|
||||||
|
|
||||||
|
- (related to #2422) Installation with PHP 7.1 is now working properly. The mcrypt dependency is now replaced by openssl
|
||||||
|
- (related to #2413) Requesting the view of a not visible product, category, contents, folder or brand now causes an HTTP 404 error instead of displaying the view
|
||||||
|
- (related to #2416) Favicon, store logo and e-mail banner are now managed from the back-office -> Configuration -> Store
|
||||||
|
- (related to #2420) The cheque instructions defined in the back-office were displayed only for en_US locales. This PR fixes this problem, the instructions are now displayed for every locale.
|
||||||
|
- (related to #2391) When creating a customer from the back offcie, the state field is now present.
|
||||||
|
- (related to #2384) Fix tinymce_lang guess helper
|
||||||
|
- (related to #2377) Added missing translation in OrderPayment.php
|
||||||
|
- (related to #2351) Changed ModelCriteriaTools to be less restrictive in checking column. The old code only checked if there was a translation available (a row present) and not the content of a column that could be NULL.
|
||||||
|
- (related to #2335) Fix behavior of translate page in back office : "custom_fallback" and "global_fallback" were ignored when "view_missing_traductions_only" was on
|
||||||
|
- (related to #2301) "view" authorization is now checked for Thelia feed list and last version number on the back-offcie home page
|
||||||
|
- (related to #2286) Fix AbstractExport array rewind bug
|
||||||
|
- (related to #2278) Fix i18n typo : Amñinistración => Administración
|
||||||
|
- (related to #2275) Fixed select option rendereing in render_form_field.html
|
||||||
|
- (related to #2273) Fixed number input in coupon percentage html5 fragment
|
||||||
|
- (related to #2262) success_url is now cosidered when deleting a cart_item
|
||||||
|
- (related to #2026) regexp significant characters are now escaped whe n processing URL parameters
|
||||||
|
- (related to #1949) $CONTENT_COUNT in folder loop now returns the number of visible contents, and not the number of all (including not visible) contents.
|
||||||
|
- (related to #1877) Update shipping-configuration-edit.html to escape markup in shipping zone name
|
||||||
|
- (related to #1876) Update form.html to escape coupon code HtML
|
||||||
|
- (related to #1875) Update coupon-update.html to escape coupon code HtML
|
||||||
|
- (related to #1822) To prevent token errors when maniplating cart items, the cart token is no longer refreshed in the delete token code
|
||||||
|
- (related to #1743) Back-Office template sale edit
|
||||||
|
- (related to #1717) The stock of a virtual product is now checked
|
||||||
|
- (related to #2414) In the cart, the first PSE image if nos displayed, if there is one. The product image is displayed otherwise.
|
||||||
|
- (related to #2408) Code style fixes and translations improvements
|
||||||
|
- (related to #2408) <br> cound now be used in text email templates to force a line break
|
||||||
|
- (related to #2272) Form fields error information are now saved in the global form error context, and remain available after a redirection.
|
||||||
|
- (related to #2276) Product loop fix: addOutputFields() method may now to manipulate fields that were set in associateValues()
|
||||||
|
- (related to #2293) performance improvement for calculating order total. This calculation uses now only one request instead of (1 + number of products).
|
||||||
|
- (related to #2345) fix and improvement of counting sub categories and sub folders. The number of request is reduced, and the visibility status of products or contents is now considered. Category and subcategory products are now deleted by dispatching a TheliaEvents::PRODUCT_DELETE instead of calling Product::delete()
|
||||||
|
- (related to #2349) New feature: It is now possible to send a test email message from the Preview tab of mailing template modification page
|
||||||
|
- (related to #2380) Fix for wrong product reference on cart and order-invoice pages
|
||||||
|
- (related to #2402) "Coupon" substitutions are now available in the templates
|
||||||
|
- (related to #2400) Back-office HTML typo
|
||||||
|
- (related to #2394) The customer state is now used to calculate cart taxes
|
||||||
|
- (related to #2357) When the resize mode is "none", and required image is bigger than original image in both dimensions, the image is now zoomed if allow_zoom is true.
|
||||||
|
- (related to #2403) Fix for wrong or missing types in ProductCloneEvent
|
||||||
|
- (related to #2363) Improved products templates features. 1) When a product's template is modified, only the obsolete attribute combinations are deleted, this is much better than deleting all attribute combinations. 2) When an attribute is removed from a template, all related products are also updated, and obsolete attribute combinations are removed. 3) When a feature is removed from a template, the related products are updated, and the feature is removed from the product. 4) The template management page now displays the related products and categories, making finding which products or categories uses the template easier. 5) It is now possible to duplicate a product template. 6) Product and Category loops have now a template_id parameter, to filter results on one ore more template IDs.
|
||||||
|
- (related to #2369) PHP7 related fix: $return was declared as string, and used as array
|
||||||
|
- (related to #2372) When an URL for a disabled language is invoked, the page in the disabled locale was displayed. The user is now redirected to the default language URL.
|
||||||
|
- (related to #2396) Fix for domain-based language selection
|
||||||
|
- (related to #2395) In RemoveXPercent coupon type, the discount is no longer rounded to 2 decimals.
|
||||||
|
- (related to #2389) `Thelia export --list-archiver` will not return an error if one of the supported archiver extensions is not installed
|
||||||
|
- (related to #2379) When creating a product, the default tax rule is used if none is defined in the ProductCreateEvent event.
|
||||||
|
- (related to #2378) When used in the back-office context (backend_context=1), the feature loop will return all features
|
||||||
|
- (related to #2296) <option> label margin using CSS is not working in IE and Safari, making category tree selection hard to use. &nbsp; is now used, via the `{option_offset l=n label='some label'}` Smarty custon function
|
||||||
|
- (related to #2375) Force an update of Cart model after deleting an item, so that the listeners will not notice the change
|
||||||
|
- (related to #2374) Image position field is now available in Carousel module configuration
|
||||||
|
- (related to #2365) en_US translation improvements
|
||||||
|
- (related to #2364) On the contact page, the map is now fetched using https
|
||||||
|
- (related to #2356) Parameter `product_count_visible_only` added to `category` loop
|
||||||
|
- (related to #2283) Typo which prevents to save the custom-css.less file in TinyMCE module
|
||||||
|
- (related to #2338) All exceptions are now logged in the Thelia log file
|
||||||
|
- (related to #2348) fix customer delete in back-offcie search view
|
||||||
|
- (related to #2339) Fix for #2337 to always get a correct LOOP_TOTAL
|
||||||
|
- (related to #2334) Fix "Class not found" in AbstractArchiver
|
||||||
|
- (related to #2327) Add cart success_url, which is missing for mobile
|
||||||
|
- (no related PR) Thelia version is now fetched using https insteade of http
|
||||||
|
- (related to #2326) Fix the "visible" argument of folder-path and category-path loops, which was not working after the first iteration. The code for the "depth" element was missing in these loops, and is now written.
|
||||||
|
- (related to #2325) Cart discount is now updated after login
|
||||||
|
- (related to #2323) Fix possible html break if the database contains a product that has multiple product sale element by default.
|
||||||
|
- (related to #2277) Module information is now displaying properly module information of 2.2 module.xml files, and specially authors.
|
||||||
|
- (related to #2309) Added missing hooks in back-office search results tables head and body
|
||||||
|
- (related to #2320) Fix the sorting feature in categories and folders back-office views: some sorting criteria, such as visible or ID where not implemented in the loops.
|
||||||
|
- (related to #2310) Fix for of array based loops extensions, to allow listeners to change array content.
|
||||||
|
- (related to #2312) Added order ID to 'customer.orders-table-row' hook parameters
|
||||||
|
- (related to #2313) The manual order is now working properly in the content loop.
|
||||||
|
- (related to #2308) Use service in ContainerAwareCommand to get URL instance. It will prevent further calls to this service to override request context.
|
||||||
|
- (related to #2291) Fix currency change to default where no currency in request. Change to default only if requested currency not exists.
|
||||||
|
- (related to #2287) Fix for not working decimals=0 in {format_number} or {format_money}
|
||||||
|
- (related to #2306) fr_FR translation imrpovement
|
||||||
|
- (related to #2303) en_US translation imrpovement
|
||||||
|
- (related to #2300) Back-office HTML typo
|
||||||
|
- (related to #2299) Back-office HTML tag typo for displaying current lang flag
|
||||||
|
- (related to #2295) Fix method initRequest on the ContainerAwareCommand
|
||||||
|
- (related to #2281) Fixed PECL extentions install script in docker setup
|
||||||
|
- (related to #2271) Invisible (off-line) categories are now available in coupon conditions and types
|
||||||
|
- (related to #2264) Check if php extension "dom" is installed (issue #2263)
|
||||||
|
- (related to #2265) Fix #2225 wrong version displayed in db update script (issue #2225)
|
||||||
|
- (related to #2266) Bad parsing of web version in DB update script (issue #2226)
|
||||||
|
- (related to #2259) Fixed "cart contains products" & "cart contains categories" coupon conditions
|
||||||
|
- (related to #2261) The manual order is now working properly in the product loop.
|
||||||
|
- (related to #2257) Fix for wrong order coupon amount
|
||||||
|
- (related to #2256) Check if a RemoveXAmount type coupon is valid for special offers
|
||||||
|
- (related to #2255) Moved php shebang in the right file
|
||||||
|
- (related to #2254) add parameter "module_code" to "modules.table-row" hook
|
||||||
|
- (related to #2238) New method BasePaymentModuleController::saveTransactionRef() to save order transaction reference
|
||||||
|
- (related to #2232) Moved to container-based infrastructure for Travis CI
|
||||||
|
- (related to #2235) Add `DISCOUNT_AMOUNT` variable to `order_coupon` loop
|
||||||
|
- (related to #2227) Fix for two problems with CART_FINDITEM event processing: 1) The CartEvent dispatched with CART_FINDITEM was the one received by Thelia\Action\Cart::addItem(), thus stopping event propagation will stop the whole cart add process. 2) Thelia\Action\Cart::findCartItem() was not aware of a cart item set in the event by event listeners with a higher priority, thus this cart item is always overwritten.
|
||||||
|
- (related to #2221) Completed default email template FR and EN translations
|
||||||
|
- (related to #2224) Added simple messages (no Message object required) processing to the MailerFactory, throug the sendSimpleEmailMessage() and createSimpleEmailMessage() methods. A new getMessageInstance() method has been added, to prevent direct usage of \Swift_Message::newInstance()
|
||||||
|
- (related to #2217) New feature: Protected and hidden modules
|
||||||
|
- (related to #2197) Pagination of coupon list
|
||||||
|
- (related to #2198) Cancel coupon usage on order cancel
|
||||||
|
- (related to #2190) Admin Home page statistics improvements
|
||||||
|
- (related to #2189) Performance improvement in feature-availability loop
|
||||||
|
- (related to #2188) A more effective way to solve issue free text feature problem (see #2061)
|
||||||
|
- (related to #2174) New PSR-6 implementation + thelia.cache service and smarty cache block
|
||||||
|
- (related to #2167) Add global variable `app` to Smarty to be consistent with Twig
|
||||||
|
- (related to #2165) Add replyTo parameter in mailer factory
|
||||||
|
- (related to #2081) Order Status improvements
|
||||||
|
- (related to #2164) New confirmation email option after customer creation
|
||||||
|
- (related to #2153) Lighten placeholders color to be more different than filled inputs
|
||||||
|
- (related to #2149) Fixed status_id parameter access
|
||||||
|
- (related to #2148) Added search by EAN code to product sale elements loop
|
||||||
|
- (related to #2146) Fix search in i18n fields when backend_context=1, and search improvements. The loop search system is imporved, by providing the StandardI18nFieldsSearchTrait, which manages searches in the standard internationalized fields (title, chapo, description and postscriptum). In the back-office, customer search is now in sentence (%term%) mode, to allow incomplete word matches, such as part of an email address.
|
||||||
|
- (related to #2140) Added missing "calendar" PHP extension to docker config
|
||||||
|
- (related to #2107) Add create function for AlphaNumStringType argument
|
||||||
|
- (related to #2082) Product and PSE references added to invoice template
|
||||||
|
- (related to #2093) Fix #1662 add of hooks in pdf email and account-order
|
||||||
|
- (related to #2106) Added order-invoice form hooks
|
||||||
|
- (related to #2109) Module routers priority improvement
|
||||||
|
- (related to #1912) Fix for feature loop with product filter
|
||||||
|
|
||||||
|
# 2.3.3
|
||||||
|
|
||||||
|
- (related to #2249) Fix identical queries in the productSaleElement loop and the Product loop
|
||||||
|
- (related to #2243) Fixed and optimized content and product loops
|
||||||
|
- (related to #2240) Fix #2229 : bad resource code in MailingSystemController class
|
||||||
|
- (related to #2239) Fix #2233 : customer profile update
|
||||||
|
- (related to #2237) Fixed cancelPayment method in BasePaymentModuleController class
|
||||||
|
- (related to #2231) Fix #2215 : loop pagination cache
|
||||||
|
- (related to #2230) Hook fixes
|
||||||
|
- (related to #2222) Fix duplicates in country loop when used with "with_area" argument
|
||||||
|
- (related to #2219) Fix coupons issues
|
||||||
|
- (related to #2214) Fix for #2213 : Nesting loops with the same argument set is now working
|
||||||
|
- (related to #2207) Add delimiter and enclosure for header insertion
|
||||||
|
- (related to #2206) Add reset array pointer if $data is an array.
|
||||||
|
- (related to #2205) Fixed sale edit form
|
||||||
|
- (related to #2204) Add isEmpty(), to check if $data is empty.
|
||||||
|
- (related to #2203) Check if $error exist, specific for submit type
|
||||||
|
- (related to #2202) Fix currency creation modal (The currency field is missing in the html template)
|
||||||
|
- (related to #2191) Update BO typo
|
||||||
|
|
||||||
|
# 2.3.2
|
||||||
|
|
||||||
|
- (related to #2182) Fix compatibility with sql_mode STRICT_ALL_TABLES
|
||||||
|
- (related to #2181) Fix CSV export cached file size
|
||||||
|
- (related to #2173) Fix customer discount apply on backoffice. The custome permanentr discount is also applied on the back office if the user is logged in front office
|
||||||
|
- (related to #2168) Fix router redirect to last rewriting_url
|
||||||
|
- (related to #2166) Fixed the update process when thelia.net is out of order
|
||||||
|
- (related to #2160) Added missing home.block 'class' parameter
|
||||||
|
- (related to #2157) Prevent an infinite loop in new product dialog
|
||||||
|
- (related to #2154) Add Test range dates exists before testing type
|
||||||
|
|
||||||
# 2.3.1
|
# 2.3.1
|
||||||
|
|
||||||
- (related to #2150) Fix form and validator translations
|
- (related to #2150) Fix form and validator translations
|
||||||
@@ -216,6 +367,29 @@
|
|||||||
- #1674 Add options ```free_text, exclude_free_text``` in FeatureValue loop
|
- #1674 Add options ```free_text, exclude_free_text``` in FeatureValue loop
|
||||||
- #1725 Add `weight` and `total_price_without_discount` attributes to the `{cart}` substitution, and some aliases to provide a better english syntax, or a more accurate name to existing attributes : `product_count`, alias of `count_product`, `item_count`, alias of `count_item`, `total_price_with_discount` alias of `total_price`, `total_taxed_price_with_discount` alias of `total_taxed_price`, `contains_virtual_product` alias of `is_virtual`, `total_tax_amount` alias of `total_vat`
|
- #1725 Add `weight` and `total_price_without_discount` attributes to the `{cart}` substitution, and some aliases to provide a better english syntax, or a more accurate name to existing attributes : `product_count`, alias of `count_product`, `item_count`, alias of `count_item`, `total_price_with_discount` alias of `total_price`, `total_taxed_price_with_discount` alias of `total_taxed_price`, `contains_virtual_product` alias of `is_virtual`, `total_tax_amount` alias of `total_vat`
|
||||||
|
|
||||||
|
|
||||||
|
# 2.2.6
|
||||||
|
|
||||||
|
- (related to #2240) Fix #2229 : bad resource code in MailingSystemController class
|
||||||
|
- (related to #2237) Fix cancelPayment method in BasePaymentModuleController class
|
||||||
|
- (related to #2231) Fix #2215 : loop pagination cache
|
||||||
|
- (related to #2219) Fix coupons issues
|
||||||
|
- (related to #2214) Fix for #2213 : Nesting loops with the same argument set is now working
|
||||||
|
- (related to #2208) Fix missing model on LoopResultRow
|
||||||
|
- (related to #2205) Fixed sale edit form
|
||||||
|
|
||||||
|
# 2.2.5
|
||||||
|
|
||||||
|
- (related to #2188) A more effective way to solve issue #2061
|
||||||
|
- #2194 Fix change currency on 2.2.x
|
||||||
|
|
||||||
|
# 2.2.4
|
||||||
|
|
||||||
|
- (related to #2182) Fix compatibility with sql_mode STRICT_ALL_TABLES
|
||||||
|
- (related to #2173) Fix customer discount apply on backoffice. The custome permanentr discount is also applied on the back office if the user is logged in front office
|
||||||
|
- (related to #2168) Router redirect to last rewriting_url
|
||||||
|
- (related to #2160) Added missing home.block 'class' parameter
|
||||||
|
|
||||||
# 2.2.3
|
# 2.2.3
|
||||||
|
|
||||||
- (related to #2147) Fixed help text display if show_label is false
|
- (related to #2147) Fixed help text display if show_label is false
|
||||||
@@ -461,6 +635,20 @@
|
|||||||
- Default border color of images resized with resize_mode="border" is now transparent instead of opaque white.
|
- Default border color of images resized with resize_mode="border" is now transparent instead of opaque white.
|
||||||
- The TemplateHelper class is deprecated. You should now use the thelia.template_helper service. TemplateHelperInterface has been introduced, so that modules may implement alternate versions
|
- The TemplateHelper class is deprecated. You should now use the thelia.template_helper service. TemplateHelperInterface has been introduced, so that modules may implement alternate versions
|
||||||
|
|
||||||
|
|
||||||
|
# 2.1.11
|
||||||
|
|
||||||
|
- (related to #2240) Fix #2229 : bad resource code in MailingSystemController class
|
||||||
|
- (related to #2237) Fixed cancelPayment method in BasePaymentModuleController class
|
||||||
|
- (related to #2231) Fix #2215 : loop pagination cache
|
||||||
|
- (related to #2214) Fix for #2213 : Nesting loops with the same argument set is now working
|
||||||
|
- (related to #2205) Fixed sale edit form
|
||||||
|
|
||||||
|
# 2.1.10
|
||||||
|
|
||||||
|
- (related to #2182) Fix compatibility with sql_mode STRICT_ALL_TABLES
|
||||||
|
- (related to #2173) Fix customer discount apply on backoffice. The custome permanentr discount is also applied on the back office if the user is logged in front office
|
||||||
|
|
||||||
# 2.1.9
|
# 2.1.9
|
||||||
|
|
||||||
- (related to #2144) Fix automatic configuration for the sql_mode
|
- (related to #2144) Fix automatic configuration for the sql_mode
|
||||||
@@ -523,7 +711,7 @@
|
|||||||
- Klik&Pay is no more a submodule
|
- Klik&Pay is no more a submodule
|
||||||
- default category's parent is now 0
|
- default category's parent is now 0
|
||||||
- check specific role in security module instead of checking if a user is logged in
|
- check specific role in security module instead of checking if a user is logged in
|
||||||
- add a customer page parameter for the order loop on the customer page
|
- add a customer page parameter for the order loop on the customer page
|
||||||
- keep break line in ACE editor
|
- keep break line in ACE editor
|
||||||
|
|
||||||
# 2.1.4
|
# 2.1.4
|
||||||
|
|||||||
73
Readme.md
73
Readme.md
@@ -6,9 +6,11 @@ Readme
|
|||||||
|
|
||||||
Thelia
|
Thelia
|
||||||
------
|
------
|
||||||
[](https://travis-ci.org/thelia/thelia) [](https://packagist.org/packages/thelia/thelia) [](https://scrutinizer-ci.com/g/thelia/thelia/)
|
[](https://travis-ci.org/thelia/thelia)
|
||||||
|
[](https://packagist.org/packages/thelia/thelia)
|
||||||
|
[](https://scrutinizer-ci.com/g/thelia/thelia/)
|
||||||
|
|
||||||
[Thelia](http://thelia.net/) is an open source tool for creating e-business websites and managing online content. This software is published under LGPL.
|
[Thelia](https://thelia.net/) is an open source tool for creating e-business websites and managing online content. This software is published under LGPL.
|
||||||
|
|
||||||
This is the new major version of Thelia.
|
This is the new major version of Thelia.
|
||||||
|
|
||||||
@@ -17,13 +19,16 @@ A repository containing all thelia modules is available at this address : https:
|
|||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* PHP 5.4
|
* PHP 5.5
|
||||||
* Required extensions :
|
* Required extensions :
|
||||||
* PDO_Mysql
|
* PDO_Mysql
|
||||||
* mcrypt
|
* openssl
|
||||||
* intl
|
* intl
|
||||||
* gd
|
* gd
|
||||||
* curl
|
* curl
|
||||||
|
* calendar
|
||||||
|
* dom
|
||||||
|
* fileinfo
|
||||||
* safe_mode off
|
* safe_mode off
|
||||||
* memory_limit at least 128M, preferably 256.
|
* memory_limit at least 128M, preferably 256.
|
||||||
* post\_max\_size 20M
|
* post\_max\_size 20M
|
||||||
@@ -63,6 +68,7 @@ Thelia's archive builder's needs external libraries.
|
|||||||
For zip archives, you need PECL zip. See [PHP Doc](http://php.net/manual/en/zip.installation.php)
|
For zip archives, you need PECL zip. See [PHP Doc](http://php.net/manual/en/zip.installation.php)
|
||||||
|
|
||||||
For tar archives, you need PECL phar. Moreover, you need to deactivate php.ini option "phar.readonly":
|
For tar archives, you need PECL phar. Moreover, you need to deactivate php.ini option "phar.readonly":
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
phar.readonly = Off
|
phar.readonly = Off
|
||||||
```
|
```
|
||||||
@@ -76,20 +82,25 @@ For tar.gz archives, you need tar's dependencies and the extension "zlib". See [
|
|||||||
You can get the sources from git and then let composer install dependencies, or use composer to install the whole thelia project into a specific directory
|
You can get the sources from git and then let composer install dependencies, or use composer to install the whole thelia project into a specific directory
|
||||||
|
|
||||||
### Using git for download and composer for dependencies
|
### Using git for download and composer for dependencies
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ git clone --recursive https://github.com/thelia/thelia path
|
$ git clone --recursive https://github.com/thelia/thelia path
|
||||||
$ cd path
|
$ cd path
|
||||||
$ git checkout 2.3.1 (2.2.3 or 2.1.9)
|
$ git checkout 2.3.4 (2.2.6 or 2.1.11)
|
||||||
$ curl -sS https://getcomposer.org/installer | php
|
$ curl -sS https://getcomposer.org/installer | php
|
||||||
$ php composer.phar install
|
$ php composer.phar install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using composer for both download and dependencies
|
### Using composer for both download and dependencies
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ curl -sS https://getcomposer.org/installer | php
|
$ curl -sS https://getcomposer.org/installer | php
|
||||||
$ php composer.phar create-project thelia/thelia path/ 2.3.1 (2.2.3 or 2.1.9)
|
$ php composer.phar create-project thelia/thelia path/ 2.3.4 (2.2.6 or 2.1.11)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If something goes wrong during the install process, you can restart Thelia install wizard with
|
||||||
|
the following command : `php composer.phar run-script post-create-project-cmd`
|
||||||
|
|
||||||
## Install it
|
## Install it
|
||||||
|
|
||||||
You can install Thelia by two different way
|
You can install Thelia by two different way
|
||||||
@@ -106,10 +117,10 @@ The install wizard in accessible with your favorite browser :
|
|||||||
http://yourdomain.tld/[/subdomain_if_needed]/install
|
http://yourdomain.tld/[/subdomain_if_needed]/install
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, I have thelia downloaded at http://thelia.net and my vhost is correctly configured, I have to reach this address :
|
For example, I have thelia downloaded at https://thelia.net and my vhost is correctly configured, I have to reach this address :
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
http://thelia.net/install
|
https://thelia.net/install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using cli tools
|
### Using cli tools
|
||||||
@@ -118,6 +129,12 @@ http://thelia.net/install
|
|||||||
$ php Thelia thelia:install
|
$ php Thelia thelia:install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or if you use a Thelia project :
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ php composer.phar run-script post-create-project-cmd
|
||||||
|
```
|
||||||
|
|
||||||
You just have to follow all instructions.
|
You just have to follow all instructions.
|
||||||
|
|
||||||
### Docker and docker compose
|
### Docker and docker compose
|
||||||
@@ -126,36 +143,40 @@ This repo contains all the configuration needed to run Thelia with docker and do
|
|||||||
|
|
||||||
It requires obviously [docker](https://docker.com/) and [docker-compose](http://docs.docker.com/compose/)
|
It requires obviously [docker](https://docker.com/) and [docker-compose](http://docs.docker.com/compose/)
|
||||||
|
|
||||||
How to start the configuration :
|
To install Thelia within Docker, run :
|
||||||
|
|
||||||
```
|
```
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
docker-compose exec web composer install
|
||||||
|
docker-compose exec web php Thelia thelia:install
|
||||||
```
|
```
|
||||||
|
|
||||||
tip : create an alias for docker-compose, it's boring to write it all the time
|
This will prompt you for database information. Enter the following :
|
||||||
|
|
||||||
All the script are launched through docker. For examples :
|
|
||||||
|
|
||||||
```
|
|
||||||
docker exec -it thelia_web_1 php Thelia cache:clear
|
|
||||||
docker exec -it thelia_web_1 php setup/faker.php
|
|
||||||
docker exec -it thelia_web_1 unit-tests.sh
|
|
||||||
docker exec -it thelia_web_1 php composer.phar install
|
|
||||||
```
|
|
||||||
|
|
||||||
Database information :
|
|
||||||
|
|
||||||
* host : mariaDB
|
* host : mariaDB
|
||||||
|
* port : 3306 (default)
|
||||||
|
* name : thelia
|
||||||
* login : root
|
* login : root
|
||||||
* password : toor
|
* password : toor
|
||||||
|
|
||||||
Once started, you can access it with your browser at this url : http://127.0.0.1:8080 and phpmyadmin : http://127.0.0.1:8081
|
tip : create an alias for docker-compose, it's boring to write it all the time
|
||||||
|
|
||||||
What is missing :
|
All the scripts can be launched through docker (or the corresponding `docker-compose exec web ...` command. For example :
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -it thelia_web_1 composer install
|
||||||
|
docker exec -it thelia_web_1 php Thelia cache:clear
|
||||||
|
docker exec -it thelia_web_1 php setup/faker.php
|
||||||
|
docker exec -it thelia_web_1 unit-tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Once started, you can open your local Thelia website at [127.0.0.1:8080](http://127.0.0.1:8080) and your phpMyAdmin installation at [127.0.0.1:8081](http://127.0.0.1:8081).
|
||||||
|
|
||||||
|
What is missing :
|
||||||
|
|
||||||
* confguration for export compression (zip, gzip, etc)
|
* confguration for export compression (zip, gzip, etc)
|
||||||
|
|
||||||
Obviously you can modify all the configuration for your own case, for example the php version or add environment variable for the database configuration. Each time you modify the configuration, you have to rebuild it :
|
Obviously you can modify all the configuration for your own case, for example the php version or add environment variable for the database configuration. Each time you modify the configuration, you have to rebuild it :
|
||||||
|
|
||||||
```
|
```
|
||||||
docker-compose build --no-cache
|
docker-compose build --no-cache
|
||||||
@@ -170,7 +191,7 @@ Thelia documentation is available at http://doc.thelia.net
|
|||||||
Roadmap
|
Roadmap
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The Roadmap is available at http://thelia.net/community/roadmap
|
The Roadmap is available at https://thelia.net/community/roadmap
|
||||||
|
|
||||||
|
|
||||||
Contribute
|
Contribute
|
||||||
@@ -193,4 +214,4 @@ To run tests (phpunit required) :
|
|||||||
$ phpunit
|
$ phpunit
|
||||||
```
|
```
|
||||||
|
|
||||||
We still have lot of work to achieve but enjoy this part.
|
We still have lot of work to achieve but enjoy this part.
|
||||||
|
|||||||
191
bin/lessc
191
bin/lessc
@@ -1,191 +0,0 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once dirname(__FILE__) . '/../lib/Less/Autoloader.php';
|
|
||||||
Less_Autoloader::register();
|
|
||||||
|
|
||||||
// Create our environment
|
|
||||||
$env = array('compress' => false, 'relativeUrls' => false);
|
|
||||||
$silent = false;
|
|
||||||
$watch = false;
|
|
||||||
$rootpath = '';
|
|
||||||
|
|
||||||
// Check for arguments
|
|
||||||
array_shift($argv);
|
|
||||||
if (!count($argv)) {
|
|
||||||
$argv[] = '-h';
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse arguments
|
|
||||||
foreach ($argv as $key => $arg) {
|
|
||||||
if (preg_match('/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i', $arg, $matches)) {
|
|
||||||
$option = $matches[1];
|
|
||||||
$value = isset($matches[2]) ? $matches[2] : false;
|
|
||||||
unset($argv[$key]);
|
|
||||||
|
|
||||||
switch ($option) {
|
|
||||||
case 'h':
|
|
||||||
case 'help':
|
|
||||||
echo <<<EOD
|
|
||||||
Usage: lessc [options] sources [destination]
|
|
||||||
|
|
||||||
-h, --help Print help (this message) and exit.
|
|
||||||
-s, --silent Suppress output of error messages.
|
|
||||||
-v, --version Print version number and exit.
|
|
||||||
-x, --compress Compress output by removing some whitespaces.
|
|
||||||
--include-path=PATHS Set include paths. Separated by `:'. Use `;' on Windows.
|
|
||||||
--strict-imports Force evaluation of imports.
|
|
||||||
-sm=on|off Turn on or off strict math, where in strict mode, math
|
|
||||||
--strict-math=on|off requires brackets. This option may default to on and then
|
|
||||||
be removed in the future.
|
|
||||||
-su=on|off Allow mixed units, e.g. 1px+1em or 1px*1px which have units
|
|
||||||
--strict-units=on|off that cannot be represented.
|
|
||||||
-ru, --relative-urls re-write relative urls to the base less file.
|
|
||||||
-rp, --rootpath=URL Set rootpath for url rewriting in relative imports and urls.
|
|
||||||
Works with or without the relative-urls option.
|
|
||||||
-w, --watch Watch input files for changes.
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
exit;
|
|
||||||
case 's':
|
|
||||||
case 'silent':
|
|
||||||
$silent = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
case 'watch':
|
|
||||||
$watch = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
case 'version':
|
|
||||||
echo "lessc " . Less_Version::version . " (less.php)\n\n";
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 'rp':
|
|
||||||
case 'rootpath':
|
|
||||||
$rootpath = $value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
//parser options
|
|
||||||
case 'compress':
|
|
||||||
$env['compress'] = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ru':
|
|
||||||
case 'relative-urls':
|
|
||||||
$env['relativeUrls'] = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'su':
|
|
||||||
case 'strict-units':
|
|
||||||
$env['strictUnits'] = ($value === 'on');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'sm':
|
|
||||||
case 'strict-math':
|
|
||||||
$env['strictMath'] = ($value === 'on');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'x':
|
|
||||||
case 'include-path':
|
|
||||||
$env['import_dirs'] = preg_split('#;|\:#', $value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($argv) > 1) {
|
|
||||||
$output = array_pop($argv);
|
|
||||||
$inputs = $argv;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$inputs = $argv;
|
|
||||||
$output = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count($inputs)) {
|
|
||||||
echo("lessc: no input files\n");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($watch) {
|
|
||||||
if (!$output) {
|
|
||||||
echo("lessc: you must specify the output file if --watch is given\n");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$lastAction = 0;
|
|
||||||
|
|
||||||
echo("lessc: watching input files\n");
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
clearstatcache();
|
|
||||||
|
|
||||||
$updated = false;
|
|
||||||
foreach ($inputs as $input) {
|
|
||||||
if ($input == '-') {
|
|
||||||
if (count($inputs) == 1) {
|
|
||||||
echo("lessc: during watching files is not possible to watch stdin\n");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filemtime($input) > $lastAction) {
|
|
||||||
$updated = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($updated) {
|
|
||||||
$lastAction = time();
|
|
||||||
$parser = new Less_Parser($env);
|
|
||||||
foreach ($inputs as $input) {
|
|
||||||
try {
|
|
||||||
$parser->parseFile($input, $rootpath);
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
echo("lessc: " . $e->getMessage() . " \n");
|
|
||||||
continue; // Invalid processing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents($output, $parser->getCss());
|
|
||||||
echo("lessc: output file recompiled\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$parser = new Less_Parser($env);
|
|
||||||
foreach ($inputs as $input) {
|
|
||||||
if ($input == '-') {
|
|
||||||
$content = file_get_contents('php://stdin');
|
|
||||||
$parser->parse($content);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
$parser->parseFile($input);
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
if (!$silent) {
|
|
||||||
echo("lessc: " . ((string)$e) . " \n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output) {
|
|
||||||
file_put_contents($output, $parser->getCss());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
echo $parser->getCss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
47
bin/phpunit
47
bin/phpunit
@@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
* This file is part of PHPUnit.
|
|
||||||
*
|
|
||||||
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (version_compare('5.3.3', PHP_VERSION, '>')) {
|
|
||||||
fwrite(
|
|
||||||
STDERR,
|
|
||||||
'This version of PHPUnit requires PHP 5.3.3; using the latest version of PHP is highly recommended.' . PHP_EOL
|
|
||||||
);
|
|
||||||
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ini_get('date.timezone')) {
|
|
||||||
ini_set('date.timezone', 'UTC');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) {
|
|
||||||
if (file_exists($file)) {
|
|
||||||
define('PHPUNIT_COMPOSER_INSTALL', $file);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($file);
|
|
||||||
|
|
||||||
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
|
|
||||||
fwrite(STDERR,
|
|
||||||
'You need to set up the project dependencies using the following commands:' . PHP_EOL .
|
|
||||||
'wget http://getcomposer.org/composer.phar' . PHP_EOL .
|
|
||||||
'php composer.phar install' . PHP_EOL
|
|
||||||
);
|
|
||||||
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require PHPUNIT_COMPOSER_INSTALL;
|
|
||||||
|
|
||||||
PHPUnit_TextUI_Command::main();
|
|
||||||
1
bin/phpunit
Symbolic link
1
bin/phpunit
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../core/vendor/phpunit/phpunit/phpunit
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
include('propel.php');
|
|
||||||
1
bin/propel
Symbolic link
1
bin/propel
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../core/vendor/propel/propel/bin/propel
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.4",
|
"php": ">=5.5",
|
||||||
"ircmaxell/password-compat": "1.0.*",
|
"ircmaxell/password-compat": "1.0.*",
|
||||||
"psr/log": "1.0",
|
"psr/log": "1.0",
|
||||||
"symfony/config": "2.8.*",
|
"symfony/config": "2.8.*",
|
||||||
@@ -62,9 +62,7 @@
|
|||||||
"ramsey/array_column": "~1.1",
|
"ramsey/array_column": "~1.1",
|
||||||
"propel/propel": "dev-thelia-2.3",
|
"propel/propel": "dev-thelia-2.3",
|
||||||
"commerceguys/addressing": "0.8.*",
|
"commerceguys/addressing": "0.8.*",
|
||||||
"thelia/paypal-module": "~2.0.0",
|
"symfony/cache": "~3.1.0"
|
||||||
"thelia/take-customer-account-module": "~1.0",
|
|
||||||
"thelia/order-creation-module": "~1.0"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fzaninotto/faker": "1.5.*",
|
"fzaninotto/faker": "1.5.*",
|
||||||
|
|||||||
306
composer.lock
generated
306
composer.lock
generated
@@ -4,8 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "3ce4f9f2d0b61f10ae68436b457457c1",
|
"hash": "c7aa4c8921650410fee007feabe9f28e",
|
||||||
"content-hash": "c9d254f8817a0e7a6db9cdacb6be6bba",
|
"content-hash": "b11e72673bc4c91ff8dae278a174c7d1",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "commerceguys/addressing",
|
"name": "commerceguys/addressing",
|
||||||
@@ -291,7 +291,6 @@
|
|||||||
"html2pdf",
|
"html2pdf",
|
||||||
"pdf"
|
"pdf"
|
||||||
],
|
],
|
||||||
"abandoned": "spipu/html2pdf",
|
|
||||||
"time": "2013-09-13 12:23:43"
|
"time": "2013-09-13 12:23:43"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -347,7 +346,6 @@
|
|||||||
"TCPDF",
|
"TCPDF",
|
||||||
"pdf"
|
"pdf"
|
||||||
],
|
],
|
||||||
"abandoned": "tecnickcom/tcpdf",
|
|
||||||
"time": "2013-09-12 17:00:40"
|
"time": "2013-09-12 17:00:40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -753,6 +751,52 @@
|
|||||||
},
|
},
|
||||||
"time": "2016-01-26 14:41:16"
|
"time": "2016-01-26 14:41:16"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/cache",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/cache.git",
|
||||||
|
"reference": "9e66031f41fbbdda45ee11e93c45d480ccba3eb3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/cache/zipball/9e66031f41fbbdda45ee11e93c45d480ccba3eb3",
|
||||||
|
"reference": "9e66031f41fbbdda45ee11e93c45d480ccba3eb3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Cache\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "http://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for caching libraries",
|
||||||
|
"keywords": [
|
||||||
|
"cache",
|
||||||
|
"psr",
|
||||||
|
"psr-6"
|
||||||
|
],
|
||||||
|
"time": "2015-12-11 02:52:07"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -1202,6 +1246,72 @@
|
|||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-01-12 17:46:01"
|
"time": "2016-01-12 17:46:01"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/cache",
|
||||||
|
"version": "v3.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/cache.git",
|
||||||
|
"reference": "5656882318413f029fcce69ccc865daa16f8d35a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/cache/zipball/5656882318413f029fcce69ccc865daa16f8d35a",
|
||||||
|
"reference": "5656882318413f029fcce69ccc865daa16f8d35a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.5.9",
|
||||||
|
"psr/cache": "~1.0",
|
||||||
|
"psr/log": "~1.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/cache-implementation": "1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"cache/integration-tests": "dev-master",
|
||||||
|
"doctrine/cache": "~1.6",
|
||||||
|
"predis/predis": "~1.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/polyfill-apcu": "For using ApcuAdapter on HHVM"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.1-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Cache\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony implementation of PSR-6",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"caching",
|
||||||
|
"psr6"
|
||||||
|
],
|
||||||
|
"time": "2016-05-25 07:47:04"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/class-loader",
|
"name": "symfony/class-loader",
|
||||||
"version": "v2.8.2",
|
"version": "v2.8.2",
|
||||||
@@ -2001,7 +2111,6 @@
|
|||||||
"icu",
|
"icu",
|
||||||
"intl"
|
"intl"
|
||||||
],
|
],
|
||||||
"abandoned": "symfony/intl",
|
|
||||||
"time": "2013-06-03 18:32:07"
|
"time": "2013-06-03 18:32:07"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3147,54 +3256,6 @@
|
|||||||
"description": "php 5.4 currency tools",
|
"description": "php 5.4 currency tools",
|
||||||
"time": "2015-11-05 16:15:32"
|
"time": "2015-11-05 16:15:32"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "thelia/installer",
|
|
||||||
"version": "1.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/thelia/installer.git",
|
|
||||||
"reference": "da27ff8bc633452913590ee5bc26ee4c79ff61ee"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/thelia/installer/zipball/da27ff8bc633452913590ee5bc26ee4c79ff61ee",
|
|
||||||
"reference": "da27ff8bc633452913590ee5bc26ee4c79ff61ee",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"composer-plugin-api": "^1.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"composer/composer": "1.0.*@dev"
|
|
||||||
},
|
|
||||||
"type": "composer-plugin",
|
|
||||||
"extra": {
|
|
||||||
"class": "Thelia\\Composer\\TheliaInstallerPlugin"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": {
|
|
||||||
"Thelia\\Composer": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL V3"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Manuel Raynaud",
|
|
||||||
"email": "raynaud.manu@gmail.com",
|
|
||||||
"homepage": "https://github.com/lunika"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "custom installer for Thelia.",
|
|
||||||
"keywords": [
|
|
||||||
"Thelia",
|
|
||||||
"Thelia-module",
|
|
||||||
"Thelia-template"
|
|
||||||
],
|
|
||||||
"time": "2015-06-11 14:04:43"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "thelia/math-tools",
|
"name": "thelia/math-tools",
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -3235,95 +3296,6 @@
|
|||||||
],
|
],
|
||||||
"description": "Number management library",
|
"description": "Number management library",
|
||||||
"time": "2015-11-05 15:52:55"
|
"time": "2015-11-05 15:52:55"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "thelia/order-creation-module",
|
|
||||||
"version": "1.4",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/thelia-modules/OrderCreation.git",
|
|
||||||
"reference": "27904242efb0a1fbec92f977949f766176f2d083"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/thelia-modules/OrderCreation/zipball/27904242efb0a1fbec92f977949f766176f2d083",
|
|
||||||
"reference": "27904242efb0a1fbec92f977949f766176f2d083",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"thelia/installer": "~1.1"
|
|
||||||
},
|
|
||||||
"type": "thelia-module",
|
|
||||||
"extra": {
|
|
||||||
"installer-name": "OrderCreation"
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-3.0+"
|
|
||||||
],
|
|
||||||
"time": "2015-09-29 15:23:31"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "thelia/paypal-module",
|
|
||||||
"version": "2.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/thelia-modules/Paypal.git",
|
|
||||||
"reference": "113b1314c11e7e4a41d540698ea39766ec622340"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/thelia-modules/Paypal/zipball/113b1314c11e7e4a41d540698ea39766ec622340",
|
|
||||||
"reference": "113b1314c11e7e4a41d540698ea39766ec622340",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"thelia/installer": "~1.0"
|
|
||||||
},
|
|
||||||
"type": "thelia-module",
|
|
||||||
"extra": {
|
|
||||||
"installer-name": "Paypal"
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL V3"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Thelia",
|
|
||||||
"email": "info@thelia.net",
|
|
||||||
"homepage": "https://github.com/thelia-modules"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Paypal module for Thelia ecommerce solution",
|
|
||||||
"time": "2016-01-14 15:33:37"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "thelia/take-customer-account-module",
|
|
||||||
"version": "1.1.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/thelia-modules/TakeCustomerAccount.git",
|
|
||||||
"reference": "68c0aa16fea905c4d4fbb2d9dd9e9ed1700fdee8"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/thelia-modules/TakeCustomerAccount/zipball/68c0aa16fea905c4d4fbb2d9dd9e9ed1700fdee8",
|
|
||||||
"reference": "68c0aa16fea905c4d4fbb2d9dd9e9ed1700fdee8",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"thelia/installer": "~1.1"
|
|
||||||
},
|
|
||||||
"type": "thelia-module",
|
|
||||||
"extra": {
|
|
||||||
"installer-name": "TakeCustomerAccount"
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-3.0+"
|
|
||||||
],
|
|
||||||
"time": "2016-02-22 21:26:29"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
@@ -4328,6 +4300,54 @@
|
|||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"time": "2014-12-24 09:51:48"
|
"time": "2014-12-24 09:51:48"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "thelia/installer",
|
||||||
|
"version": "1.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thelia/installer.git",
|
||||||
|
"reference": "da27ff8bc633452913590ee5bc26ee4c79ff61ee"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thelia/installer/zipball/da27ff8bc633452913590ee5bc26ee4c79ff61ee",
|
||||||
|
"reference": "da27ff8bc633452913590ee5bc26ee4c79ff61ee",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"composer-plugin-api": "^1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"composer/composer": "1.0.*@dev"
|
||||||
|
},
|
||||||
|
"type": "composer-plugin",
|
||||||
|
"extra": {
|
||||||
|
"class": "Thelia\\Composer\\TheliaInstallerPlugin"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Thelia\\Composer": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL V3"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Manuel Raynaud",
|
||||||
|
"email": "raynaud.manu@gmail.com",
|
||||||
|
"homepage": "https://github.com/lunika"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "custom installer for Thelia.",
|
||||||
|
"keywords": [
|
||||||
|
"Thelia",
|
||||||
|
"Thelia-module",
|
||||||
|
"Thelia-template"
|
||||||
|
],
|
||||||
|
"time": "2015-06-11 14:04:43"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
@@ -4338,7 +4358,7 @@
|
|||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=5.4"
|
"php": ">=5.5"
|
||||||
},
|
},
|
||||||
"platform-dev": []
|
"platform-dev": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,16 @@ A repository containing all thelia modules is available at this address : https:
|
|||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* php 5.4
|
* php 5.5
|
||||||
* Required extensions :
|
* Required extensions :
|
||||||
* PDO_Mysql
|
* PDO_Mysql
|
||||||
* mcrypt
|
* openssl
|
||||||
* intl
|
* intl
|
||||||
* gd
|
* gd
|
||||||
* curl
|
* curl
|
||||||
|
* calendar
|
||||||
|
* dom
|
||||||
|
* fileinfo
|
||||||
* safe_mode off
|
* safe_mode off
|
||||||
* memory_limit at least 128M, preferably 256.
|
* memory_limit at least 128M, preferably 256.
|
||||||
* post_max_size 20M
|
* post_max_size 20M
|
||||||
|
|||||||
1
core/Thelia
Normal file → Executable file
1
core/Thelia
Normal file → Executable file
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
if (php_sapi_name() != 'cli') {
|
if (php_sapi_name() != 'cli') {
|
||||||
|
|||||||
@@ -55,7 +55,8 @@
|
|||||||
"smarty/smarty": "3.1.20",
|
"smarty/smarty": "3.1.20",
|
||||||
"ramsey/array_column": "~1.1",
|
"ramsey/array_column": "~1.1",
|
||||||
"propel/propel": "dev-thelia-2.3",
|
"propel/propel": "dev-thelia-2.3",
|
||||||
"commerceguys/addressing": "0.8.*"
|
"commerceguys/addressing": "0.8.*",
|
||||||
|
"symfony/cache": "~3.1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fzaninotto/faker": "1.5.*",
|
"fzaninotto/faker": "1.5.*",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace Thelia\Action;
|
|||||||
|
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Thelia\Core\Event\Brand\BrandCreateEvent;
|
use Thelia\Core\Event\Brand\BrandCreateEvent;
|
||||||
use Thelia\Core\Event\Brand\BrandDeleteEvent;
|
use Thelia\Core\Event\Brand\BrandDeleteEvent;
|
||||||
use Thelia\Core\Event\Brand\BrandToggleVisibilityEvent;
|
use Thelia\Core\Event\Brand\BrandToggleVisibilityEvent;
|
||||||
@@ -21,6 +22,7 @@ use Thelia\Core\Event\Brand\BrandUpdateEvent;
|
|||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
use Thelia\Core\Event\UpdatePositionEvent;
|
use Thelia\Core\Event\UpdatePositionEvent;
|
||||||
use Thelia\Core\Event\UpdateSeoEvent;
|
use Thelia\Core\Event\UpdateSeoEvent;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
use Thelia\Model\Brand as BrandModel;
|
use Thelia\Model\Brand as BrandModel;
|
||||||
use Thelia\Model\BrandQuery;
|
use Thelia\Model\BrandQuery;
|
||||||
|
|
||||||
@@ -121,6 +123,36 @@ class Brand extends BaseAction implements EventSubscriberInterface
|
|||||||
$this->genericUpdatePosition(BrandQuery::create(), $event, $dispatcher);
|
$this->genericUpdatePosition(BrandQuery::create(), $event, $dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if is a brand view and if brand_id is visible
|
||||||
|
*
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function viewCheck(ViewCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if ($event->getView() == 'brand') {
|
||||||
|
$brand = BrandQuery::create()
|
||||||
|
->filterById($event->getViewId())
|
||||||
|
->filterByVisible(1)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
if ($brand == 0) {
|
||||||
|
$dispatcher->dispatch(TheliaEvents::VIEW_BRAND_ID_NOT_VISIBLE, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public function viewBrandIdNotVisible(ViewCheckEvent $event)
|
||||||
|
{
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@@ -135,6 +167,9 @@ class Brand extends BaseAction implements EventSubscriberInterface
|
|||||||
|
|
||||||
TheliaEvents::BRAND_UPDATE_POSITION => array('updatePosition', 128),
|
TheliaEvents::BRAND_UPDATE_POSITION => array('updatePosition', 128),
|
||||||
TheliaEvents::BRAND_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
TheliaEvents::BRAND_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
||||||
|
|
||||||
|
TheliaEvents::VIEW_CHECK => array('viewCheck', 128),
|
||||||
|
TheliaEvents::VIEW_BRAND_ID_NOT_VISIBLE => array('viewBrandIdNotVisible', 128),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace Thelia\Action;
|
namespace Thelia\Action;
|
||||||
|
|
||||||
|
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\Filesystem\Filesystem;
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
use Thelia\Core\Event\Cache\CacheEvent;
|
use Thelia\Core\Event\Cache\CacheEvent;
|
||||||
@@ -24,8 +25,23 @@ use Thelia\Core\Event\TheliaEvents;
|
|||||||
*/
|
*/
|
||||||
class Cache extends BaseAction implements EventSubscriberInterface
|
class Cache extends BaseAction implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
|
/** @var AdapterInterface */
|
||||||
|
protected $adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CacheListener constructor.
|
||||||
|
* @param AdapterInterface $adapter
|
||||||
|
*/
|
||||||
|
public function __construct(AdapterInterface $adapter)
|
||||||
|
{
|
||||||
|
$this->adapter = $adapter;
|
||||||
|
}
|
||||||
|
|
||||||
public function cacheClear(CacheEvent $event)
|
public function cacheClear(CacheEvent $event)
|
||||||
{
|
{
|
||||||
|
// clear cache on thelia.cache service
|
||||||
|
$this->adapter->clear();
|
||||||
|
|
||||||
$dir = $event->getDir();
|
$dir = $event->getDir();
|
||||||
|
|
||||||
$fs = new Filesystem();
|
$fs = new Filesystem();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use Thelia\Core\Event\Cart\CartRestoreEvent;
|
|||||||
use Thelia\Core\Event\Cart\CartEvent;
|
use Thelia\Core\Event\Cart\CartEvent;
|
||||||
use Thelia\Core\Event\Currency\CurrencyChangeEvent;
|
use Thelia\Core\Event\Currency\CurrencyChangeEvent;
|
||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
|
use Thelia\Exception\TheliaProcessException;
|
||||||
use Thelia\Model\Base\CustomerQuery;
|
use Thelia\Model\Base\CustomerQuery;
|
||||||
use Thelia\Model\Base\ProductSaleElementsQuery;
|
use Thelia\Model\Base\ProductSaleElementsQuery;
|
||||||
use Thelia\Model\Currency as CurrencyModel;
|
use Thelia\Model\Currency as CurrencyModel;
|
||||||
@@ -100,9 +101,11 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
|||||||
$productId = $event->getProduct();
|
$productId = $event->getProduct();
|
||||||
|
|
||||||
// Search for an identical item in the cart
|
// Search for an identical item in the cart
|
||||||
$dispatcher->dispatch(TheliaEvents::CART_FINDITEM, $event);
|
$findItemEvent = clone $event;
|
||||||
|
|
||||||
$cartItem = $event->getCartItem();
|
$dispatcher->dispatch(TheliaEvents::CART_FINDITEM, $findItemEvent);
|
||||||
|
|
||||||
|
$cartItem = $findItemEvent->getCartItem();
|
||||||
|
|
||||||
if ($cartItem === null || $newness) {
|
if ($cartItem === null || $newness) {
|
||||||
$productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId);
|
$productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId);
|
||||||
@@ -111,6 +114,9 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
|||||||
$productPrices = $productSaleElements->getPricesByCurrency($currency, $discount);
|
$productPrices = $productSaleElements->getPricesByCurrency($currency, $discount);
|
||||||
|
|
||||||
$cartItem = $this->doAddItem($dispatcher, $cart, $productId, $productSaleElements, $quantity, $productPrices);
|
$cartItem = $this->doAddItem($dispatcher, $cart, $productId, $productSaleElements, $quantity, $productPrices);
|
||||||
|
} else {
|
||||||
|
// We did no find any PSE... Something is wrong with the DB, just throw an exception.
|
||||||
|
throw new TheliaProcessException("This item cannot be added to the cart: no matching product sale element was found.");
|
||||||
}
|
}
|
||||||
} elseif ($append && $cartItem !== null) {
|
} elseif ($append && $cartItem !== null) {
|
||||||
$cartItem->addQuantity($quantity)->save();
|
$cartItem->addQuantity($quantity)->save();
|
||||||
@@ -133,6 +139,10 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
|||||||
->filterByCartId($cart->getId())
|
->filterByCartId($cart->getId())
|
||||||
->filterById($cartItemId)
|
->filterById($cartItemId)
|
||||||
->delete();
|
->delete();
|
||||||
|
|
||||||
|
// Force an update of the Cart object to provide
|
||||||
|
// to other listeners an updated CartItem collection.
|
||||||
|
$cart->clearCartItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +311,9 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
|||||||
*/
|
*/
|
||||||
public function findCartItem(CartEvent $event)
|
public function findCartItem(CartEvent $event)
|
||||||
{
|
{
|
||||||
if (null !== $foundItem = CartItemQuery::create()
|
// Do not try to find a cartItem if one exists in the event, as previous event handlers
|
||||||
|
// mays have put it in th event.
|
||||||
|
if (null === $event->getCartItem() && null !== $foundItem = CartItemQuery::create()
|
||||||
->filterByCartId($event->getCart()->getId())
|
->filterByCartId($event->getCart()->getId())
|
||||||
->filterByProductId($event->getProduct())
|
->filterByProductId($event->getProduct())
|
||||||
->filterByProductSaleElementsId($event->getProductSaleElementsId())
|
->filterByProductSaleElementsId($event->getProductSaleElementsId())
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Thelia\Action;
|
|||||||
use Propel\Runtime\Propel;
|
use Propel\Runtime\Propel;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||||
use Thelia\Core\Event\UpdateSeoEvent;
|
use Thelia\Core\Event\UpdateSeoEvent;
|
||||||
use Thelia\Model\CategoryDocumentQuery;
|
use Thelia\Model\CategoryDocumentQuery;
|
||||||
@@ -29,6 +30,7 @@ use Thelia\Core\Event\UpdatePositionEvent;
|
|||||||
use Thelia\Core\Event\Category\CategoryToggleVisibilityEvent;
|
use Thelia\Core\Event\Category\CategoryToggleVisibilityEvent;
|
||||||
use Thelia\Core\Event\Category\CategoryAddContentEvent;
|
use Thelia\Core\Event\Category\CategoryAddContentEvent;
|
||||||
use Thelia\Core\Event\Category\CategoryDeleteContentEvent;
|
use Thelia\Core\Event\Category\CategoryDeleteContentEvent;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
use Thelia\Model\CategoryAssociatedContent;
|
use Thelia\Model\CategoryAssociatedContent;
|
||||||
use Thelia\Model\CategoryAssociatedContentQuery;
|
use Thelia\Model\CategoryAssociatedContentQuery;
|
||||||
use Thelia\Model\Map\CategoryTableMap;
|
use Thelia\Model\Map\CategoryTableMap;
|
||||||
@@ -212,6 +214,36 @@ class Category extends BaseAction implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if is a category view and if category_id is visible
|
||||||
|
*
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function viewCheck(ViewCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if ($event->getView() == 'category') {
|
||||||
|
$category = CategoryQuery::create()
|
||||||
|
->filterById($event->getViewId())
|
||||||
|
->filterByVisible(1)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
if ($category == 0) {
|
||||||
|
$dispatcher->dispatch(TheliaEvents::VIEW_CATEGORY_ID_NOT_VISIBLE, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public function viewcategoryIdNotVisible(ViewCheckEvent $event)
|
||||||
|
{
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@@ -229,6 +261,8 @@ class Category extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::CATEGORY_ADD_CONTENT => array("addContent", 128),
|
TheliaEvents::CATEGORY_ADD_CONTENT => array("addContent", 128),
|
||||||
TheliaEvents::CATEGORY_REMOVE_CONTENT => array("removeContent", 128),
|
TheliaEvents::CATEGORY_REMOVE_CONTENT => array("removeContent", 128),
|
||||||
|
|
||||||
|
TheliaEvents::VIEW_CHECK => array('viewCheck', 128),
|
||||||
|
TheliaEvents::VIEW_CATEGORY_ID_NOT_VISIBLE => array('viewcategoryIdNotVisible', 128),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use Propel\Runtime\Exception\PropelException;
|
|||||||
use Propel\Runtime\Propel;
|
use Propel\Runtime\Propel;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Thelia\Core\Event\Content\ContentAddFolderEvent;
|
use Thelia\Core\Event\Content\ContentAddFolderEvent;
|
||||||
use Thelia\Core\Event\Content\ContentCreateEvent;
|
use Thelia\Core\Event\Content\ContentCreateEvent;
|
||||||
use Thelia\Core\Event\Content\ContentDeleteEvent;
|
use Thelia\Core\Event\Content\ContentDeleteEvent;
|
||||||
@@ -26,6 +27,7 @@ use Thelia\Core\Event\File\FileDeleteEvent;
|
|||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
use Thelia\Core\Event\UpdatePositionEvent;
|
use Thelia\Core\Event\UpdatePositionEvent;
|
||||||
use Thelia\Core\Event\UpdateSeoEvent;
|
use Thelia\Core\Event\UpdateSeoEvent;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
use Thelia\Model\ContentDocumentQuery;
|
use Thelia\Model\ContentDocumentQuery;
|
||||||
use Thelia\Model\ContentFolder;
|
use Thelia\Model\ContentFolder;
|
||||||
use Thelia\Model\ContentFolderQuery;
|
use Thelia\Model\ContentFolderQuery;
|
||||||
@@ -207,13 +209,43 @@ class Content extends BaseAction implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if is a content view and if content_id is visible
|
||||||
|
*
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function viewCheck(ViewCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if ($event->getView() == 'content') {
|
||||||
|
$content = ContentQuery::create()
|
||||||
|
->filterById($event->getViewId())
|
||||||
|
->filterByVisible(1)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
if ($content == 0) {
|
||||||
|
$dispatcher->dispatch(TheliaEvents::VIEW_CONTENT_ID_NOT_VISIBLE, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public function viewContentIdNotVisible(ViewCheckEvent $event)
|
||||||
|
{
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public static function getSubscribedEvents()
|
public static function getSubscribedEvents()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
TheliaEvents::CONTENT_CREATE => array('create', 128),
|
TheliaEvents::CONTENT_CREATE => array('create', 128),
|
||||||
TheliaEvents::CONTENT_UPDATE => array('update', 128),
|
TheliaEvents::CONTENT_UPDATE => array('update', 128),
|
||||||
TheliaEvents::CONTENT_DELETE => array('delete', 128),
|
TheliaEvents::CONTENT_DELETE => array('delete', 128),
|
||||||
TheliaEvents::CONTENT_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
TheliaEvents::CONTENT_TOGGLE_VISIBILITY => array('toggleVisibility', 128),
|
||||||
@@ -223,6 +255,9 @@ class Content extends BaseAction implements EventSubscriberInterface
|
|||||||
|
|
||||||
TheliaEvents::CONTENT_ADD_FOLDER => array('addFolder', 128),
|
TheliaEvents::CONTENT_ADD_FOLDER => array('addFolder', 128),
|
||||||
TheliaEvents::CONTENT_REMOVE_FOLDER => array('removeFolder', 128),
|
TheliaEvents::CONTENT_REMOVE_FOLDER => array('removeFolder', 128),
|
||||||
|
|
||||||
|
TheliaEvents::VIEW_CHECK => array('viewCheck', 128),
|
||||||
|
TheliaEvents::VIEW_CONTENT_ID_NOT_VISIBLE => array('viewContentIdNotVisible', 128),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ use Thelia\Model\Map\OrderCouponTableMap;
|
|||||||
use Thelia\Model\OrderCoupon;
|
use Thelia\Model\OrderCoupon;
|
||||||
use Thelia\Model\OrderCouponCountry;
|
use Thelia\Model\OrderCouponCountry;
|
||||||
use Thelia\Model\OrderCouponModule;
|
use Thelia\Model\OrderCouponModule;
|
||||||
|
use Thelia\Model\OrderCouponQuery;
|
||||||
|
use Thelia\Model\OrderStatusQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process Coupon Events
|
* Process Coupon Events
|
||||||
@@ -322,7 +324,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
|||||||
$orderCoupon->setOrder($event->getOrder())
|
$orderCoupon->setOrder($event->getOrder())
|
||||||
->setCode($couponModel->getCode())
|
->setCode($couponModel->getCode())
|
||||||
->setType($couponModel->getType())
|
->setType($couponModel->getType())
|
||||||
->setAmount($couponModel->getAmount())
|
->setAmount($couponCode->exec())
|
||||||
|
|
||||||
->setTitle($couponModel->getTitle())
|
->setTitle($couponModel->getTitle())
|
||||||
->setShortDescription($couponModel->getShortDescription())
|
->setShortDescription($couponModel->getShortDescription())
|
||||||
@@ -378,6 +380,58 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
|||||||
$dispatcher->dispatch(TheliaEvents::COUPON_CLEAR_ALL);
|
$dispatcher->dispatch(TheliaEvents::COUPON_CLEAR_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels order coupons usage when order is canceled or refunded,
|
||||||
|
* or use canceled coupons again if the order is no longer canceled or refunded
|
||||||
|
*
|
||||||
|
* @param OrderEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
* @throws \Exception
|
||||||
|
* @throws \Propel\Runtime\Exception\PropelException
|
||||||
|
*/
|
||||||
|
public function orderStatusChange(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
// The order has been canceled or refunded ?
|
||||||
|
if ($event->getOrder()->isCancelled() || $event->getOrder()->isRefunded()) {
|
||||||
|
// Cancel usage of all coupons for this order
|
||||||
|
$usedCoupons = OrderCouponQuery::create()
|
||||||
|
->filterByUsageCanceled(false)
|
||||||
|
->findByOrderId($event->getOrder()->getId());
|
||||||
|
|
||||||
|
$customerId = $event->getOrder()->getCustomerId();
|
||||||
|
|
||||||
|
/** @var OrderCoupon $usedCoupon */
|
||||||
|
foreach ($usedCoupons as $usedCoupon) {
|
||||||
|
if (null !== $couponModel = CouponQuery::create()->findOneByCode($usedCoupon->getCode())) {
|
||||||
|
// If the coupon still exists, restore one usage to the usage count.
|
||||||
|
$this->couponManager->incrementQuantity($couponModel, $customerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark coupon usage as canceled in the OrderCoupon table
|
||||||
|
$usedCoupon->setUsageCanceled(true)->save();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Mark canceled coupons for this order as used again
|
||||||
|
$usedCoupons = OrderCouponQuery::create()
|
||||||
|
->filterByUsageCanceled(true)
|
||||||
|
->findByOrderId($event->getOrder()->getId());
|
||||||
|
|
||||||
|
$customerId = $event->getOrder()->getCustomerId();
|
||||||
|
|
||||||
|
/** @var OrderCoupon $usedCoupon */
|
||||||
|
foreach ($usedCoupons as $usedCoupon) {
|
||||||
|
if (null !== $couponModel = CouponQuery::create()->findOneByCode($usedCoupon->getCode())) {
|
||||||
|
// If the coupon still exists, mark the coupon as used
|
||||||
|
$this->couponManager->decrementQuantity($couponModel, $customerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The coupon is no longer canceled
|
||||||
|
$usedCoupon->setUsageCanceled(false)->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@@ -392,9 +446,11 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128),
|
TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128),
|
||||||
TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132),
|
TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132),
|
||||||
TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128),
|
TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128),
|
||||||
|
TheliaEvents::ORDER_UPDATE_STATUS => array("orderStatusChange", 10),
|
||||||
TheliaEvents::CART_ADDITEM => array("updateOrderDiscount", 10),
|
TheliaEvents::CART_ADDITEM => array("updateOrderDiscount", 10),
|
||||||
TheliaEvents::CART_UPDATEITEM => array("updateOrderDiscount", 10),
|
TheliaEvents::CART_UPDATEITEM => array("updateOrderDiscount", 10),
|
||||||
TheliaEvents::CART_DELETEITEM => array("updateOrderDiscount", 10),
|
TheliaEvents::CART_DELETEITEM => array("updateOrderDiscount", 10),
|
||||||
|
TheliaEvents::CUSTOMER_LOGIN => array("updateOrderDiscount", 10)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use Thelia\Core\Security\SecurityContext;
|
|||||||
use Thelia\Core\Translation\Translator;
|
use Thelia\Core\Translation\Translator;
|
||||||
use Thelia\Exception\CustomerException;
|
use Thelia\Exception\CustomerException;
|
||||||
use Thelia\Mailer\MailerFactory;
|
use Thelia\Mailer\MailerFactory;
|
||||||
|
use Thelia\Model\ConfigQuery;
|
||||||
use Thelia\Model\Customer as CustomerModel;
|
use Thelia\Model\Customer as CustomerModel;
|
||||||
use Thelia\Model\CustomerQuery;
|
use Thelia\Model\CustomerQuery;
|
||||||
use Thelia\Tools\Password;
|
use Thelia\Tools\Password;
|
||||||
@@ -59,7 +60,29 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
|||||||
$this->createOrUpdateCustomer($customer, $event, $dispatcher);
|
$this->createOrUpdateCustomer($customer, $event, $dispatcher);
|
||||||
|
|
||||||
if ($event->getNotifyCustomerOfAccountCreation()) {
|
if ($event->getNotifyCustomerOfAccountCreation()) {
|
||||||
$this->mailer->sendEmailToCustomer('customer_account_created', $customer, [ 'password' => $plainPassword ]);
|
$this->mailer->sendEmailToCustomer(
|
||||||
|
'customer_account_created',
|
||||||
|
$customer,
|
||||||
|
[ 'password' => $plainPassword ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dispatcher->dispatch(
|
||||||
|
TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL,
|
||||||
|
new CustomerEvent($customer)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function customerConfirmationEmail(CustomerEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
$customer = $event->getCustomer();
|
||||||
|
|
||||||
|
if (ConfigQuery::isCustomerEmailConfirmationEnable() && $customer->getConfirmationToken() !== null && $customer !== null) {
|
||||||
|
$this->mailer->sendEmailToCustomer(
|
||||||
|
'customer_confirmation',
|
||||||
|
$customer,
|
||||||
|
['customer_id' => $customer->getId()]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +232,8 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::CUSTOMER_LOGOUT => array('logout', 128),
|
TheliaEvents::CUSTOMER_LOGOUT => array('logout', 128),
|
||||||
TheliaEvents::CUSTOMER_LOGIN => array('login', 128),
|
TheliaEvents::CUSTOMER_LOGIN => array('login', 128),
|
||||||
TheliaEvents::CUSTOMER_DELETEACCOUNT => array('delete', 128),
|
TheliaEvents::CUSTOMER_DELETEACCOUNT => array('delete', 128),
|
||||||
TheliaEvents::LOST_PASSWORD => array('lostPassword', 128)
|
TheliaEvents::LOST_PASSWORD => array('lostPassword', 128),
|
||||||
|
TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL => array('customerConfirmationEmail', 128)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Thelia\Action;
|
|||||||
use Propel\Runtime\Propel;
|
use Propel\Runtime\Propel;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||||
use Thelia\Core\Event\Folder\FolderCreateEvent;
|
use Thelia\Core\Event\Folder\FolderCreateEvent;
|
||||||
use Thelia\Core\Event\Folder\FolderDeleteEvent;
|
use Thelia\Core\Event\Folder\FolderDeleteEvent;
|
||||||
@@ -23,6 +24,7 @@ use Thelia\Core\Event\Folder\FolderUpdateEvent;
|
|||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
use Thelia\Core\Event\UpdatePositionEvent;
|
use Thelia\Core\Event\UpdatePositionEvent;
|
||||||
use Thelia\Core\Event\UpdateSeoEvent;
|
use Thelia\Core\Event\UpdateSeoEvent;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
use Thelia\Model\FolderDocumentQuery;
|
use Thelia\Model\FolderDocumentQuery;
|
||||||
use Thelia\Model\FolderImageQuery;
|
use Thelia\Model\FolderImageQuery;
|
||||||
use Thelia\Model\FolderQuery;
|
use Thelia\Model\FolderQuery;
|
||||||
@@ -155,6 +157,36 @@ class Folder extends BaseAction implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if is a folder view and if folder_id is visible
|
||||||
|
*
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function viewCheck(ViewCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if ($event->getView() == 'folder') {
|
||||||
|
$folder = FolderQuery::create()
|
||||||
|
->filterById($event->getViewId())
|
||||||
|
->filterByVisible(1)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
if ($folder == 0) {
|
||||||
|
$dispatcher->dispatch(TheliaEvents::VIEW_FOLDER_ID_NOT_VISIBLE, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public function viewFolderIdNotVisible(ViewCheckEvent $event)
|
||||||
|
{
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@@ -167,7 +199,10 @@ class Folder extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::FOLDER_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
TheliaEvents::FOLDER_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
|
||||||
|
|
||||||
TheliaEvents::FOLDER_UPDATE_POSITION => array("updatePosition", 128),
|
TheliaEvents::FOLDER_UPDATE_POSITION => array("updatePosition", 128),
|
||||||
TheliaEvents::FOLDER_UPDATE_SEO => array('updateSeo', 128)
|
TheliaEvents::FOLDER_UPDATE_SEO => array('updateSeo', 128),
|
||||||
|
|
||||||
|
TheliaEvents::VIEW_CHECK => array('viewCheck', 128),
|
||||||
|
TheliaEvents::VIEW_FOLDER_ID_NOT_VISIBLE => array('viewFolderIdNotVisible', 128),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,11 +301,18 @@ class Image extends BaseCachedFile implements EventSubscriberInterface
|
|||||||
$delta_x = $delta_y = $border_width = $border_height = 0;
|
$delta_x = $delta_y = $border_width = $border_height = 0;
|
||||||
|
|
||||||
if ($width_diff > 1 && $height_diff > 1) {
|
if ($width_diff > 1 && $height_diff > 1) {
|
||||||
$resize_width = $width_orig;
|
// Set the default final size. If zoom is allowed, we will get the required
|
||||||
$resize_height = $height_orig;
|
// image dimension. Otherwise, the final image may be smaller than required.
|
||||||
|
if ($allow_zoom) {
|
||||||
|
$resize_width = $dest_width;
|
||||||
|
$resize_height = $dest_height;
|
||||||
|
} else {
|
||||||
|
$resize_width = $width_orig;
|
||||||
|
$resize_height = $height_orig;
|
||||||
|
}
|
||||||
|
|
||||||
// When cropping, be sure to always generate an image which is
|
// When cropping, be sure to always generate an image which is
|
||||||
// no smaller than the required size, zooming it if required.
|
// not smaller than the required size, zooming it if required.
|
||||||
if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
|
||||||
if ($allow_zoom) {
|
if ($allow_zoom) {
|
||||||
if ($width_diff > $height_diff) {
|
if ($width_diff > $height_diff) {
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ class Module extends BaseAction implements EventSubscriberInterface
|
|||||||
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) {
|
||||||
try {
|
try {
|
||||||
if ($module->getActivate() == BaseModule::IS_ACTIVATED) {
|
if ($module->getActivate() == BaseModule::IS_ACTIVATED) {
|
||||||
|
if ($module->getMandatory() == BaseModule::IS_MANDATORY && $event->getAssumeDeactivate() === false) {
|
||||||
|
throw new \Exception(
|
||||||
|
Translator::getInstance()->trans('Can\'t deactivate a secure module')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ($event->isRecursive()) {
|
if ($event->isRecursive()) {
|
||||||
$this->recursiveDeactivation($event, $eventName, $dispatcher);
|
$this->recursiveDeactivation($event, $eventName, $dispatcher);
|
||||||
}
|
}
|
||||||
@@ -233,6 +239,11 @@ class Module extends BaseAction implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ($module->getMandatory() == BaseModule::IS_MANDATORY && $event->getAssumeDelete() === false) {
|
||||||
|
throw new \Exception(
|
||||||
|
Translator::getInstance()->trans('Can\'t remove a core module')
|
||||||
|
);
|
||||||
|
}
|
||||||
// First, try to create an instance
|
// First, try to create an instance
|
||||||
$instance = $module->createInstance();
|
$instance = $module->createInstance();
|
||||||
|
|
||||||
|
|||||||
@@ -642,6 +642,19 @@ class Order extends BaseAction implements EventSubscriberInterface
|
|||||||
$event->setOrder($order);
|
$event->setOrder($order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param OrderEvent $event
|
||||||
|
*/
|
||||||
|
public function updateTransactionRef(OrderEvent $event)
|
||||||
|
{
|
||||||
|
$order = $event->getOrder();
|
||||||
|
|
||||||
|
$order->setTransactionRef($event->getTransactionRef());
|
||||||
|
$order->save();
|
||||||
|
|
||||||
|
$event->setOrder($order);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OrderAddressEvent $event
|
* @param OrderAddressEvent $event
|
||||||
*/
|
*/
|
||||||
@@ -710,6 +723,7 @@ class Order extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL => array("sendNotificationEmail", 128),
|
TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL => array("sendNotificationEmail", 128),
|
||||||
TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128),
|
TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128),
|
||||||
TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128),
|
TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128),
|
||||||
|
TheliaEvents::ORDER_UPDATE_TRANSACTION_REF => array("updateTransactionRef", 128),
|
||||||
TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128),
|
TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128),
|
||||||
TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128),
|
TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,17 +14,53 @@ namespace Thelia\Action;
|
|||||||
|
|
||||||
use Propel\Runtime\ActiveQuery\Criteria;
|
use Propel\Runtime\ActiveQuery\Criteria;
|
||||||
use Propel\Runtime\Exception\PropelException;
|
use Propel\Runtime\Exception\PropelException;
|
||||||
|
use Propel\Runtime\Propel;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
|
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
|
||||||
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
|
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
|
||||||
|
use Thelia\Core\Event\FeatureProduct\FeatureProductDeleteEvent;
|
||||||
|
use Thelia\Core\Event\FeatureProduct\FeatureProductUpdateEvent;
|
||||||
use Thelia\Core\Event\File\FileDeleteEvent;
|
use Thelia\Core\Event\File\FileDeleteEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductAddAccessoryEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductAddCategoryEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductAddContentEvent;
|
||||||
use Thelia\Core\Event\Product\ProductCloneEvent;
|
use Thelia\Core\Event\Product\ProductCloneEvent;
|
||||||
use Thelia\Model\AttributeCombinationQuery;
|
use Thelia\Core\Event\Product\ProductCreateEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductDeleteCategoryEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductDeleteContentEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductDeleteEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductSetTemplateEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductToggleVisibilityEvent;
|
||||||
|
use Thelia\Core\Event\Product\ProductUpdateEvent;
|
||||||
|
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementDeleteEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
||||||
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
|
use Thelia\Core\Event\UpdatePositionEvent;
|
||||||
|
use Thelia\Core\Event\UpdateSeoEvent;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
|
use Thelia\Model\Accessory;
|
||||||
|
use Thelia\Model\AccessoryQuery;
|
||||||
|
use Thelia\Model\AttributeTemplateQuery;
|
||||||
|
use Thelia\Model\Currency as CurrencyModel;
|
||||||
use Thelia\Model\FeatureAvI18n;
|
use Thelia\Model\FeatureAvI18n;
|
||||||
use Thelia\Model\FeatureAvI18nQuery;
|
use Thelia\Model\FeatureAvI18nQuery;
|
||||||
use Thelia\Model\FeatureAvQuery;
|
use Thelia\Model\FeatureAvQuery;
|
||||||
|
use Thelia\Model\FeatureProduct;
|
||||||
|
use Thelia\Model\FeatureProductQuery;
|
||||||
|
use Thelia\Model\FeatureTemplateQuery;
|
||||||
|
use Thelia\Model\Map\AttributeTemplateTableMap;
|
||||||
|
use Thelia\Model\Map\FeatureTemplateTableMap;
|
||||||
|
use Thelia\Model\Map\ProductSaleElementsTableMap;
|
||||||
use Thelia\Model\Map\ProductTableMap;
|
use Thelia\Model\Map\ProductTableMap;
|
||||||
|
use Thelia\Model\Product as ProductModel;
|
||||||
|
use Thelia\Model\ProductAssociatedContent;
|
||||||
|
use Thelia\Model\ProductAssociatedContentQuery;
|
||||||
|
use Thelia\Model\ProductCategory;
|
||||||
|
use Thelia\Model\ProductCategoryQuery;
|
||||||
use Thelia\Model\ProductDocument;
|
use Thelia\Model\ProductDocument;
|
||||||
use Thelia\Model\ProductDocumentQuery;
|
use Thelia\Model\ProductDocumentQuery;
|
||||||
use Thelia\Model\ProductI18n;
|
use Thelia\Model\ProductI18n;
|
||||||
@@ -34,34 +70,8 @@ use Thelia\Model\ProductImageQuery;
|
|||||||
use Thelia\Model\ProductPrice;
|
use Thelia\Model\ProductPrice;
|
||||||
use Thelia\Model\ProductPriceQuery;
|
use Thelia\Model\ProductPriceQuery;
|
||||||
use Thelia\Model\ProductQuery;
|
use Thelia\Model\ProductQuery;
|
||||||
use Thelia\Model\Product as ProductModel;
|
|
||||||
use Thelia\Model\ProductAssociatedContent;
|
|
||||||
use Thelia\Model\ProductAssociatedContentQuery;
|
|
||||||
use Thelia\Model\ProductCategory;
|
|
||||||
use Thelia\Model\TaxRuleQuery;
|
|
||||||
use Thelia\Model\AccessoryQuery;
|
|
||||||
use Thelia\Model\Accessory;
|
|
||||||
use Thelia\Model\FeatureProduct;
|
|
||||||
use Thelia\Model\FeatureProductQuery;
|
|
||||||
use Thelia\Model\ProductCategoryQuery;
|
|
||||||
use Thelia\Model\ProductSaleElementsQuery;
|
use Thelia\Model\ProductSaleElementsQuery;
|
||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Model\TaxRuleQuery;
|
||||||
use Thelia\Core\Event\Product\ProductUpdateEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductCreateEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductDeleteEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductToggleVisibilityEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductAddContentEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductDeleteContentEvent;
|
|
||||||
use Thelia\Core\Event\UpdatePositionEvent;
|
|
||||||
use Thelia\Core\Event\UpdateSeoEvent;
|
|
||||||
use Thelia\Core\Event\FeatureProduct\FeatureProductUpdateEvent;
|
|
||||||
use Thelia\Core\Event\FeatureProduct\FeatureProductDeleteEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductSetTemplateEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductDeleteCategoryEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductAddCategoryEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductAddAccessoryEvent;
|
|
||||||
use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent;
|
|
||||||
use Propel\Runtime\Propel;
|
|
||||||
|
|
||||||
class Product extends BaseAction implements EventSubscriberInterface
|
class Product extends BaseAction implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
@@ -80,6 +90,11 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
*/
|
*/
|
||||||
public function create(ProductCreateEvent $event)
|
public function create(ProductCreateEvent $event)
|
||||||
{
|
{
|
||||||
|
$defaultTaxRuleId = null;
|
||||||
|
if (null !== $defaultTaxRule = TaxRuleQuery::create()->findOneByIsDefault(true)) {
|
||||||
|
$defaultTaxRuleId = $defaultTaxRule->getId();
|
||||||
|
}
|
||||||
|
|
||||||
$product = new ProductModel();
|
$product = new ProductModel();
|
||||||
|
|
||||||
$product
|
$product
|
||||||
@@ -90,17 +105,14 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
->setTitle($event->getTitle())
|
->setTitle($event->getTitle())
|
||||||
->setVisible($event->getVisible() ? 1 : 0)
|
->setVisible($event->getVisible() ? 1 : 0)
|
||||||
->setVirtual($event->getVirtual() ? 1 : 0)
|
->setVirtual($event->getVirtual() ? 1 : 0)
|
||||||
|
|
||||||
// Set the default tax rule to this product
|
|
||||||
->setTaxRule(TaxRuleQuery::create()->findOneByIsDefault(true))
|
|
||||||
|
|
||||||
->setTemplateId($event->getTemplateId())
|
->setTemplateId($event->getTemplateId())
|
||||||
|
|
||||||
->create(
|
->create(
|
||||||
$event->getDefaultCategory(),
|
$event->getDefaultCategory(),
|
||||||
$event->getBasePrice(),
|
$event->getBasePrice(),
|
||||||
$event->getCurrencyId(),
|
$event->getCurrencyId(),
|
||||||
$event->getTaxRuleId(),
|
// Set the default tax rule if not defined
|
||||||
|
$event->getTaxRuleId() ?: $defaultTaxRuleId,
|
||||||
$event->getBaseWeight(),
|
$event->getBaseWeight(),
|
||||||
$event->getBaseQuantity()
|
$event->getBaseQuantity()
|
||||||
)
|
)
|
||||||
@@ -278,6 +290,7 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
->findByProductId($event->getOriginalProduct()->getId());
|
->findByProductId($event->getOriginalProduct()->getId());
|
||||||
|
|
||||||
// Set clone product associated contents
|
// Set clone product associated contents
|
||||||
|
/** @var ProductAssociatedContent $originalProductAssocCont */
|
||||||
foreach ($originalProductAssocConts as $originalProductAssocCont) {
|
foreach ($originalProductAssocConts as $originalProductAssocCont) {
|
||||||
$clonedProductCreatePAC = new ProductAddContentEvent($event->getClonedProduct(), $originalProductAssocCont->getContentId());
|
$clonedProductCreatePAC = new ProductAddContentEvent($event->getClonedProduct(), $originalProductAssocCont->getContentId());
|
||||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $clonedProductCreatePAC);
|
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $clonedProductCreatePAC);
|
||||||
@@ -291,6 +304,7 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
->findByProductId($event->getOriginalProduct()->getId());
|
->findByProductId($event->getOriginalProduct()->getId());
|
||||||
|
|
||||||
// Set clone product accessories
|
// Set clone product accessories
|
||||||
|
/** @var Accessory $originalProductAccessory */
|
||||||
foreach ($originalProductAccessoryList as $originalProductAccessory) {
|
foreach ($originalProductAccessoryList as $originalProductAccessory) {
|
||||||
$clonedProductAddAccessoryEvent = new ProductAddAccessoryEvent($event->getClonedProduct(), $originalProductAccessory->getAccessory());
|
$clonedProductAddAccessoryEvent = new ProductAddAccessoryEvent($event->getClonedProduct(), $originalProductAccessory->getAccessory());
|
||||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_ACCESSORY, $clonedProductAddAccessoryEvent);
|
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_ACCESSORY, $clonedProductAddAccessoryEvent);
|
||||||
@@ -387,22 +401,6 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
->findByProductId($event->getProductId());
|
->findByProductId($event->getProductId());
|
||||||
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
$fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE;
|
||||||
|
|
||||||
// Delete free_text_feature AV (see issue #2061)
|
|
||||||
$featureAvs = FeatureAvQuery::create()
|
|
||||||
->useFeatureProductQuery()
|
|
||||||
->filterByFreeTextValue(true)
|
|
||||||
->filterByProductId($event->getProductId())
|
|
||||||
->endUse()
|
|
||||||
->find($con)
|
|
||||||
;
|
|
||||||
|
|
||||||
foreach ($featureAvs as $featureAv) {
|
|
||||||
$featureAv
|
|
||||||
->setDispatcher($this->eventDispatcher)
|
|
||||||
->delete($con)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete product
|
// Delete product
|
||||||
$product
|
$product
|
||||||
->setDispatcher($this->eventDispatcher)
|
->setDispatcher($this->eventDispatcher)
|
||||||
@@ -563,28 +561,69 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
try {
|
try {
|
||||||
$product = $event->getProduct();
|
$product = $event->getProduct();
|
||||||
|
|
||||||
// Delete all product feature relations
|
// Check differences between current coobination and the next one, and clear obsoletes values.
|
||||||
if (null !== $featureProducts = FeatureProductQuery::create()->findByProductId($product->getId())) {
|
$nextTemplateId = $event->getTemplateId();
|
||||||
/** @var \Thelia\Model\FeatureProduct $featureProduct */
|
$currentTemplateId = $product->getTemplateId();
|
||||||
foreach ($featureProducts as $featureProduct) {
|
|
||||||
$eventDelete = new FeatureProductDeleteEvent($product->getId(), $featureProduct->getFeatureId());
|
// 1. Process product features.
|
||||||
|
|
||||||
$this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $eventDelete);
|
$currentFeatures = FeatureTemplateQuery::create()
|
||||||
}
|
->filterByTemplateId($currentTemplateId)
|
||||||
|
->select([ FeatureTemplateTableMap::FEATURE_ID ])
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
$nextFeatures = FeatureTemplateQuery::create()
|
||||||
|
->filterByTemplateId($nextTemplateId)
|
||||||
|
->select([ FeatureTemplateTableMap::FEATURE_ID ])
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
// Find features values we shoud delete. To do this, we have to
|
||||||
|
// find all features in $currentFeatures that are not present in $nextFeatures
|
||||||
|
$featuresToDelete = array_diff($currentFeatures->getData(), $nextFeatures->getData());
|
||||||
|
|
||||||
|
// Delete obsolete features values
|
||||||
|
foreach ($featuresToDelete as $featureId) {
|
||||||
|
$this->eventDispatcher->dispatch(
|
||||||
|
TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE,
|
||||||
|
new FeatureProductDeleteEvent($product->getId(), $featureId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Process product Attributes
|
||||||
|
|
||||||
|
$currentAttributes = AttributeTemplateQuery::create()
|
||||||
|
->filterByTemplateId($currentTemplateId)
|
||||||
|
->select([ AttributeTemplateTableMap::ATTRIBUTE_ID ])
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
$nextAttributes = AttributeTemplateQuery::create()
|
||||||
|
->filterByTemplateId($nextTemplateId)
|
||||||
|
->select([ AttributeTemplateTableMap::ATTRIBUTE_ID ])
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
// Find attributes values we shoud delete. To do this, we have to
|
||||||
|
// find all attributes in $currentAttributes that are not present in $nextAttributes
|
||||||
|
$attributesToDelete = array_diff($currentAttributes->getData(), $nextAttributes->getData());
|
||||||
|
|
||||||
// Delete all product attributes sale elements
|
// Find PSE which includes $attributesToDelete for the current product/
|
||||||
AttributeCombinationQuery::create()
|
$pseToDelete = ProductSaleElementsQuery::create()
|
||||||
->filterByProductSaleElements($product->getProductSaleElementss())
|
->filterByProductId($product->getId())
|
||||||
->delete($con)
|
->useAttributeCombinationQuery()
|
||||||
;
|
->filterByAttributeId($attributesToDelete, Criteria::IN)
|
||||||
|
->endUse()
|
||||||
//Delete all productSaleElements except the default one (to keep price, weight, ean, etc...)
|
->select([ ProductSaleElementsTableMap::ID ])
|
||||||
ProductSaleElementsQuery::create()
|
->find();
|
||||||
->filterByProduct($product)
|
|
||||||
->filterByIsDefault(1, Criteria::NOT_EQUAL)
|
// Delete obsolete PSEs
|
||||||
->delete($con)
|
foreach ($pseToDelete->getData() as $pseId) {
|
||||||
;
|
$this->eventDispatcher->dispatch(
|
||||||
|
TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT,
|
||||||
|
new ProductSaleElementDeleteEvent(
|
||||||
|
$pseId,
|
||||||
|
CurrencyModel::getDefaultCurrency()->getId()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Update the product template
|
// Update the product template
|
||||||
$template_id = $event->getTemplateId();
|
$template_id = $event->getTemplateId();
|
||||||
@@ -596,16 +635,6 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
|
|
||||||
$product->setTemplateId($template_id)->save($con);
|
$product->setTemplateId($template_id)->save($con);
|
||||||
|
|
||||||
//Be sure that the product has a default productSaleElements
|
|
||||||
/** @var \Thelia\Model\ProductSaleElements $defaultPse */
|
|
||||||
if (null == $defaultPse = ProductSaleElementsQuery::create()
|
|
||||||
->filterByProduct($product)
|
|
||||||
->filterByIsDefault(1)
|
|
||||||
->findOne()) {
|
|
||||||
// Create a new default product sale element
|
|
||||||
$product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$product->clearProductSaleElementss();
|
$product->clearProductSaleElementss();
|
||||||
|
|
||||||
$event->setProduct($product);
|
$event->setProduct($product);
|
||||||
@@ -618,7 +647,7 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes accessry position, selecting absolute ou relative change.
|
* Changes accessry position, selecting absolute ou relative change.
|
||||||
*
|
*
|
||||||
@@ -781,6 +810,93 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
$model->getProductSaleElementsProductDocuments()->delete();
|
$model->getProductSaleElementsProductDocuments()->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a feature is removed from a template, the products which are using this feature should be updated.
|
||||||
|
*
|
||||||
|
* @param TemplateDeleteFeatureEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function deleteTemplateFeature(TemplateDeleteFeatureEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
// Detete the removed feature in all products which are using this template
|
||||||
|
$products = ProductQuery::create()
|
||||||
|
->filterByTemplateId($event->getTemplate()->getId())
|
||||||
|
->find()
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach ($products as $product) {
|
||||||
|
$dispatcher->dispatch(
|
||||||
|
TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE,
|
||||||
|
new FeatureProductDeleteEvent($product->getId(), $event->getFeatureId())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an attribute is removed from a template, the conbinations and PSE of products which are using this template
|
||||||
|
* should be updated.
|
||||||
|
*
|
||||||
|
* @param TemplateDeleteAttributeEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function deleteTemplateAttribute(TemplateDeleteAttributeEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
// Detete the removed attribute in all products which are using this template
|
||||||
|
$pseToDelete = ProductSaleElementsQuery::create()
|
||||||
|
->useProductQuery()
|
||||||
|
->filterByTemplateId($event->getTemplate()->getId())
|
||||||
|
->endUse()
|
||||||
|
->useAttributeCombinationQuery()
|
||||||
|
->filterByAttributeId($event->getAttributeId())
|
||||||
|
->endUse()
|
||||||
|
->select([ ProductSaleElementsTableMap::ID ])
|
||||||
|
->find();
|
||||||
|
|
||||||
|
$currencyId = CurrencyModel::getDefaultCurrency()->getId();
|
||||||
|
|
||||||
|
foreach ($pseToDelete->getData() as $pseId) {
|
||||||
|
$dispatcher->dispatch(
|
||||||
|
TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT,
|
||||||
|
new ProductSaleElementDeleteEvent(
|
||||||
|
$pseId,
|
||||||
|
$currencyId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if is a product view and if product_id is visible
|
||||||
|
*
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @param string $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function viewCheck(ViewCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if ($event->getView() == 'product') {
|
||||||
|
$product = ProductQuery::create()
|
||||||
|
->filterById($event->getViewId())
|
||||||
|
->filterByVisible(1)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
if ($product == 0) {
|
||||||
|
$dispatcher->dispatch(TheliaEvents::VIEW_PRODUCT_ID_NOT_VISIBLE, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ViewCheckEvent $event
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public function viewProductIdNotVisible(ViewCheckEvent $event)
|
||||||
|
{
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -812,10 +928,16 @@ class Product extends BaseAction implements EventSubscriberInterface
|
|||||||
|
|
||||||
TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 128),
|
TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 128),
|
||||||
TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE => array("deleteFeatureProductValue", 128),
|
TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE => array("deleteFeatureProductValue", 128),
|
||||||
|
|
||||||
|
TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE => array("deleteTemplateAttribute", 128),
|
||||||
|
TheliaEvents::TEMPLATE_DELETE_FEATURE => array("deleteTemplateFeature", 128),
|
||||||
|
|
||||||
// Those two have to be executed before
|
// Those two have to be executed before
|
||||||
TheliaEvents::IMAGE_DELETE => array("deleteImagePSEAssociations", 192),
|
TheliaEvents::IMAGE_DELETE => array("deleteImagePSEAssociations", 192),
|
||||||
TheliaEvents::DOCUMENT_DELETE => array("deleteDocumentPSEAssociations", 192),
|
TheliaEvents::DOCUMENT_DELETE => array("deleteDocumentPSEAssociations", 192),
|
||||||
|
|
||||||
|
TheliaEvents::VIEW_CHECK => array('viewCheck', 128),
|
||||||
|
TheliaEvents::VIEW_PRODUCT_ID_NOT_VISIBLE => array('viewProductIdNotVisible', 128),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,24 +15,26 @@ namespace Thelia\Action;
|
|||||||
use Propel\Runtime\Propel;
|
use Propel\Runtime\Propel;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Thelia\Model\CategoryQuery;
|
|
||||||
use Thelia\Model\Map\TemplateTableMap;
|
|
||||||
use Thelia\Model\TemplateQuery;
|
|
||||||
use Thelia\Model\Template as TemplateModel;
|
|
||||||
use Thelia\Core\Event\TheliaEvents;
|
|
||||||
use Thelia\Core\Event\Template\TemplateUpdateEvent;
|
|
||||||
use Thelia\Core\Event\Template\TemplateCreateEvent;
|
|
||||||
use Thelia\Core\Event\Template\TemplateDeleteEvent;
|
|
||||||
use Thelia\Core\Event\UpdatePositionEvent;
|
|
||||||
use Thelia\Model\ProductQuery;
|
|
||||||
use Thelia\Core\Event\Template\TemplateAddAttributeEvent;
|
use Thelia\Core\Event\Template\TemplateAddAttributeEvent;
|
||||||
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
|
||||||
use Thelia\Model\AttributeTemplateQuery;
|
|
||||||
use Thelia\Model\AttributeTemplate;
|
|
||||||
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
|
||||||
use Thelia\Core\Event\Template\TemplateAddFeatureEvent;
|
use Thelia\Core\Event\Template\TemplateAddFeatureEvent;
|
||||||
use Thelia\Model\FeatureTemplateQuery;
|
use Thelia\Core\Event\Template\TemplateCreateEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDeleteEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDuplicateEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateUpdateEvent;
|
||||||
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
|
use Thelia\Core\Event\UpdatePositionEvent;
|
||||||
|
use Thelia\Core\Translation\Translator;
|
||||||
|
use Thelia\Model\AttributeTemplate;
|
||||||
|
use Thelia\Model\AttributeTemplateQuery;
|
||||||
|
use Thelia\Model\CategoryQuery;
|
||||||
use Thelia\Model\FeatureTemplate;
|
use Thelia\Model\FeatureTemplate;
|
||||||
|
use Thelia\Model\FeatureTemplateQuery;
|
||||||
|
use Thelia\Model\Map\TemplateTableMap;
|
||||||
|
use Thelia\Model\ProductQuery;
|
||||||
|
use Thelia\Model\Template as TemplateModel;
|
||||||
|
use Thelia\Model\TemplateQuery;
|
||||||
|
|
||||||
class Template extends BaseAction implements EventSubscriberInterface
|
class Template extends BaseAction implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
@@ -46,19 +48,66 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
public function create(TemplateCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
public function create(TemplateCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
{
|
{
|
||||||
$template = new TemplateModel();
|
$template = new TemplateModel();
|
||||||
|
|
||||||
$template
|
$template
|
||||||
->setDispatcher($dispatcher)
|
->setDispatcher($dispatcher)
|
||||||
|
|
||||||
->setLocale($event->getLocale())
|
->setLocale($event->getLocale())
|
||||||
->setName($event->getTemplateName())
|
->setName($event->getTemplateName())
|
||||||
|
|
||||||
->save()
|
->save()
|
||||||
;
|
;
|
||||||
|
|
||||||
$event->setTemplate($template);
|
$event->setTemplate($template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dupliucate an existing template entry
|
||||||
|
*
|
||||||
|
* @param \Thelia\Core\Event\Template\TemplateCreateEvent $event
|
||||||
|
* @param $eventName
|
||||||
|
* @param EventDispatcherInterface $dispatcher
|
||||||
|
*/
|
||||||
|
public function duplicate(TemplateDuplicateEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
|
{
|
||||||
|
if (null !== $source = TemplateQuery::create()->findPk($event->getSourceTemplateId())) {
|
||||||
|
$source->setLocale($event->getLocale());
|
||||||
|
|
||||||
|
$createEvent = new TemplateCreateEvent();
|
||||||
|
$createEvent
|
||||||
|
->setLocale($event->getLocale())
|
||||||
|
->setTemplateName(
|
||||||
|
Translator::getInstance()->trans("Copy of %tpl", ["%tpl" => $source->getName() ])
|
||||||
|
);
|
||||||
|
|
||||||
|
$dispatcher->dispatch(TheliaEvents::TEMPLATE_CREATE, $createEvent);
|
||||||
|
|
||||||
|
$clone = $createEvent->getTemplate();
|
||||||
|
|
||||||
|
$attrList = AttributeTemplateQuery::create()->findByTemplateId($source->getId());
|
||||||
|
|
||||||
|
/** @var $feat AttributeTemplate */
|
||||||
|
foreach ($attrList as $feat) {
|
||||||
|
$dispatcher->dispatch(
|
||||||
|
TheliaEvents::TEMPLATE_ADD_ATTRIBUTE,
|
||||||
|
new TemplateAddAttributeEvent($clone, $feat->getAttributeId())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$featList = FeatureTemplateQuery::create()->findByTemplateId($source->getId());
|
||||||
|
|
||||||
|
/** @var $feat FeatureTemplate */
|
||||||
|
foreach ($featList as $feat) {
|
||||||
|
$dispatcher->dispatch(
|
||||||
|
TheliaEvents::TEMPLATE_ADD_FEATURE,
|
||||||
|
new TemplateAddFeatureEvent($clone, $feat->getFeatureId())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->setTemplate($clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change a product template
|
* Change a product template
|
||||||
*
|
*
|
||||||
@@ -71,15 +120,15 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
if (null !== $template = TemplateQuery::create()->findPk($event->getTemplateId())) {
|
if (null !== $template = TemplateQuery::create()->findPk($event->getTemplateId())) {
|
||||||
$template
|
$template
|
||||||
->setDispatcher($dispatcher)
|
->setDispatcher($dispatcher)
|
||||||
|
|
||||||
->setLocale($event->getLocale())
|
->setLocale($event->getLocale())
|
||||||
->setName($event->getTemplateName())
|
->setName($event->getTemplateName())
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$event->setTemplate($template);
|
$event->setTemplate($template);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a product template entry
|
* Delete a product template entry
|
||||||
*
|
*
|
||||||
@@ -92,54 +141,54 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
if (null !== ($template = TemplateQuery::create()->findPk($event->getTemplateId()))) {
|
if (null !== ($template = TemplateQuery::create()->findPk($event->getTemplateId()))) {
|
||||||
// Check if template is used by a product
|
// Check if template is used by a product
|
||||||
$product_count = ProductQuery::create()->findByTemplateId($template->getId())->count();
|
$productCount = ProductQuery::create()->findByTemplateId($template->getId())->count();
|
||||||
|
|
||||||
if ($product_count <= 0) {
|
if ($productCount <= 0) {
|
||||||
$con = Propel::getWriteConnection(TemplateTableMap::DATABASE_NAME);
|
$con = Propel::getWriteConnection(TemplateTableMap::DATABASE_NAME);
|
||||||
$con->beginTransaction();
|
$con->beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$template
|
$template
|
||||||
->setDispatcher($dispatcher)
|
->setDispatcher($dispatcher)
|
||||||
->delete($con);
|
->delete($con);
|
||||||
|
|
||||||
// We have to also delete any reference of this template in category tables
|
// We have to also delete any reference of this template in category tables
|
||||||
// We can't use a FK here, as the DefaultTemplateId column may be NULL
|
// We can't use a FK here, as the DefaultTemplateId column may be NULL
|
||||||
// so let's take care of this.
|
// so let's take care of this.
|
||||||
CategoryQuery::create()
|
CategoryQuery::create()
|
||||||
->filterByDefaultTemplateId($event->getTemplateId())
|
->filterByDefaultTemplateId($event->getTemplateId())
|
||||||
->update([ 'DefaultTemplateId' => null], $con);
|
->update([ 'DefaultTemplateId' => null], $con);
|
||||||
|
|
||||||
$con->commit();
|
$con->commit();
|
||||||
} catch (\Exception $ex) {
|
} catch (\Exception $ex) {
|
||||||
$con->rollback();
|
$con->rollback();
|
||||||
|
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$event->setTemplate($template);
|
$event->setTemplate($template);
|
||||||
|
|
||||||
$event->setProductCount($product_count);
|
$event->setProductCount($productCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addAttribute(TemplateAddAttributeEvent $event)
|
public function addAttribute(TemplateAddAttributeEvent $event)
|
||||||
{
|
{
|
||||||
if (null === AttributeTemplateQuery::create()
|
if (null === AttributeTemplateQuery::create()
|
||||||
->filterByAttributeId($event->getAttributeId())
|
->filterByAttributeId($event->getAttributeId())
|
||||||
->filterByTemplate($event->getTemplate())
|
->filterByTemplate($event->getTemplate())
|
||||||
->findOne()) {
|
->findOne()) {
|
||||||
$attribute_template = new AttributeTemplate();
|
$attributeTemplate = new AttributeTemplate();
|
||||||
|
|
||||||
$attribute_template
|
$attributeTemplate
|
||||||
->setAttributeId($event->getAttributeId())
|
->setAttributeId($event->getAttributeId())
|
||||||
->setTemplate($event->getTemplate())
|
->setTemplate($event->getTemplate())
|
||||||
->save()
|
->save()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes position, selecting absolute ou relative change.
|
* Changes position, selecting absolute ou relative change.
|
||||||
*
|
*
|
||||||
@@ -151,7 +200,7 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
$this->genericUpdatePosition(AttributeTemplateQuery::create(), $event, $dispatcher);
|
$this->genericUpdatePosition(AttributeTemplateQuery::create(), $event, $dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes position, selecting absolute ou relative change.
|
* Changes position, selecting absolute ou relative change.
|
||||||
*
|
*
|
||||||
@@ -163,19 +212,24 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
$this->genericUpdatePosition(FeatureTemplateQuery::create(), $event, $dispatcher);
|
$this->genericUpdatePosition(FeatureTemplateQuery::create(), $event, $dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteAttribute(TemplateDeleteAttributeEvent $event)
|
public function deleteAttribute(TemplateDeleteAttributeEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
{
|
{
|
||||||
$attribute_template = AttributeTemplateQuery::create()
|
$attributeTemplate = AttributeTemplateQuery::create()
|
||||||
->filterByAttributeId($event->getAttributeId())
|
->filterByAttributeId($event->getAttributeId())
|
||||||
->filterByTemplate($event->getTemplate())->findOne()
|
->filterByTemplate($event->getTemplate())->findOne()
|
||||||
;
|
;
|
||||||
|
|
||||||
if ($attribute_template !== null) {
|
if ($attributeTemplate !== null) {
|
||||||
$attribute_template->delete();
|
$attributeTemplate
|
||||||
|
->setDispatcher($dispatcher)
|
||||||
|
->delete();
|
||||||
|
} else {
|
||||||
|
// Prevent event propagation
|
||||||
|
$event->stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addFeature(TemplateAddFeatureEvent $event)
|
public function addFeature(TemplateAddFeatureEvent $event)
|
||||||
{
|
{
|
||||||
if (null === FeatureTemplateQuery::create()
|
if (null === FeatureTemplateQuery::create()
|
||||||
@@ -183,28 +237,33 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
->filterByTemplate($event->getTemplate())
|
->filterByTemplate($event->getTemplate())
|
||||||
->findOne()
|
->findOne()
|
||||||
) {
|
) {
|
||||||
$feature_template = new FeatureTemplate();
|
$featureTemplate = new FeatureTemplate();
|
||||||
|
|
||||||
$feature_template
|
$featureTemplate
|
||||||
->setFeatureId($event->getFeatureId())
|
->setFeatureId($event->getFeatureId())
|
||||||
->setTemplate($event->getTemplate())
|
->setTemplate($event->getTemplate())
|
||||||
->save()
|
->save()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteFeature(TemplateDeleteFeatureEvent $event)
|
public function deleteFeature(TemplateDeleteFeatureEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||||
{
|
{
|
||||||
$feature_template = FeatureTemplateQuery::create()
|
$featureTemplate = FeatureTemplateQuery::create()
|
||||||
->filterByFeatureId($event->getFeatureId())
|
->filterByFeatureId($event->getFeatureId())
|
||||||
->filterByTemplate($event->getTemplate())->findOne()
|
->filterByTemplate($event->getTemplate())->findOne()
|
||||||
;
|
;
|
||||||
|
|
||||||
if ($feature_template !== null) {
|
if ($featureTemplate !== null) {
|
||||||
$feature_template->delete();
|
$featureTemplate
|
||||||
|
->setDispatcher($dispatcher)
|
||||||
|
->delete();
|
||||||
|
} else {
|
||||||
|
// Prevent event propagation
|
||||||
|
$event->stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@@ -214,16 +273,16 @@ class Template extends BaseAction implements EventSubscriberInterface
|
|||||||
TheliaEvents::TEMPLATE_CREATE => array("create", 128),
|
TheliaEvents::TEMPLATE_CREATE => array("create", 128),
|
||||||
TheliaEvents::TEMPLATE_UPDATE => array("update", 128),
|
TheliaEvents::TEMPLATE_UPDATE => array("update", 128),
|
||||||
TheliaEvents::TEMPLATE_DELETE => array("delete", 128),
|
TheliaEvents::TEMPLATE_DELETE => array("delete", 128),
|
||||||
|
TheliaEvents::TEMPLATE_DUPLICATE => array("duplicate", 128),
|
||||||
|
|
||||||
TheliaEvents::TEMPLATE_ADD_ATTRIBUTE => array("addAttribute", 128),
|
TheliaEvents::TEMPLATE_ADD_ATTRIBUTE => array("addAttribute", 128),
|
||||||
TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE => array("deleteAttribute", 128),
|
TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE => array("deleteAttribute", 128),
|
||||||
|
|
||||||
TheliaEvents::TEMPLATE_ADD_FEATURE => array("addFeature", 128),
|
TheliaEvents::TEMPLATE_ADD_FEATURE => array("addFeature", 128),
|
||||||
TheliaEvents::TEMPLATE_DELETE_FEATURE => array("deleteFeature", 128),
|
TheliaEvents::TEMPLATE_DELETE_FEATURE => array("deleteFeature", 128),
|
||||||
|
|
||||||
TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION => array('updateAttributePosition', 128),
|
TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION => array('updateAttributePosition', 128),
|
||||||
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION => array('updateFeaturePosition', 128),
|
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION => array('updateFeaturePosition', 128),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,9 @@ class ContainerAwareCommand extends Command implements ContainerAwareInterface
|
|||||||
|
|
||||||
$requestContext = new RequestContext();
|
$requestContext = new RequestContext();
|
||||||
$requestContext->fromRequest($request);
|
$requestContext->fromRequest($request);
|
||||||
$url = new URL($container);
|
$url = $container->get('thelia.url.manager');
|
||||||
$url->setRequestContext($requestContext);
|
$url->setRequestContext($requestContext);
|
||||||
|
$this->getContainer()->get('router.admin')->setContext($requestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ class HookCleanCommand extends ContainerAwareCommand
|
|||||||
} catch (\Exception $ex) {
|
} catch (\Exception $ex) {
|
||||||
$output->writeln(sprintf("<error>%s</error>", $ex->getMessage()));
|
$output->writeln(sprintf("<error>%s</error>", $ex->getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getModule(InputInterface $input)
|
private function getModule(InputInterface $input)
|
||||||
|
|||||||
@@ -12,10 +12,13 @@
|
|||||||
|
|
||||||
namespace Thelia\Command;
|
namespace Thelia\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
use Thelia\Action\Module;
|
||||||
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
use Thelia\Model\ModuleQuery;
|
use Thelia\Model\ModuleQuery;
|
||||||
@@ -47,6 +50,12 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
|||||||
InputArgument::REQUIRED,
|
InputArgument::REQUIRED,
|
||||||
"module to deactivate"
|
"module to deactivate"
|
||||||
)
|
)
|
||||||
|
->addOption(
|
||||||
|
"assume-yes",
|
||||||
|
'y',
|
||||||
|
InputOption::VALUE_NONE,
|
||||||
|
'Assume to deactivate a mandatory module'
|
||||||
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +76,15 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$event = new ModuleToggleActivationEvent($module->getId());
|
$event = new ModuleToggleActivationEvent($module->getId());
|
||||||
|
|
||||||
|
$module = ModuleQuery::create()->findPk($module->getId());
|
||||||
|
if ($module->getMandatory() == BaseModule::IS_MANDATORY) {
|
||||||
|
if (!$this->askConfirmation($input, $output)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$event->setAssumeDeactivate(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ($input->getOption("with-dependencies")) {
|
if ($input->getOption("with-dependencies")) {
|
||||||
$event->setRecursive(true);
|
$event->setRecursive(true);
|
||||||
}
|
}
|
||||||
@@ -84,4 +102,33 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
|||||||
), "bg=green;fg=black");
|
), "bg=green;fg=black");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function askConfirmation(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$assumeYes = $input->getOption("assume-yes");
|
||||||
|
$moduleCode = $input->getArgument("module");
|
||||||
|
|
||||||
|
if (!$assumeYes) {
|
||||||
|
/** @var QuestionHelper $helper */
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$questionText = "Module ";
|
||||||
|
$questionText .= (empty($moduleCode))
|
||||||
|
? ""
|
||||||
|
: $moduleCode;
|
||||||
|
$questionText .= " is mandatory.\n";
|
||||||
|
$questionText .= "Would you like to deactivate the module ";
|
||||||
|
$questionText .= (empty($moduleCode))
|
||||||
|
? ""
|
||||||
|
: $moduleCode;
|
||||||
|
$questionText .= " ? (yes, or no) ";
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion($questionText, false);
|
||||||
|
|
||||||
|
if (!$helper->ask($input, $output, $question)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,4 +38,6 @@
|
|||||||
-->
|
-->
|
||||||
<thelia>2.2.0</thelia>
|
<thelia>2.2.0</thelia>
|
||||||
<stability>other</stability>
|
<stability>other</stability>
|
||||||
|
<mandatory>0</mandatory>
|
||||||
|
<hidden>0</hidden>
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
@@ -99,18 +99,18 @@ class CartContainsCategories extends ConditionAbstract
|
|||||||
|
|
||||||
/** @var Category $category */
|
/** @var Category $category */
|
||||||
foreach ($categories as $category) {
|
foreach ($categories as $category) {
|
||||||
$catecoryInCart = $this->conditionValidator->variableOpComparison(
|
if (! $this->conditionValidator->variableOpComparison(
|
||||||
$category->getId(),
|
$category->getId(),
|
||||||
$this->operators[self::CATEGORIES_LIST],
|
$this->operators[self::CATEGORIES_LIST],
|
||||||
$this->values[self::CATEGORIES_LIST]
|
$this->values[self::CATEGORIES_LIST]
|
||||||
);
|
)) {
|
||||||
|
// cart item doesn't match go to next cart item
|
||||||
if ($catecoryInCart) {
|
continue 2;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// cart item match
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ class CartContainsProducts extends ConditionAbstract
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,5 +79,4 @@ class MatchForXArticlesIncludeQuantity extends MatchForXArticles
|
|||||||
|
|
||||||
return $toolTip;
|
return $toolTip;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ return array(
|
|||||||
' note: only non-visible documents can be associated.' => ' note: only non-visible documents can be associated.',
|
' note: only non-visible documents can be associated.' => ' note: only non-visible documents can be associated.',
|
||||||
'"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" parameter cannot be empty in loop type: %type, name: %name',
|
'"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" parameter cannot be empty in loop type: %type, name: %name',
|
||||||
'"%param" parameter is missing in loop type: %type, name: %name' => '"%param" parameter is missing in loop type: %type, name: %name',
|
'"%param" parameter is missing in loop type: %type, name: %name' => '"%param" parameter is missing in loop type: %type, name: %name',
|
||||||
|
'#000000' => '#000000',
|
||||||
'%module (version: %version)' => '%module (version: %version)',
|
'%module (version: %version)' => '%module (version: %version)',
|
||||||
'%n for number, %c for the currency code, %s for the currency symbol' => '%n for number, %c for the currency code, %s for the currency symbol',
|
'%n for number, %c for the currency code, %s for the currency symbol' => '%n for number, %c for the currency code, %s for the currency symbol',
|
||||||
'%obj SEO modification' => '%obj SEO modification',
|
'%obj SEO modification' => '%obj SEO modification',
|
||||||
@@ -52,6 +53,7 @@ return array(
|
|||||||
'All countries' => 'All countries',
|
'All countries' => 'All countries',
|
||||||
'All shipping methods' => 'All shipping methods',
|
'All shipping methods' => 'All shipping methods',
|
||||||
'Amount' => 'Amount',
|
'Amount' => 'Amount',
|
||||||
|
'An administrator with thie email address already exists' => 'An administrator with this email address already exists',
|
||||||
'An administrator with this email address already exists' => 'An administrator with this email address already exists',
|
'An administrator with this email address already exists' => 'An administrator with this email address already exists',
|
||||||
'An invalid token was provided, your password cannot be changed' => 'An invalid token was provided, your password cannot be changed',
|
'An invalid token was provided, your password cannot be changed' => 'An invalid token was provided, your password cannot be changed',
|
||||||
'Apply exchange rates on price in %sym' => 'Apply exchange rates on price in %sym',
|
'Apply exchange rates on price in %sym' => 'Apply exchange rates on price in %sym',
|
||||||
@@ -81,6 +83,8 @@ return array(
|
|||||||
'By Module' => 'By Module',
|
'By Module' => 'By Module',
|
||||||
'CSS' => 'CSS',
|
'CSS' => 'CSS',
|
||||||
'CSS stylesheet' => 'CSS stylesheet',
|
'CSS stylesheet' => 'CSS stylesheet',
|
||||||
|
'Can\'t deactivate a secure module' => 'Can\'t deactivate a secure module',
|
||||||
|
'Can\'t remove a core module' => 'Can\'t remove a core module',
|
||||||
'Cannot disable the default language' => 'Cannot disable the default language',
|
'Cannot disable the default language' => 'Cannot disable the default language',
|
||||||
'Cannot find a default country. Please define one.' => 'Cannot find a default country. Please define one.',
|
'Cannot find a default country. Please define one.' => 'Cannot find a default country. Please define one.',
|
||||||
'Cannot find the shop country. Please select a shop country.' => 'Cannot find the shop country. Please select a shop country.',
|
'Cannot find the shop country. Please select a shop country.' => 'Cannot find the shop country. Please select a shop country.',
|
||||||
@@ -106,6 +110,7 @@ return array(
|
|||||||
'Change password' => 'Change password',
|
'Change password' => 'Change password',
|
||||||
'Check country iso codes <a href="http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes" target="_blank">here</a>.' => 'Check country iso codes <a href="http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes" target="_blank">in Wikipedia</a>.',
|
'Check country iso codes <a href="http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes" target="_blank">here</a>.' => 'Check country iso codes <a href="http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes" target="_blank">in Wikipedia</a>.',
|
||||||
'Check the total Cart amount in the given currency' => 'Check the total Cart amount in the given currency',
|
'Check the total Cart amount in the given currency' => 'Check the total Cart amount in the given currency',
|
||||||
|
'Choice a color for this order status code' => 'Choice a color for this order status code',
|
||||||
'City' => 'City',
|
'City' => 'City',
|
||||||
'Code' => 'Code',
|
'Code' => 'Code',
|
||||||
'Combination builder' => 'Combination builder',
|
'Combination builder' => 'Combination builder',
|
||||||
@@ -180,6 +185,8 @@ return array(
|
|||||||
'Enter here the brand name in the default language (%title%)' => 'Enter here the brand name in the default language (%title%)',
|
'Enter here the brand name in the default language (%title%)' => 'Enter here the brand name in the default language (%title%)',
|
||||||
'Enter here the category title in the default language (%title%)' => 'Enter here the category title in the default language (%title%)',
|
'Enter here the category title in the default language (%title%)' => 'Enter here the category title in the default language (%title%)',
|
||||||
'Enter here the mail template purpose in the default language (%title%)' => 'Enter here the mail template purpose in the default language (%title%)',
|
'Enter here the mail template purpose in the default language (%title%)' => 'Enter here the mail template purpose in the default language (%title%)',
|
||||||
|
'Enter here the order status code' => 'Enter here the order status code',
|
||||||
|
'Enter here the order status name in the default language (%title%)' => 'Enter here the order status name in the default language (%title%)',
|
||||||
'Enter here the sale name in the default language (%title%)' => 'Enter here the sale name in the default language (%title%)',
|
'Enter here the sale name in the default language (%title%)' => 'Enter here the sale name in the default language (%title%)',
|
||||||
'Enter the new password' => 'Enter the new password',
|
'Enter the new password' => 'Enter the new password',
|
||||||
'Enter the new password again' => 'Enter the new password again',
|
'Enter the new password again' => 'Enter the new password again',
|
||||||
@@ -187,6 +194,8 @@ return array(
|
|||||||
'Error during %action process : %error. Exception was %exc' => 'Error during %action process : %error. Exception was %exc',
|
'Error during %action process : %error. Exception was %exc' => 'Error during %action process : %error. Exception was %exc',
|
||||||
'Error occured while processing order ref. %ref, ID %id: %err' => 'Error occurred while processing order ref. %ref, ID %id: %err',
|
'Error occured while processing order ref. %ref, ID %id: %err' => 'Error occurred while processing order ref. %ref, ID %id: %err',
|
||||||
'Error occured.' => 'Error occurred.',
|
'Error occured.' => 'Error occurred.',
|
||||||
|
'Error occurred while cancelling order ref. %ref, ID %id: %err' => 'Error occurred while cancelling order ref. %ref, ID %id: %err',
|
||||||
|
'Error occurred while saving payment transaction %transaction_ref for order ID %id.' => 'Error occurred while saving payment transaction %transaction_ref for order ID %id.',
|
||||||
'Error(s) in import :<br />%errors' => 'Error(s) in import :<br />%errors',
|
'Error(s) in import :<br />%errors' => 'Error(s) in import :<br />%errors',
|
||||||
'Errors' => 'Errors',
|
'Errors' => 'Errors',
|
||||||
'Export' => 'Export',
|
'Export' => 'Export',
|
||||||
@@ -346,6 +355,9 @@ return array(
|
|||||||
'Order failed' => 'Order failed',
|
'Order failed' => 'Order failed',
|
||||||
'Order ref. %ref is now unpaid.' => 'Order ref. %ref is now unpaid.',
|
'Order ref. %ref is now unpaid.' => 'Order ref. %ref is now unpaid.',
|
||||||
'Order ref. %ref, ID %id has been successfully paid.' => 'Order ref. %ref, ID %id has been successfully paid.',
|
'Order ref. %ref, ID %id has been successfully paid.' => 'Order ref. %ref, ID %id has been successfully paid.',
|
||||||
|
'Order status code' => 'Order status code',
|
||||||
|
'Order status color' => 'Order status color',
|
||||||
|
'Order status name' => 'Order status name',
|
||||||
'Orders' => 'Orders',
|
'Orders' => 'Orders',
|
||||||
'Overall' => 'Overall',
|
'Overall' => 'Overall',
|
||||||
'Page 404' => 'Page 404',
|
'Page 404' => 'Page 404',
|
||||||
@@ -357,6 +369,8 @@ return array(
|
|||||||
'Password confirmation' => 'Password confirmation',
|
'Password confirmation' => 'Password confirmation',
|
||||||
'Payment failed' => 'Payment failed',
|
'Payment failed' => 'Payment failed',
|
||||||
'Payment gateway' => 'Payment gateway',
|
'Payment gateway' => 'Payment gateway',
|
||||||
|
'Payment module ID not found' => 'Payment module ID not found',
|
||||||
|
'Payment transaction %transaction_ref for order ref. %ref, ID %id has been successfully saved.' => 'Payment transaction %transaction_ref for order ref. %ref, ID %id has been successfully saved.',
|
||||||
'Per customer' => 'Per customer',
|
'Per customer' => 'Per customer',
|
||||||
'Percent' => 'Percent',
|
'Percent' => 'Percent',
|
||||||
'Percentage' => 'Percentage',
|
'Percentage' => 'Percentage',
|
||||||
@@ -421,6 +435,7 @@ return array(
|
|||||||
'Range date Start' => 'Range date Start',
|
'Range date Start' => 'Range date Start',
|
||||||
'Rate' => 'Rate',
|
'Rate' => 'Rate',
|
||||||
'Rate from %currencyCode' => 'Rate from %currencyCode',
|
'Rate from %currencyCode' => 'Rate from %currencyCode',
|
||||||
|
'Recipient e-mail address' => 'Recipient e-mail address',
|
||||||
'Redirecting ...' => 'Redirecting ...',
|
'Redirecting ...' => 'Redirecting ...',
|
||||||
'Redirecting to %url' => 'Redirecting to %url',
|
'Redirecting to %url' => 'Redirecting to %url',
|
||||||
'Reference' => 'Reference',
|
'Reference' => 'Reference',
|
||||||
@@ -453,6 +468,7 @@ return array(
|
|||||||
'Select the product brand, or supplier.' => 'Select the product brand, or supplier.',
|
'Select the product brand, or supplier.' => 'Select the product brand, or supplier.',
|
||||||
'Select the products covered by this operation' => 'Select the products covered by this operation',
|
'Select the products covered by this operation' => 'Select the products covered by this operation',
|
||||||
'Select the virtual document' => 'Select the virtual document',
|
'Select the virtual document' => 'Select the virtual document',
|
||||||
|
'Send test e-mail to:' => 'Send test e-mail to:',
|
||||||
'Service ID' => 'Service ID',
|
'Service ID' => 'Service ID',
|
||||||
'Shipping configuration' => 'Shipping configuration',
|
'Shipping configuration' => 'Shipping configuration',
|
||||||
'Shipping zone name' => 'Shipping zone name',
|
'Shipping zone name' => 'Shipping zone name',
|
||||||
@@ -460,6 +476,8 @@ return array(
|
|||||||
'Short description text' => 'Short description text',
|
'Short description text' => 'Short description text',
|
||||||
'Show redirections *' => 'Show redirections *',
|
'Show redirections *' => 'Show redirections *',
|
||||||
'Sitemap' => 'Sitemap',
|
'Sitemap' => 'Sitemap',
|
||||||
|
'Some commands use this status.' => 'Some commands use this status.',
|
||||||
|
'Something goes wrong, the message was not sent to recipient. Error is : %err' => 'Something goes wrong, the message was not sent to recipient. Error is : %err',
|
||||||
'Sorry, an error occured.' => 'Sorry, an error occurred.',
|
'Sorry, an error occured.' => 'Sorry, an error occurred.',
|
||||||
'Sorry, an error occured: %msg' => 'Sorry, an error occurred: %msg',
|
'Sorry, an error occured: %msg' => 'Sorry, an error occurred: %msg',
|
||||||
'Sorry, an error occured: %s' => 'Sorry, an error occurred: %s',
|
'Sorry, an error occured: %s' => 'Sorry, an error occurred: %s',
|
||||||
@@ -536,6 +554,7 @@ return array(
|
|||||||
'The lost admin password recovery feature is disabled.' => 'The lost admin password recovery feature is disabled.',
|
'The lost admin password recovery feature is disabled.' => 'The lost admin password recovery feature is disabled.',
|
||||||
'The mailing template in HTML format.' => 'The mailing template in HTML format.',
|
'The mailing template in HTML format.' => 'The mailing template in HTML format.',
|
||||||
'The mailing template in text-only format.' => 'The mailing template in text-only format.',
|
'The mailing template in text-only format.' => 'The mailing template in text-only format.',
|
||||||
|
'The message has been successfully sent to %recipient.' => 'The message has been successfully sent to %recipient.',
|
||||||
'The method %method% doesn\'t exist in classname %classname%' => 'The method %method% doesn\'t exist in classname %classname%',
|
'The method %method% doesn\'t exist in classname %classname%' => 'The method %method% doesn\'t exist in classname %classname%',
|
||||||
'The method name that will handle the hook event.' => 'The method name that will handle the hook event.',
|
'The method name that will handle the hook event.' => 'The method name that will handle the hook event.',
|
||||||
'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.',
|
'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.',
|
||||||
@@ -545,6 +564,8 @@ return array(
|
|||||||
'The module has to be activated.' => 'The module has to be activated.',
|
'The module has to be activated.' => 'The module has to be activated.',
|
||||||
'The module is not valid : %message' => 'The module is not valid : %message',
|
'The module is not valid : %message' => 'The module is not valid : %message',
|
||||||
'The module zip file' => 'The module zip file',
|
'The module zip file' => 'The module zip file',
|
||||||
|
'The order status code' => 'The order status code',
|
||||||
|
'The order status name or title' => 'The order status name or title',
|
||||||
'The product document id %id doesn\'t exists' => 'The product document id %id doesn\'t exists',
|
'The product document id %id doesn\'t exists' => 'The product document id %id doesn\'t exists',
|
||||||
'The product image id %id doesn\'t exists' => 'The product image id %id doesn\'t exists',
|
'The product image id %id doesn\'t exists' => 'The product image id %id doesn\'t exists',
|
||||||
'The product sale element id %id doesn\'t exist' => 'The product sale element id %id doesn\'t exist',
|
'The product sale element id %id doesn\'t exist' => 'The product sale element id %id doesn\'t exist',
|
||||||
@@ -574,6 +595,7 @@ return array(
|
|||||||
'This administrator login already exists' => 'This administrator login already exists',
|
'This administrator login already exists' => 'This administrator login already exists',
|
||||||
'This brand is online' => 'This brand is online',
|
'This brand is online' => 'This brand is online',
|
||||||
'This category is online' => 'This category is online',
|
'This category is online' => 'This category is online',
|
||||||
|
'This code is already used.' => 'This code is already used.',
|
||||||
'This condition is always true' => 'This condition is always true',
|
'This condition is always true' => 'This condition is always true',
|
||||||
'This content is online.' => 'This content is online.',
|
'This content is online.' => 'This content is online.',
|
||||||
'This country has states / provinces' => 'This country has states / provinces',
|
'This country has states / provinces' => 'This country has states / provinces',
|
||||||
@@ -596,6 +618,8 @@ return array(
|
|||||||
'This image is online' => 'This image is online',
|
'This image is online' => 'This image is online',
|
||||||
'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.',
|
'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.',
|
||||||
'This is an identifier that will be used in the code to get this message' => 'This is an identifier that will be used in the code to get this message',
|
'This is an identifier that will be used in the code to get this message' => 'This is an identifier that will be used in the code to get this message',
|
||||||
|
'This is not a hexadecimal color.' => 'This is not a hexadecimal color.',
|
||||||
|
'This is not a valid code.' => 'This is not a valid code.',
|
||||||
'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'This is the contact email address, and the sender email of all e-mails sent by your store.',
|
'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'This is the contact email address, and the sender email of all e-mails sent by your store.',
|
||||||
'This is the message purpose, such as \'Order confirmation\'.' => 'This is the message purpose, such as \'Order confirmation\'.',
|
'This is the message purpose, such as \'Order confirmation\'.' => 'This is the message purpose, such as \'Order confirmation\'.',
|
||||||
'This is the name used on the login screen' => 'This is the name used on the login screen',
|
'This is the name used on the login screen' => 'This is the name used on the login screen',
|
||||||
@@ -608,6 +632,7 @@ return array(
|
|||||||
'This product_sale_elements_id does not exists for this product : %d' => 'This product_sale_elements_id does not exists for this product : %d',
|
'This product_sale_elements_id does not exists for this product : %d' => 'This product_sale_elements_id does not exists for this product : %d',
|
||||||
'This state doesn\'t belong to this country.' => 'This state doesn\'t belong to this country.',
|
'This state doesn\'t belong to this country.' => 'This state doesn\'t belong to this country.',
|
||||||
'This state is online' => 'This state is online',
|
'This state is online' => 'This state is online',
|
||||||
|
'This status is protected.' => 'This status is protected.',
|
||||||
'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.',
|
'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.',
|
||||||
'This the unique name of this message. Do not change this value unless you understand what you do.' => 'This the unique name of this message. Do not change this value unless you understand what you do.',
|
'This the unique name of this message. Do not change this value unless you understand what you do.' => 'This the unique name of this message. Do not change this value unless you understand what you do.',
|
||||||
'This value should not be blank.' => 'This value should not be blank.',
|
'This value should not be blank.' => 'This value should not be blank.',
|
||||||
@@ -654,6 +679,7 @@ return array(
|
|||||||
'Wrong form method, %s expected.' => 'Wrong form method, %s expected.',
|
'Wrong form method, %s expected.' => 'Wrong form method, %s expected.',
|
||||||
'Yes, I have a password :' => 'Yes, I have a password :',
|
'Yes, I have a password :' => 'Yes, I have a password :',
|
||||||
'You are already registered!' => 'You are already registered!',
|
'You are already registered!' => 'You are already registered!',
|
||||||
|
'You can not delete it.' => 'You can not delete it.',
|
||||||
'You don\'t need to use commas or other punctuations.' => 'You don\'t need to use commas or other punctuations.',
|
'You don\'t need to use commas or other punctuations.' => 'You don\'t need to use commas or other punctuations.',
|
||||||
'You have to configure your store email first !' => 'You have to configure your store email first !',
|
'You have to configure your store email first !' => 'You have to configure your store email first !',
|
||||||
'You must select at least one attribute.' => 'You must select at least one attribute.',
|
'You must select at least one attribute.' => 'You must select at least one attribute.',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
' content create form' => 'Formulaire de création de contenu',
|
' content create form' => 'Formulaire de création de contenu',
|
||||||
' note: only non-visible documents can be associated.' => 'remarque : seuls ces modules. les documents non visibles peuvent être associés.',
|
' note: only non-visible documents can be associated.' => 'remarque : seuls ces modules. les documents non visibles peuvent être associés.',
|
||||||
'"%param" parameter cannot be empty in loop type: %type, name: %name' => 'Le paramètre "%param" ne peut être vide dans la boucle type: %type, nom: %name ',
|
'"%param" parameter cannot be empty in loop type: %type, name: %name' => 'Le paramètre "%param" ne peut être vide dans la boucle type: %type, nom: %name ',
|
||||||
@@ -70,6 +70,8 @@ return [
|
|||||||
'Available shipping zones' => 'Zones de livraison disponibles',
|
'Available shipping zones' => 'Zones de livraison disponibles',
|
||||||
'Back Office' => 'Back Office',
|
'Back Office' => 'Back Office',
|
||||||
'Bad tax list JSON' => 'Mauvais JSON de la liste des taxes',
|
'Bad tax list JSON' => 'Mauvais JSON de la liste des taxes',
|
||||||
|
'Banner' => 'Bannière',
|
||||||
|
'Banner of the website. Used in the e-mails send to the customers.' => 'Bannière du site utilisée dans le contenu des mails envoyés aux clients.',
|
||||||
'Billing country' => 'Pays de facturation',
|
'Billing country' => 'Pays de facturation',
|
||||||
'Billing country is' => 'Le pays de facturation est',
|
'Billing country is' => 'Le pays de facturation est',
|
||||||
'Brand' => 'Marque',
|
'Brand' => 'Marque',
|
||||||
@@ -80,6 +82,8 @@ return [
|
|||||||
'By Module' => 'Par module',
|
'By Module' => 'Par module',
|
||||||
'CSS' => 'CSS',
|
'CSS' => 'CSS',
|
||||||
'CSS stylesheet' => 'Feuille de style CSS',
|
'CSS stylesheet' => 'Feuille de style CSS',
|
||||||
|
'Can\'t deactivate a secure module' => 'Impossible de désactiver un module sécurisé',
|
||||||
|
'Can\'t remove a core module' => 'Impossible de supprimer un module de base',
|
||||||
'Cannot disable the default language' => 'Impossible de désactiver la langue par défaut',
|
'Cannot disable the default language' => 'Impossible de désactiver la langue par défaut',
|
||||||
'Cannot find a default country. Please define one.' => 'Impossible de trouver un pays par défaut. Veuillez en définir un.',
|
'Cannot find a default country. Please define one.' => 'Impossible de trouver un pays par défaut. Veuillez en définir un.',
|
||||||
'Cannot find the shop country. Please select a shop country.' => 'Impossible de trouver le pays du magasin. Veuillez en sélectionner un.',
|
'Cannot find the shop country. Please select a shop country.' => 'Impossible de trouver le pays du magasin. Veuillez en sélectionner un.',
|
||||||
@@ -203,6 +207,7 @@ return [
|
|||||||
'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'L\'ouverture du fichier %file a échoué. Merci de vérifier que ce fichier est accessible en écriture pour votre serveur Web.',
|
'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'L\'ouverture du fichier %file a échoué. Merci de vérifier que ce fichier est accessible en écriture pour votre serveur Web.',
|
||||||
'Failed to send message %code. Failed recipients: %failed_addresses' => 'Erreur lors de l\'envoi du message %code. Echec pour les destinataires %failed_addresses',
|
'Failed to send message %code. Failed recipients: %failed_addresses' => 'Erreur lors de l\'envoi du message %code. Echec pour les destinataires %failed_addresses',
|
||||||
'Failed to update language definition: %ex' => 'Erreur lors de la mise à jour de la définition de la langue : %ex',
|
'Failed to update language definition: %ex' => 'Erreur lors de la mise à jour de la définition de la langue : %ex',
|
||||||
|
'Favicon image' => 'Icône du site',
|
||||||
'Fax' => 'Fax',
|
'Fax' => 'Fax',
|
||||||
'Feature' => 'Caractéristique',
|
'Feature' => 'Caractéristique',
|
||||||
'Feature value does not match FLOAT format' => 'valeur de caractéristique n\'est pas un FLOAT',
|
'Feature value does not match FLOAT format' => 'valeur de caractéristique n\'est pas un FLOAT',
|
||||||
@@ -240,6 +245,7 @@ return [
|
|||||||
'Hooks' => 'Points d\'accroche',
|
'Hooks' => 'Points d\'accroche',
|
||||||
'Host' => 'Nom de l\'hôte',
|
'Host' => 'Nom de l\'hôte',
|
||||||
'I would like to receive the newsletter or the latest news.' => 'Je souhaite recevoir la lettre d\'information ou les dernières actualités.',
|
'I would like to receive the newsletter or the latest news.' => 'Je souhaite recevoir la lettre d\'information ou les dernières actualités.',
|
||||||
|
'Icon of the website. Only PNG and ICO files are allowed.' => 'Icône du site. Seuls les fichiers au format PNG ou ICO sont autorisés.',
|
||||||
'ISO 4217 code' => 'Code ISO 4217',
|
'ISO 4217 code' => 'Code ISO 4217',
|
||||||
'ISO 639-1 Code' => 'Code ISO 639-1',
|
'ISO 639-1 Code' => 'Code ISO 639-1',
|
||||||
'ISO Alpha-2 code' => 'Code ISO Alpha-2',
|
'ISO Alpha-2 code' => 'Code ISO Alpha-2',
|
||||||
@@ -355,6 +361,7 @@ return [
|
|||||||
'Password confirmation' => 'Confirmation du mot de passe.',
|
'Password confirmation' => 'Confirmation du mot de passe.',
|
||||||
'Payment failed' => 'Echec du paiement',
|
'Payment failed' => 'Echec du paiement',
|
||||||
'Payment gateway' => 'Passerelle de paiement',
|
'Payment gateway' => 'Passerelle de paiement',
|
||||||
|
'Payment module ID not found' => 'ID du module de paiement non trouvé',
|
||||||
'Per customer' => 'Par client',
|
'Per customer' => 'Par client',
|
||||||
'Percent' => 'Pourcent',
|
'Percent' => 'Pourcent',
|
||||||
'Percentage' => 'Pourcentage',
|
'Percentage' => 'Pourcentage',
|
||||||
@@ -419,6 +426,7 @@ return [
|
|||||||
'Range date Start' => 'Date de début',
|
'Range date Start' => 'Date de début',
|
||||||
'Rate' => 'Taux',
|
'Rate' => 'Taux',
|
||||||
'Rate from %currencyCode' => 'Taux pour %currencyCode',
|
'Rate from %currencyCode' => 'Taux pour %currencyCode',
|
||||||
|
'Recipient e-mail address' => 'Adresse e-mail du destinataire',
|
||||||
'Redirecting ...' => 'Redirection ...',
|
'Redirecting ...' => 'Redirection ...',
|
||||||
'Redirecting to %url' => 'Redirection vers %url',
|
'Redirecting to %url' => 'Redirection vers %url',
|
||||||
'Reference' => 'Référence',
|
'Reference' => 'Référence',
|
||||||
@@ -451,6 +459,7 @@ return [
|
|||||||
'Select the product brand, or supplier.' => 'Choisissez la marque ou le fournisseur du produit.',
|
'Select the product brand, or supplier.' => 'Choisissez la marque ou le fournisseur du produit.',
|
||||||
'Select the products covered by this operation' => 'Produits inclus dans cette promotion',
|
'Select the products covered by this operation' => 'Produits inclus dans cette promotion',
|
||||||
'Select the virtual document' => 'Sélectionnez le document virtuel',
|
'Select the virtual document' => 'Sélectionnez le document virtuel',
|
||||||
|
'Send test e-mail to:' => 'Envoyer un email de test à: ',
|
||||||
'Service ID' => 'ID du service',
|
'Service ID' => 'ID du service',
|
||||||
'Shipping configuration' => 'Configuration du transport',
|
'Shipping configuration' => 'Configuration du transport',
|
||||||
'Shipping zone name' => 'Nom de la zone de livraison',
|
'Shipping zone name' => 'Nom de la zone de livraison',
|
||||||
@@ -478,6 +487,7 @@ return [
|
|||||||
'Store configuration failed.' => 'Erreur de configuration du magasin.',
|
'Store configuration failed.' => 'Erreur de configuration du magasin.',
|
||||||
'Store description' => 'Description du magasin',
|
'Store description' => 'Description du magasin',
|
||||||
'Store email address' => 'Adresse mail du magasin',
|
'Store email address' => 'Adresse mail du magasin',
|
||||||
|
'Store logo' => 'Logo de la boutique',
|
||||||
'Store logs into text file' => 'Conserver les logs dans des fichiers texte',
|
'Store logs into text file' => 'Conserver les logs dans des fichiers texte',
|
||||||
'Store logs into text file, up to a certian size, then a new file is created' => 'Sauvegarder les logs dans un fichier texte. A partir d\'une certaine taille un nouveau fichier est créé',
|
'Store logs into text file, up to a certian size, then a new file is created' => 'Sauvegarder les logs dans un fichier texte. A partir d\'une certaine taille un nouveau fichier est créé',
|
||||||
'Store name' => 'Nom du magasin',
|
'Store name' => 'Nom du magasin',
|
||||||
@@ -535,7 +545,7 @@ return [
|
|||||||
'The method %method% doesn\'t exist in classname %classname%' => 'La méthode %method% n\'existe pas dans la classe %classname%',
|
'The method %method% doesn\'t exist in classname %classname%' => 'La méthode %method% n\'existe pas dans la classe %classname%',
|
||||||
'The method name that will handle the hook event.' => 'Le nom de la méthode qui va traiter l\'évènement du point d\'accroche.',
|
'The method name that will handle the hook event.' => 'Le nom de la méthode qui va traiter l\'évènement du point d\'accroche.',
|
||||||
'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'Le module "%name%" est utilisé par au moins une commande, et ne peut être supprimé.',
|
'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'Le module "%name%" est utilisé par au moins une commande, et ne peut être supprimé.',
|
||||||
'The module %module has been installed successfully.' => 'Le module %module a été activé avec succès.',
|
'The module %module has been installed successfully.' => 'Le module %module a été installé avec succès.',
|
||||||
'The module %name is already installed in the same or greater version.' => 'Le module %name est déja installé dans la même version, ou dans une version plus récente.',
|
'The module %name is already installed in the same or greater version.' => 'Le module %name est déja installé dans la même version, ou dans une version plus récente.',
|
||||||
'The module %name requires Thelia %version or newer' => 'Le module %name nécessite Thelia %version ou plus récent',
|
'The module %name requires Thelia %version or newer' => 'Le module %name nécessite Thelia %version ou plus récent',
|
||||||
'The module has to be activated.' => 'Le module doit être activé.',
|
'The module has to be activated.' => 'Le module doit être activé.',
|
||||||
@@ -820,4 +830,4 @@ return [
|
|||||||
'update form' => 'Formulaire de modification',
|
'update form' => 'Formulaire de modification',
|
||||||
'value table header' => 'colonne tableau valeur',
|
'value table header' => 'colonne tableau valeur',
|
||||||
'value table row' => 'ligne tableau valeurs',
|
'value table row' => 'ligne tableau valeurs',
|
||||||
];
|
);
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
<tag name="kernel.event_subscriber"/>
|
<tag name="kernel.event_subscriber"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="thelia.action.order_status" class="Thelia\Action\OrderStatus">
|
||||||
|
<tag name="kernel.event_subscriber"/>
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="thelia.action.coupon" class="Thelia\Action\Coupon">
|
<service id="thelia.action.coupon" class="Thelia\Action\Coupon">
|
||||||
<argument type="service" id="request_stack"/>
|
<argument type="service" id="request_stack"/>
|
||||||
<argument type="service" id="thelia.coupon.factory"/>
|
<argument type="service" id="thelia.coupon.factory"/>
|
||||||
@@ -171,6 +175,7 @@
|
|||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="thelia.action.cache" class="Thelia\Action\Cache">
|
<service id="thelia.action.cache" class="Thelia\Action\Cache">
|
||||||
|
<argument type="service" id="thelia.cache"/>
|
||||||
<tag name="kernel.event_subscriber"/>
|
<tag name="kernel.event_subscriber"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
<parameter key="HOOK">admin.hook</parameter>
|
<parameter key="HOOK">admin.hook</parameter>
|
||||||
<parameter key="MODULE_HOOK">admin.module-hook</parameter>
|
<parameter key="MODULE_HOOK">admin.module-hook</parameter>
|
||||||
<parameter key="ORDER">admin.order</parameter>
|
<parameter key="ORDER">admin.order</parameter>
|
||||||
|
<parameter key="ORDER_STATUS">admin.configuration.order-status</parameter>
|
||||||
<parameter key="PRODUCT">admin.product</parameter>
|
<parameter key="PRODUCT">admin.product</parameter>
|
||||||
<parameter key="PROFILE">admin.configuration.profile</parameter>
|
<parameter key="PROFILE">admin.configuration.profile</parameter>
|
||||||
<parameter key="SHIPPING_ZONE">admin.configuration.shipping-zone</parameter>
|
<parameter key="SHIPPING_ZONE">admin.configuration.shipping-zone</parameter>
|
||||||
@@ -90,6 +91,9 @@
|
|||||||
|
|
||||||
<!-- Thelia logger class -->
|
<!-- Thelia logger class -->
|
||||||
<parameter key="thelia.logger.class">Thelia\Log\Tlog</parameter>
|
<parameter key="thelia.logger.class">Thelia\Log\Tlog</parameter>
|
||||||
|
|
||||||
|
<!-- Thelia Cache Config -->
|
||||||
|
<parameter key="thelia.cache.namespace">thelia_cache</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
|
|
||||||
|
|
||||||
@@ -352,7 +356,6 @@
|
|||||||
<argument>%admin.resources%</argument>
|
<argument>%admin.resources%</argument>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
|
||||||
<!-- Handlers -->
|
<!-- Handlers -->
|
||||||
<service id="thelia.export.handler" class="Thelia\Handler\ExportHandler">
|
<service id="thelia.export.handler" class="Thelia\Handler\ExportHandler">
|
||||||
<argument type="service" id="event_dispatcher" />
|
<argument type="service" id="event_dispatcher" />
|
||||||
@@ -365,5 +368,12 @@
|
|||||||
<argument type="service" id="thelia.archiver.manager" />
|
<argument type="service" id="thelia.archiver.manager" />
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service" id="service_container" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<!-- Cache -->
|
||||||
|
<service id="thelia.cache" class="Symfony\Component\Cache\Adapter\FilesystemAdapter">
|
||||||
|
<argument>%thelia.cache.namespace%</argument>
|
||||||
|
<argument>600</argument>
|
||||||
|
<argument>%kernel.cache_dir%</argument>
|
||||||
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</config>
|
</config>
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
|
|
||||||
<form name="thelia.admin.message.creation" class="Thelia\Form\MessageCreationForm"/>
|
<form name="thelia.admin.message.creation" class="Thelia\Form\MessageCreationForm"/>
|
||||||
<form name="thelia.admin.message.modification" class="Thelia\Form\MessageModificationForm"/>
|
<form name="thelia.admin.message.modification" class="Thelia\Form\MessageModificationForm"/>
|
||||||
|
<form name="thelia.admin.message.send-sample" class="Thelia\Form\MessageSendSampleForm"/>
|
||||||
|
|
||||||
<form name="thelia.admin.currency.creation" class="Thelia\Form\CurrencyCreationForm"/>
|
<form name="thelia.admin.currency.creation" class="Thelia\Form\CurrencyCreationForm"/>
|
||||||
<form name="thelia.admin.currency.modification" class="Thelia\Form\CurrencyModificationForm"/>
|
<form name="thelia.admin.currency.modification" class="Thelia\Form\CurrencyModificationForm"/>
|
||||||
@@ -162,6 +163,9 @@
|
|||||||
<form name="thelia_api_create" class="Thelia\Form\Api\ApiCreateForm"/>
|
<form name="thelia_api_create" class="Thelia\Form\Api\ApiCreateForm"/>
|
||||||
<form name="thelia_api_update" class="Thelia\Form\Api\ApiUpdateForm"/>
|
<form name="thelia_api_update" class="Thelia\Form\Api\ApiUpdateForm"/>
|
||||||
|
|
||||||
|
<form name="thelia.admin.order-status.creation" class="Thelia\Form\OrderStatus\OrderStatusCreationForm"/>
|
||||||
|
<form name="thelia.admin.order-status.modification" class="Thelia\Form\OrderStatus\OrderStatusModificationForm"/>
|
||||||
|
|
||||||
</forms>
|
</forms>
|
||||||
|
|
||||||
</config>
|
</config>
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
|
|
||||||
<services>
|
<services>
|
||||||
<service id="thelia.listener.view" class="Thelia\Core\EventListener\ViewListener">
|
<service id="thelia.listener.view" class="Thelia\Core\EventListener\ViewListener">
|
||||||
<tag name="kernel.event_subscriber"/>
|
|
||||||
<argument type="service" id="service_container"/>
|
<argument type="service" id="service_container"/>
|
||||||
|
<argument type="service" id="event_dispatcher"/>
|
||||||
|
<tag name="kernel.event_subscriber"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="controller.default" class="Thelia\Controller\DefaultController"/>
|
<service id="controller.default" class="Thelia\Controller\DefaultController"/>
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
<route id="admin.customer.update.process" path="/admin/customer/save">
|
<route id="admin.customer.update.process" path="/admin/customer/save">
|
||||||
<default key="_controller">Thelia\Controller\Admin\CustomerController::processUpdateAction</default>
|
<default key="_controller">Thelia\Controller\Admin\CustomerController::processUpdateAction</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
<route id="admin.customer.delete" path="/admin/customer/delete">
|
<route id="admin.customer.delete" path="/admin/customer/delete">
|
||||||
<default key="_controller">Thelia\Controller\Admin\CustomerController::deleteAction</default>
|
<default key="_controller">Thelia\Controller\Admin\CustomerController::deleteAction</default>
|
||||||
@@ -252,6 +252,36 @@
|
|||||||
|
|
||||||
<!-- end order management -->
|
<!-- end order management -->
|
||||||
|
|
||||||
|
<!-- order status management -->
|
||||||
|
|
||||||
|
<route id="admin.order-status.default" path="/admin/configuration/order-status">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::defaultAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.order-status.create" path="/admin/configuration/order-status/create">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::createAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.order-status.update" path="/admin/configuration/order-status/update/{order_status_id}">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::updateAction</default>
|
||||||
|
<requirement key="order_status_id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.order-status.save" path="/admin/configuration/order-status/save/{order_status_id}">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::processUpdateAction</default>
|
||||||
|
<requirement key="order_status_id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.order-status.delete" path="/admin/configuration/order-status/delete">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::deleteAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.order-status.update-position" path="/admin/configuration/order-status/update-position">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\OrderStatusController::updatePositionAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<!-- end order status management -->
|
||||||
|
|
||||||
<!-- Categories management -->
|
<!-- Categories management -->
|
||||||
|
|
||||||
<route id="admin.categories.default" path="/admin/categories">
|
<route id="admin.categories.default" path="/admin/categories">
|
||||||
@@ -725,6 +755,10 @@
|
|||||||
<default key="_controller">Thelia\Controller\Admin\TemplateController::deleteAction</default>
|
<default key="_controller">Thelia\Controller\Admin\TemplateController::deleteAction</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.configuration.templates.duplicate" path="/admin/configuration/templates/duplicate">
|
||||||
|
<default key="_controller">Thelia\Controller\Admin\TemplateController::duplicateAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
<route id="admin.configuration.templates.features.list" path="/admin/configuration/templates/features/list">
|
<route id="admin.configuration.templates.features.list" path="/admin/configuration/templates/features/list">
|
||||||
<default key="_controller">Thelia\Controller\Admin\TemplateController::getAjaxFeaturesAction</default>
|
<default key="_controller">Thelia\Controller\Admin\TemplateController::getAjaxFeaturesAction</default>
|
||||||
</route>
|
</route>
|
||||||
@@ -1544,6 +1578,11 @@
|
|||||||
<requirement key="messageId">\d+</requirement>
|
<requirement key="messageId">\d+</requirement>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.email.test_send" path="/admin/message/send/{messageId}" methods="post">
|
||||||
|
<default key="_controller">Thelia:Admin\Message:sendSampleByEmail</default>
|
||||||
|
<requirement key="messageId">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
<!-- The default route, to display a template -->
|
<!-- The default route, to display a template -->
|
||||||
|
|
||||||
<route id="admin.processTemplate" path="/admin/{template}">
|
<route id="admin.processTemplate" path="/admin/{template}">
|
||||||
|
|||||||
@@ -366,8 +366,6 @@ class BaseAdminController extends BaseController
|
|||||||
// Add the template standard extension
|
// Add the template standard extension
|
||||||
$templateName .= '.html';
|
$templateName .= '.html';
|
||||||
|
|
||||||
$session = $this->getSession();
|
|
||||||
|
|
||||||
// Find the current edit language ID
|
// Find the current edit language ID
|
||||||
$edition_language = $this->getCurrentEditionLang();
|
$edition_language = $this->getCurrentEditionLang();
|
||||||
|
|
||||||
@@ -376,16 +374,9 @@ class BaseAdminController extends BaseController
|
|||||||
|
|
||||||
// Prepare common template variables
|
// Prepare common template variables
|
||||||
$args = array_merge($args, array(
|
$args = array_merge($args, array(
|
||||||
'locale' => $session->getLang()->getLocale(),
|
|
||||||
'lang_code' => $session->getLang()->getCode(),
|
|
||||||
'lang_id' => $session->getLang()->getId(),
|
|
||||||
|
|
||||||
'edit_language_id' => $edition_language->getId(),
|
'edit_language_id' => $edition_language->getId(),
|
||||||
'edit_language_locale' => $edition_language->getLocale(),
|
'edit_language_locale' => $edition_language->getLocale(),
|
||||||
|
|
||||||
'edit_currency_id' => $edition_currency->getId(),
|
'edit_currency_id' => $edition_currency->getId(),
|
||||||
|
|
||||||
'current_url' => $this->getRequest()->getUri()
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// Update the current edition language & currency in session
|
// Update the current edition language & currency in session
|
||||||
|
|||||||
@@ -43,6 +43,29 @@ class ConfigStoreController extends BaseAdminController
|
|||||||
return $this->renderTemplate();
|
return $this->renderTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getAndWriteStoreMediaFileInConfig($form, $inputName, $configKey, $storeMediaUploadDir)
|
||||||
|
{
|
||||||
|
$file = $form->get($inputName)->getData();
|
||||||
|
|
||||||
|
if ($file != null) {
|
||||||
|
// Delete the old file
|
||||||
|
$fs = new \Symfony\Component\Filesystem\Filesystem();
|
||||||
|
$oldFileName = ConfigQuery::read($configKey);
|
||||||
|
|
||||||
|
if ($oldFileName !== null) {
|
||||||
|
$oldFilePath = $storeMediaUploadDir . DS . $oldFileName;
|
||||||
|
if ($fs->exists($oldFilePath)) {
|
||||||
|
$fs->remove($oldFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the new file
|
||||||
|
$newFileName = uniqid() . '-' . $file->getClientOriginalName();
|
||||||
|
$file->move($storeMediaUploadDir, $newFileName);
|
||||||
|
ConfigQuery::write($configKey, $newFileName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function saveAction()
|
public function saveAction()
|
||||||
{
|
{
|
||||||
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::UPDATE)) {
|
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::UPDATE)) {
|
||||||
@@ -56,11 +79,33 @@ class ConfigStoreController extends BaseAdminController
|
|||||||
try {
|
try {
|
||||||
$form = $this->validateForm($configStoreForm);
|
$form = $this->validateForm($configStoreForm);
|
||||||
|
|
||||||
|
$storeMediaUploadDir = ConfigQuery::read('images_library_path');
|
||||||
|
|
||||||
|
if ($storeMediaUploadDir === null) {
|
||||||
|
$storeMediaUploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images';
|
||||||
|
} else {
|
||||||
|
$storeMediaUploadDir = THELIA_ROOT . $storeMediaUploadDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
$storeMediaUploadDir .= DS . 'store';
|
||||||
|
|
||||||
|
// List of medias that can be uploaded through this form.
|
||||||
|
// [Name of the form input] => [Key in the config table]
|
||||||
|
$storeMediaList = [
|
||||||
|
'favicon_file' => 'favicon_file',
|
||||||
|
'logo_file' => 'logo_file',
|
||||||
|
'banner_file' => 'banner_file'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($storeMediaList as $input_name => $config_key) {
|
||||||
|
$this->getAndWriteStoreMediaFileInConfig($form, $input_name, $config_key, $storeMediaUploadDir);
|
||||||
|
}
|
||||||
|
|
||||||
$data = $form->getData();
|
$data = $form->getData();
|
||||||
|
|
||||||
// Update store
|
// Update store
|
||||||
foreach ($data as $name => $value) {
|
foreach ($data as $name => $value) {
|
||||||
if (! $configStoreForm->isTemplateDefinedHiddenFieldName($name)) {
|
if (!array_key_exists($name, $storeMediaList) && !$configStoreForm->isTemplateDefinedHiddenFieldName($name)) {
|
||||||
ConfigQuery::write($name, $value, false);
|
ConfigQuery::write($name, $value, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ class CountryController extends AbstractCrudController
|
|||||||
;
|
;
|
||||||
|
|
||||||
return $event;
|
return $event;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hydrateEvent($event, $formData)
|
protected function hydrateEvent($event, $formData)
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ class CouponController extends BaseAdminController
|
|||||||
$this->pageNotFound();
|
$this->pageNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = new ResponseRest($couponManager->drawBackOfficeInputs());
|
$response = new ResponseRest($couponManager->drawBackOfficeInputs(), 'text');
|
||||||
} else {
|
} else {
|
||||||
// Return an empty response if the service ID is not defined
|
// Return an empty response if the service ID is not defined
|
||||||
// Typically, when the user chooses "Please select a coupon type"
|
// Typically, when the user chooses "Please select a coupon type"
|
||||||
@@ -815,7 +815,7 @@ class CouponController extends BaseAdminController
|
|||||||
|
|
||||||
protected function getDefaultDateFormat()
|
protected function getDefaultDateFormat()
|
||||||
{
|
{
|
||||||
return LangQuery::create()->findOneByByDefault(true)->getDateFormat();
|
return LangQuery::create()->findOneByByDefault(true)->getDatetimeFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -205,7 +205,6 @@ class CurrencyController extends AbstractCrudController
|
|||||||
'undefined_rates' => $event->getUndefinedRates()
|
'undefined_rates' => $event->getUndefinedRates()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $ex) {
|
} catch (\Exception $ex) {
|
||||||
// Any error
|
// Any error
|
||||||
return $this->errorPage($ex);
|
return $this->errorPage($ex);
|
||||||
|
|||||||
@@ -435,7 +435,6 @@ class LangController extends BaseAdminController
|
|||||||
),
|
),
|
||||||
$changedObject->getId()
|
$changedObject->getId()
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Tlog::getInstance()->error(sprintf("Error on changing languages with message : %s", $e->getMessage()));
|
Tlog::getInstance()->error(sprintf("Error on changing languages with message : %s", $e->getMessage()));
|
||||||
$errorMessage = $e->getMessage();
|
$errorMessage = $e->getMessage();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use Thelia\Model\ConfigQuery;
|
|||||||
|
|
||||||
class MailingSystemController extends BaseAdminController
|
class MailingSystemController extends BaseAdminController
|
||||||
{
|
{
|
||||||
const RESOURCE_CODE = "admin.mailing-system";
|
const RESOURCE_CODE = "admin.configuration.mailing-system";
|
||||||
|
|
||||||
public function defaultAction()
|
public function defaultAction()
|
||||||
{
|
{
|
||||||
@@ -130,7 +130,7 @@ class MailingSystemController extends BaseAdminController
|
|||||||
|
|
||||||
$htmlMessage = "<p>$message</p>";
|
$htmlMessage = "<p>$message</p>";
|
||||||
|
|
||||||
$instance = \Swift_Message::newInstance()
|
$instance = $this->getMailer()->getMessageInstance()
|
||||||
->addTo($emailTest, $storeName)
|
->addTo($emailTest, $storeName)
|
||||||
->addFrom($contactEmail, $storeName)
|
->addFrom($contactEmail, $storeName)
|
||||||
->setSubject($message)
|
->setSubject($message)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use Thelia\Core\Security\AccessManager;
|
|||||||
use Thelia\Core\Security\Resource\AdminResources;
|
use Thelia\Core\Security\Resource\AdminResources;
|
||||||
use Thelia\Core\Template\TemplateDefinition;
|
use Thelia\Core\Template\TemplateDefinition;
|
||||||
use Thelia\Form\Definition\AdminForm;
|
use Thelia\Form\Definition\AdminForm;
|
||||||
|
use Thelia\Model\ConfigQuery;
|
||||||
use Thelia\Model\Message;
|
use Thelia\Model\Message;
|
||||||
use Thelia\Model\MessageQuery;
|
use Thelia\Model\MessageQuery;
|
||||||
use Thelia\Model\Module;
|
use Thelia\Model\Module;
|
||||||
@@ -48,35 +49,35 @@ class MessageController extends AbstractCrudController
|
|||||||
null // No position update
|
null // No position update
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getCreationForm()
|
protected function getCreationForm()
|
||||||
{
|
{
|
||||||
return $this->createForm(AdminForm::MESSAGE_CREATION);
|
return $this->createForm(AdminForm::MESSAGE_CREATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getUpdateForm()
|
protected function getUpdateForm()
|
||||||
{
|
{
|
||||||
return $this->createForm(AdminForm::MESSAGE_MODIFICATION);
|
return $this->createForm(AdminForm::MESSAGE_MODIFICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getCreationEvent($formData)
|
protected function getCreationEvent($formData)
|
||||||
{
|
{
|
||||||
$createEvent = new MessageCreateEvent();
|
$createEvent = new MessageCreateEvent();
|
||||||
|
|
||||||
$createEvent
|
$createEvent
|
||||||
->setMessageName($formData['name'])
|
->setMessageName($formData['name'])
|
||||||
->setLocale($formData["locale"])
|
->setLocale($formData["locale"])
|
||||||
->setTitle($formData['title'])
|
->setTitle($formData['title'])
|
||||||
->setSecured($formData['secured'] ? true : false)
|
->setSecured($formData['secured'] ? true : false)
|
||||||
;
|
;
|
||||||
|
|
||||||
return $createEvent;
|
return $createEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getUpdateEvent($formData)
|
protected function getUpdateEvent($formData)
|
||||||
{
|
{
|
||||||
$changeEvent = new MessageUpdateEvent($formData['id']);
|
$changeEvent = new MessageUpdateEvent($formData['id']);
|
||||||
|
|
||||||
// Create and dispatch the change event
|
// Create and dispatch the change event
|
||||||
$changeEvent
|
$changeEvent
|
||||||
->setMessageName($formData['name'])
|
->setMessageName($formData['name'])
|
||||||
@@ -91,20 +92,20 @@ class MessageController extends AbstractCrudController
|
|||||||
->setHtmlMessage($formData['html_message'])
|
->setHtmlMessage($formData['html_message'])
|
||||||
->setTextMessage($formData['text_message'])
|
->setTextMessage($formData['text_message'])
|
||||||
;
|
;
|
||||||
|
|
||||||
return $changeEvent;
|
return $changeEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDeleteEvent()
|
protected function getDeleteEvent()
|
||||||
{
|
{
|
||||||
return new MessageDeleteEvent($this->getRequest()->get('message_id'));
|
return new MessageDeleteEvent($this->getRequest()->get('message_id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function eventContainsObject($event)
|
protected function eventContainsObject($event)
|
||||||
{
|
{
|
||||||
return $event->hasMessage();
|
return $event->hasMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hydrateObjectForm($object)
|
protected function hydrateObjectForm($object)
|
||||||
{
|
{
|
||||||
// Prepare the data that will hydrate the form
|
// Prepare the data that will hydrate the form
|
||||||
@@ -117,34 +118,34 @@ class MessageController extends AbstractCrudController
|
|||||||
'subject' => $object->getSubject(),
|
'subject' => $object->getSubject(),
|
||||||
'html_message' => $object->getHtmlMessage(),
|
'html_message' => $object->getHtmlMessage(),
|
||||||
'text_message' => $object->getTextMessage(),
|
'text_message' => $object->getTextMessage(),
|
||||||
|
|
||||||
'html_layout_file_name' => $object->getHtmlLayoutFileName(),
|
'html_layout_file_name' => $object->getHtmlLayoutFileName(),
|
||||||
'html_template_file_name' => $object->getHtmlTemplateFileName(),
|
'html_template_file_name' => $object->getHtmlTemplateFileName(),
|
||||||
'text_layout_file_name' => $object->getTextLayoutFileName(),
|
'text_layout_file_name' => $object->getTextLayoutFileName(),
|
||||||
'text_template_file_name' => $object->getTextTemplateFileName(),
|
'text_template_file_name' => $object->getTextTemplateFileName(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Setup the object form
|
// Setup the object form
|
||||||
return $this->createForm(AdminForm::MESSAGE_MODIFICATION, "form", $data);
|
return $this->createForm(AdminForm::MESSAGE_MODIFICATION, "form", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getObjectFromEvent($event)
|
protected function getObjectFromEvent($event)
|
||||||
{
|
{
|
||||||
return $event->hasMessage() ? $event->getMessage() : null;
|
return $event->hasMessage() ? $event->getMessage() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getExistingObject()
|
protected function getExistingObject()
|
||||||
{
|
{
|
||||||
$message = MessageQuery::create()
|
$message = MessageQuery::create()
|
||||||
->findOneById($this->getRequest()->get('message_id', 0));
|
->findOneById($this->getRequest()->get('message_id', 0));
|
||||||
|
|
||||||
if (null !== $message) {
|
if (null !== $message) {
|
||||||
$message->setLocale($this->getCurrentEditionLocale());
|
$message->setLocale($this->getCurrentEditionLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Message $object
|
* @param Message $object
|
||||||
* @return string
|
* @return string
|
||||||
@@ -153,7 +154,7 @@ class MessageController extends AbstractCrudController
|
|||||||
{
|
{
|
||||||
return $object->getName();
|
return $object->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Message $object
|
* @param Message $object
|
||||||
* @return int
|
* @return int
|
||||||
@@ -162,30 +163,30 @@ class MessageController extends AbstractCrudController
|
|||||||
{
|
{
|
||||||
return $object->getId();
|
return $object->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderListTemplate($currentOrder)
|
protected function renderListTemplate($currentOrder)
|
||||||
{
|
{
|
||||||
return $this->render('messages');
|
return $this->render('messages');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function listDirectoryContent($requiredExtension)
|
protected function listDirectoryContent($requiredExtension)
|
||||||
{
|
{
|
||||||
$list = array();
|
$list = array();
|
||||||
|
|
||||||
$dir = $this->getTemplateHelper()->getActiveMailTemplate()->getAbsolutePath();
|
$dir = $this->getTemplateHelper()->getActiveMailTemplate()->getAbsolutePath();
|
||||||
|
|
||||||
$finder = Finder::create()->files()->in($dir)->ignoreDotFiles(true)->sortByName()->name("*.$requiredExtension");
|
$finder = Finder::create()->files()->in($dir)->ignoreDotFiles(true)->sortByName()->name("*.$requiredExtension");
|
||||||
|
|
||||||
foreach ($finder as $file) {
|
foreach ($finder as $file) {
|
||||||
$list[] = $file->getBasename();
|
$list[] = $file->getBasename();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add modules templates
|
// Add modules templates
|
||||||
$modules = ModuleQuery::getActivated();
|
$modules = ModuleQuery::getActivated();
|
||||||
/** @var Module $module */
|
/** @var Module $module */
|
||||||
foreach ($modules as $module) {
|
foreach ($modules as $module) {
|
||||||
$dir = $module->getAbsoluteTemplateBasePath() . DS . TemplateDefinition::EMAIL_SUBDIR . DS . 'default';
|
$dir = $module->getAbsoluteTemplateBasePath() . DS . TemplateDefinition::EMAIL_SUBDIR . DS . 'default';
|
||||||
|
|
||||||
if (file_exists($dir)) {
|
if (file_exists($dir)) {
|
||||||
$finder = Finder::create()
|
$finder = Finder::create()
|
||||||
->files()
|
->files()
|
||||||
@@ -193,7 +194,7 @@ class MessageController extends AbstractCrudController
|
|||||||
->ignoreDotFiles(true)
|
->ignoreDotFiles(true)
|
||||||
->sortByName()
|
->sortByName()
|
||||||
->name("*.$requiredExtension");
|
->name("*.$requiredExtension");
|
||||||
|
|
||||||
foreach ($finder as $file) {
|
foreach ($finder as $file) {
|
||||||
$fileName = $file->getBasename();
|
$fileName = $file->getBasename();
|
||||||
if (!in_array($fileName, $list)) {
|
if (!in_array($fileName, $list)) {
|
||||||
@@ -202,20 +203,20 @@ class MessageController extends AbstractCrudController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderEditionTemplate()
|
protected function renderEditionTemplate()
|
||||||
{
|
{
|
||||||
return $this->render('message-edit', array(
|
return $this->render('message-edit', array(
|
||||||
'message_id' => $this->getRequest()->get('message_id'),
|
'message_id' => $this->getRequest()->get('message_id'),
|
||||||
'layout_list' => $this->listDirectoryContent('tpl'),
|
'layout_list' => $this->listDirectoryContent('tpl'),
|
||||||
'html_template_list' => $this->listDirectoryContent('html'),
|
'html_template_list' => $this->listDirectoryContent('html'),
|
||||||
'text_template_list' => $this->listDirectoryContent('txt'),
|
'text_template_list' => $this->listDirectoryContent('txt'),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function redirectToEditionTemplate()
|
protected function redirectToEditionTemplate()
|
||||||
{
|
{
|
||||||
return $this->generateRedirectFromRoute(
|
return $this->generateRedirectFromRoute(
|
||||||
@@ -225,47 +226,95 @@ class MessageController extends AbstractCrudController
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function redirectToListTemplate()
|
protected function redirectToListTemplate()
|
||||||
{
|
{
|
||||||
return $this->generateRedirectFromRoute('admin.configuration.messages.default');
|
return $this->generateRedirectFromRoute('admin.configuration.messages.default');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function previewAction($messageId, $html = true)
|
public function previewAction($messageId, $html = true)
|
||||||
{
|
{
|
||||||
if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) {
|
if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $message = MessageQuery::create()->findPk($messageId)) {
|
if (null === $message = MessageQuery::create()->findPk($messageId)) {
|
||||||
$this->pageNotFound();
|
$this->pageNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
$parser = $this->getParser($this->getTemplateHelper()->getActiveMailTemplate());
|
$parser = $this->getParser($this->getTemplateHelper()->getActiveMailTemplate());
|
||||||
|
|
||||||
foreach ($this->getRequest()->query->all() as $key => $value) {
|
foreach ($this->getRequest()->query->all() as $key => $value) {
|
||||||
$parser->assign($key, $value);
|
$parser->assign($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($html) {
|
if ($html) {
|
||||||
$content = $message->setLocale($this->getCurrentEditionLocale())->getHtmlMessageBody($parser);
|
$content = $message->setLocale($this->getCurrentEditionLocale())->getHtmlMessageBody($parser);
|
||||||
} else {
|
} else {
|
||||||
$content = $message->setLocale($this->getCurrentEditionLocale())->getTextMessageBody($parser);
|
$content = $message->setLocale($this->getCurrentEditionLocale())->getTextMessageBody($parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response($content);
|
return new Response($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function previewAsHtmlAction($messageId)
|
public function previewAsHtmlAction($messageId)
|
||||||
{
|
{
|
||||||
return $this->previewAction($messageId);
|
return $this->previewAction($messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function previewAsTextAction($messageId)
|
public function previewAsTextAction($messageId)
|
||||||
{
|
{
|
||||||
$response = $this->previewAction($messageId, false);
|
$response = $this->previewAction($messageId, false);
|
||||||
$response->headers->add(["Content-Type" => "text/plain"]);
|
$response->headers->add(["Content-Type" => "text/plain"]);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sendSampleByEmailAction($messageId)
|
||||||
|
{
|
||||||
|
if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $message = MessageQuery::create()->findPk($messageId)) {
|
||||||
|
// Ajax submission: prevent CRSF control, as page is not refreshed
|
||||||
|
$baseForm = $this->createForm(AdminForm::MESSAGE_SEND_SAMPLE, 'form', [], ['csrf_protection' => false]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$form = $this->validateForm($baseForm, "POST");
|
||||||
|
|
||||||
|
$data = $form->getData();
|
||||||
|
|
||||||
|
$messageParameters = [];
|
||||||
|
|
||||||
|
foreach ($this->getRequest()->request->all() as $key => $value) {
|
||||||
|
$messageParameters[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getMailer()->sendEmailMessage(
|
||||||
|
$message->getName(),
|
||||||
|
[ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName()],
|
||||||
|
[ $data['recipient_email'] => $data['recipient_email'] ],
|
||||||
|
$messageParameters,
|
||||||
|
$this->getCurrentEditionLocale()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
$this->getTranslator()->trans(
|
||||||
|
"The message has been successfully sent to %recipient.",
|
||||||
|
[ '%recipient' => $data['recipient_email'] ]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
return new Response(
|
||||||
|
$this->getTranslator()->trans(
|
||||||
|
"Something goes wrong, the message was not sent to recipient. Error is : %err",
|
||||||
|
[ '%err' => $ex->getMessage() ]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->pageNotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class OrderController extends BaseAdminController
|
|||||||
|
|
||||||
$order = OrderQuery::create()->findPk($order_id);
|
$order = OrderQuery::create()->findPk($order_id);
|
||||||
|
|
||||||
$statusId = $this->getRequest()->request->get("status_id");
|
$statusId = $this->getRequest()->get("status_id");
|
||||||
$status = OrderStatusQuery::create()->findPk($statusId);
|
$status = OrderStatusQuery::create()->findPk($statusId);
|
||||||
|
|
||||||
if (null === $order) {
|
if (null === $order) {
|
||||||
|
|||||||
@@ -329,7 +329,6 @@ class ProductController extends AbstractSeoCrudController
|
|||||||
$this->appendValue($combinationPseData, "isdefault", $saleElement->getIsDefault() > 0 ? 1 : 0);
|
$this->appendValue($combinationPseData, "isdefault", $saleElement->getIsDefault() > 0 ? 1 : 0);
|
||||||
$this->appendValue($combinationPseData, "ean_code", $saleElement->getEanCode());
|
$this->appendValue($combinationPseData, "ean_code", $saleElement->getEanCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultPseForm = $this->createForm(AdminForm::PRODUCT_DEFAULT_SALE_ELEMENT_UPDATE, "form", $defaultPseData);
|
$defaultPseForm = $this->createForm(AdminForm::PRODUCT_DEFAULT_SALE_ELEMENT_UPDATE, "form", $defaultPseData);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class SaleController extends AbstractCrudController
|
|||||||
/** @var SaleProduct $saleProduct */
|
/** @var SaleProduct $saleProduct */
|
||||||
foreach ($saleProducts as $saleProduct) {
|
foreach ($saleProducts as $saleProduct) {
|
||||||
$categories[] = $saleProduct->getProduct()->getDefaultCategoryId();
|
$categories[] = $saleProduct->getProduct()->getDefaultCategoryId();
|
||||||
$products[] = $saleProduct->getProduct()->getId();
|
$products[$saleProduct->getProduct()->getId()] = $saleProduct->getProduct()->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = SaleModificationForm::PHP_DATE_FORMAT;
|
$dateFormat = SaleModificationForm::PHP_DATE_FORMAT;
|
||||||
|
|||||||
@@ -185,7 +185,6 @@ class SessionController extends BaseAdminController
|
|||||||
$this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, null);
|
$this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, null);
|
||||||
|
|
||||||
return $this->generateSuccessRedirect($adminCreatePasswordForm);
|
return $this->generateSuccessRedirect($adminCreatePasswordForm);
|
||||||
|
|
||||||
} catch (FormValidationException $ex) {
|
} catch (FormValidationException $ex) {
|
||||||
// Validation problem
|
// Validation problem
|
||||||
$message = $this->createStandardFormValidationErrorMessage($ex);
|
$message = $this->createStandardFormValidationErrorMessage($ex);
|
||||||
|
|||||||
@@ -241,5 +241,4 @@ class StateController extends AbstractCrudController
|
|||||||
{
|
{
|
||||||
return new StateToggleVisibilityEvent($this->getExistingObject());
|
return new StateToggleVisibilityEvent($this->getExistingObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,7 +332,6 @@ class TaxRuleController extends AbstractCrudController
|
|||||||
);
|
);
|
||||||
|
|
||||||
return $this->jsonResponse(json_encode($responseData));
|
return $this->jsonResponse(json_encode($responseData));
|
||||||
|
|
||||||
} catch (FormValidationException $ex) {
|
} catch (FormValidationException $ex) {
|
||||||
// Form cannot be validated
|
// Form cannot be validated
|
||||||
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
|
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
|
||||||
@@ -411,7 +410,6 @@ class TaxRuleController extends AbstractCrudController
|
|||||||
|
|
||||||
$taxRuleCountry = $taxRuleCountries->getNext();
|
$taxRuleCountry = $taxRuleCountries->getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ use Thelia\Core\Event\Template\TemplateCreateEvent;
|
|||||||
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
|
||||||
use Thelia\Core\Event\Template\TemplateDeleteEvent;
|
use Thelia\Core\Event\Template\TemplateDeleteEvent;
|
||||||
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
|
||||||
|
use Thelia\Core\Event\Template\TemplateDuplicateEvent;
|
||||||
use Thelia\Core\Event\Template\TemplateUpdateEvent;
|
use Thelia\Core\Event\Template\TemplateUpdateEvent;
|
||||||
use Thelia\Core\Event\TheliaEvents;
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
|
use Thelia\Core\HttpFoundation\Request;
|
||||||
use Thelia\Core\Security\AccessManager;
|
use Thelia\Core\Security\AccessManager;
|
||||||
use Thelia\Core\Security\Resource\AdminResources;
|
use Thelia\Core\Security\Resource\AdminResources;
|
||||||
use Thelia\Form\Definition\AdminForm;
|
use Thelia\Form\Definition\AdminForm;
|
||||||
@@ -157,13 +159,18 @@ class TemplateController extends AbstractCrudController
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function redirectToEditionTemplate()
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
protected function redirectToEditionTemplate($request = null, $id = null)
|
||||||
{
|
{
|
||||||
return $this->generateRedirectFromRoute(
|
return $this->generateRedirectFromRoute(
|
||||||
"admin.configuration.templates.update",
|
"admin.configuration.templates.update",
|
||||||
[
|
[
|
||||||
'template_id' => $this->getRequest()->get('template_id'),
|
'template_id' => $id ?: $this->getRequest()->get('template_id'),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -195,6 +202,33 @@ class TemplateController extends AbstractCrudController
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function duplicateAction()
|
||||||
|
{
|
||||||
|
// Check current user authorization
|
||||||
|
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::CREATE)) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$template_id = intval($this->getRequest()->get('template_id'));
|
||||||
|
|
||||||
|
if ($template_id > 0) {
|
||||||
|
try {
|
||||||
|
$event = new TemplateDuplicateEvent($template_id, $this->getCurrentEditionLocale());
|
||||||
|
|
||||||
|
$this->dispatch(TheliaEvents::TEMPLATE_DUPLICATE, $event);
|
||||||
|
|
||||||
|
if ($event->hasTemplate()) {
|
||||||
|
$template_id = $event->getTemplate()->getId();
|
||||||
|
}
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
// Any error
|
||||||
|
return $this->errorPage($ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToEditionTemplate(null, $template_id);
|
||||||
|
}
|
||||||
|
|
||||||
public function getAjaxFeaturesAction()
|
public function getAjaxFeaturesAction()
|
||||||
{
|
{
|
||||||
return $this->render(
|
return $this->render(
|
||||||
|
|||||||
@@ -126,18 +126,7 @@ class BaseFrontController extends BaseController
|
|||||||
// Add the template standard extension
|
// Add the template standard extension
|
||||||
$templateName .= '.html';
|
$templateName .= '.html';
|
||||||
|
|
||||||
$session = $this->getSession();
|
|
||||||
|
|
||||||
// Prepare common template variables
|
|
||||||
$args = array_merge($args, array(
|
|
||||||
'locale' => $session->getLang()->getLocale(),
|
|
||||||
'lang_code' => $session->getLang()->getCode(),
|
|
||||||
'lang_id' => $session->getLang()->getId(),
|
|
||||||
'current_url' => $this->getRequest()->getUri()
|
|
||||||
));
|
|
||||||
|
|
||||||
// Render the template.
|
// Render the template.
|
||||||
|
|
||||||
$data = $this->getParser($templateDir)->render($templateName, $args);
|
$data = $this->getParser($templateDir)->render($templateName, $args);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
namespace Thelia\Core\Archiver;
|
namespace Thelia\Core\Archiver;
|
||||||
|
|
||||||
|
use Thelia\Core\Translation\Translator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AbstractArchiver
|
* Class AbstractArchiver
|
||||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||||
@@ -28,10 +30,10 @@ abstract class AbstractArchiver implements ArchiverInterface
|
|||||||
*/
|
*/
|
||||||
protected $archivePath;
|
protected $archivePath;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct($checkIsAvailable = false)
|
||||||
{
|
{
|
||||||
if (!$this->isAvailable()) {
|
if ($checkIsAvailable && !$this->isAvailable()) {
|
||||||
throw new Exception(
|
throw new \Exception(
|
||||||
Translator::getInstance()->trans(
|
Translator::getInstance()->trans(
|
||||||
"The archiver :name is not available. Please install the php extension :extension first.",
|
"The archiver :name is not available. Please install the php extension :extension first.",
|
||||||
[
|
[
|
||||||
@@ -40,7 +42,7 @@ abstract class AbstractArchiver implements ArchiverInterface
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getArchivePath()
|
public function getArchivePath()
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace Thelia\Core\DependencyInjection\Compiler;
|
|||||||
use Propel\Runtime\Propel;
|
use Propel\Runtime\Propel;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Thelia\Core\Hook\BaseHook;
|
use Thelia\Core\Hook\BaseHook;
|
||||||
use Thelia\Core\Hook\HookDefinition;
|
use Thelia\Core\Hook\HookDefinition;
|
||||||
@@ -26,8 +26,8 @@ use Thelia\Model\Base\IgnoredModuleHookQuery;
|
|||||||
use Thelia\Model\ConfigQuery;
|
use Thelia\Model\ConfigQuery;
|
||||||
use Thelia\Model\Hook;
|
use Thelia\Model\Hook;
|
||||||
use Thelia\Model\HookQuery;
|
use Thelia\Model\HookQuery;
|
||||||
use Thelia\Model\ModuleHookQuery;
|
|
||||||
use Thelia\Model\ModuleHook;
|
use Thelia\Model\ModuleHook;
|
||||||
|
use Thelia\Model\ModuleHookQuery;
|
||||||
use Thelia\Model\ModuleQuery;
|
use Thelia\Model\ModuleQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,11 +61,11 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function logAlertMessage($message)
|
protected function logAlertMessage($message, $failSafe = false)
|
||||||
{
|
{
|
||||||
Tlog::getInstance()->addAlert($message);
|
Tlog::getInstance()->addAlert($message);
|
||||||
|
|
||||||
if ($this->debugEnabled) {
|
if (!$failSafe && $this->debugEnabled) {
|
||||||
throw new \InvalidArgumentException($message);
|
throw new \InvalidArgumentException($message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,6 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
$moduleHook
|
$moduleHook
|
||||||
->setHookActive(false)
|
->setHookActive(false)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//$moduleHook->setTemplates($attributes['templates']);
|
//$moduleHook->setTemplates($attributes['templates']);
|
||||||
|
|
||||||
@@ -226,6 +225,7 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
$hookId = 0;
|
$hookId = 0;
|
||||||
/** @var ModuleHook $moduleHook */
|
/** @var ModuleHook $moduleHook */
|
||||||
foreach ($moduleHooks as $moduleHook) {
|
foreach ($moduleHooks as $moduleHook) {
|
||||||
|
|
||||||
// check if class and method exists
|
// check if class and method exists
|
||||||
if (!$container->hasDefinition($moduleHook->getClassname())) {
|
if (!$container->hasDefinition($moduleHook->getClassname())) {
|
||||||
continue;
|
continue;
|
||||||
@@ -236,7 +236,8 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
if (!$this->isValidHookMethod(
|
if (!$this->isValidHookMethod(
|
||||||
$container->getDefinition($moduleHook->getClassname())->getClass(),
|
$container->getDefinition($moduleHook->getClassname())->getClass(),
|
||||||
$moduleHook->getMethod(),
|
$moduleHook->getMethod(),
|
||||||
$hook->getBlock()
|
$hook->getBlock(),
|
||||||
|
true
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
$moduleHook->delete();
|
$moduleHook->delete();
|
||||||
@@ -346,9 +347,7 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! $hook->getActivate()) {
|
if (! $hook->getActivate()) {
|
||||||
$this->logAlertMessage(sprintf("Hook %s is not activated.", $hookName));
|
$this->logAlertMessage(sprintf("Hook %s is not activated.", $hookName), true);
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $hook;
|
return $hook;
|
||||||
@@ -360,10 +359,11 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
* @param string $className the namespace of the class
|
* @param string $className the namespace of the class
|
||||||
* @param string $methodName the method name
|
* @param string $methodName the method name
|
||||||
* @param bool $block tell if the hook is a block or a function
|
* @param bool $block tell if the hook is a block or a function
|
||||||
|
* @param bool $failSafe
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function isValidHookMethod($className, $methodName, $block)
|
protected function isValidHookMethod($className, $methodName, $block, $failSafe = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$method = new ReflectionMethod($className, $methodName);
|
$method = new ReflectionMethod($className, $methodName);
|
||||||
@@ -380,7 +380,10 @@ class RegisterHookListenersPass implements CompilerPassInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (ReflectionException $ex) {
|
} catch (ReflectionException $ex) {
|
||||||
$this->logAlertMessage(sprintf("Method %s does not exist in %s : %s", $methodName, $className, $ex));
|
$this->logAlertMessage(
|
||||||
|
sprintf("Method %s does not exist in %s : %s", $methodName, $className, $ex),
|
||||||
|
$failSafe
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
use Thelia\Model\Module;
|
||||||
|
use Thelia\Model\ModuleQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -52,8 +54,9 @@ class RegisterRouterPass implements CompilerPassInterface
|
|||||||
$chainRouter->addMethodCall("add", array(new Reference($id), $priority));
|
$chainRouter->addMethodCall("add", array(new Reference($id), $priority));
|
||||||
}
|
}
|
||||||
if (defined("THELIA_INSTALL_MODE") === false) {
|
if (defined("THELIA_INSTALL_MODE") === false) {
|
||||||
$modules = \Thelia\Model\ModuleQuery::getActivated();
|
$modules = ModuleQuery::getActivated();
|
||||||
|
|
||||||
|
/** @var Module $module */
|
||||||
foreach ($modules as $module) {
|
foreach ($modules as $module) {
|
||||||
$moduleBaseDir = $module->getBaseDir();
|
$moduleBaseDir = $module->getBaseDir();
|
||||||
$routingConfigFilePath = $module->getAbsoluteBaseDir() . DS . "Config" . DS . "routing.xml";
|
$routingConfigFilePath = $module->getAbsoluteBaseDir() . DS . "Config" . DS . "routing.xml";
|
||||||
@@ -76,7 +79,7 @@ class RegisterRouterPass implements CompilerPassInterface
|
|||||||
|
|
||||||
$container->setDefinition("router.".$moduleBaseDir, $definition);
|
$container->setDefinition("router.".$moduleBaseDir, $definition);
|
||||||
|
|
||||||
$chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150));
|
$chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150 + $module->getPosition()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class CartDuplicationEvent extends CartEvent
|
|||||||
*/
|
*/
|
||||||
public function getDuplicatedCart()
|
public function getDuplicatedCart()
|
||||||
{
|
{
|
||||||
return parent::getCart();
|
return $this->getCart();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Event\Country;
|
|||||||
*/
|
*/
|
||||||
class CountryToggleVisibilityEvent extends CountryEvent
|
class CountryToggleVisibilityEvent extends CountryEvent
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,4 @@ class ModuleHookCreateEvent extends ModuleHookEvent
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,36 +10,57 @@
|
|||||||
/* file that was distributed with this source code. */
|
/* file that was distributed with this source code. */
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
namespace Thelia\Core\Event\Loop;
|
namespace Thelia\Core\Event\Loop;
|
||||||
|
|
||||||
use Thelia\Core\Template\Element\BaseLoop;
|
use Thelia\Core\Template\Element\BaseLoop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LoopExtendsBuildArrayEvent
|
* Class LoopExtendsBuildArrayEvent
|
||||||
|
*
|
||||||
* @package Thelia\Core\Event\Loop
|
* @package Thelia\Core\Event\Loop
|
||||||
* @author Julien Chanséaume <julien@thelia.net>
|
* @author Julien Chanséaume <julien@thelia.net>
|
||||||
*/
|
*/
|
||||||
class LoopExtendsBuildArrayEvent extends LoopExtendsEvent
|
class LoopExtendsBuildArrayEvent extends LoopExtendsEvent
|
||||||
{
|
{
|
||||||
/** @var array $array */
|
/**
|
||||||
|
* @var array Build array results
|
||||||
|
*/
|
||||||
protected $array;
|
protected $array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoopExtendsBuildArrayEvent constructor.
|
* Class constructor
|
||||||
* @param array $array
|
*
|
||||||
|
* @param \Thelia\Core\Template\Element\BaseLoop $loop Loop object
|
||||||
|
* @param array $array Build array base results
|
||||||
*/
|
*/
|
||||||
public function __construct(BaseLoop $loop, array $array)
|
public function __construct(BaseLoop $loop, array $array)
|
||||||
{
|
{
|
||||||
parent::__construct($loop);
|
parent::__construct($loop);
|
||||||
|
|
||||||
$this->array = $array;
|
$this->array = $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* Get build array results
|
||||||
|
*
|
||||||
|
* @return array Build array results
|
||||||
*/
|
*/
|
||||||
public function getArray()
|
public function getArray()
|
||||||
{
|
{
|
||||||
return $this->array;
|
return $this->array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set build array results
|
||||||
|
*
|
||||||
|
* @param array $array
|
||||||
|
*
|
||||||
|
* @return $this Return $this, allow chaining
|
||||||
|
*/
|
||||||
|
public function setArray(array $array)
|
||||||
|
{
|
||||||
|
$this->array = $array;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,28 @@ class ModuleDeleteEvent extends ModuleEvent
|
|||||||
protected $module_id;
|
protected $module_id;
|
||||||
protected $delete_data;
|
protected $delete_data;
|
||||||
|
|
||||||
public function __construct($module_id)
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $assume_delete;
|
||||||
|
|
||||||
|
public function __construct($module_id, $assume_delete = false)
|
||||||
{
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
$this->module_id = $module_id;
|
$this->module_id = $module_id;
|
||||||
|
$this->assume_delete = $assume_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $module_id
|
* @param int $module_id
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setModuleId($module_id)
|
public function setModuleId($module_id)
|
||||||
{
|
{
|
||||||
$this->module_id = $module_id;
|
$this->module_id = $module_id;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,10 +62,33 @@ class ModuleDeleteEvent extends ModuleEvent
|
|||||||
return $this->delete_data;
|
return $this->delete_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $delete_data
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setDeleteData($delete_data)
|
public function setDeleteData($delete_data)
|
||||||
{
|
{
|
||||||
$this->delete_data = $delete_data;
|
$this->delete_data = $delete_data;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getAssumeDelete()
|
||||||
|
{
|
||||||
|
return $this->assume_delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $assume_delete
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAssumeDelete($assume_delete)
|
||||||
|
{
|
||||||
|
$this->assume_delete = $assume_delete;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,13 +34,21 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
|||||||
*/
|
*/
|
||||||
protected $recursive;
|
protected $recursive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $assume_deactivate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $module_id
|
* @param int $module_id
|
||||||
*/
|
*/
|
||||||
public function __construct($module_id)
|
public function __construct($module_id, $assume_deactivate = false)
|
||||||
{
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
$this->module_id = $module_id;
|
$this->module_id = $module_id;
|
||||||
|
$this->assume_deactivate = $assume_deactivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +81,7 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boolean $noCheck
|
* @param boolean $noCheck
|
||||||
* @return $this;
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setNoCheck($noCheck)
|
public function setNoCheck($noCheck)
|
||||||
{
|
{
|
||||||
@@ -92,11 +100,29 @@ class ModuleToggleActivationEvent extends ModuleEvent
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boolean $recursive
|
* @param boolean $recursive
|
||||||
* @return $this;
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setRecursive($recursive)
|
public function setRecursive($recursive)
|
||||||
{
|
{
|
||||||
$this->recursive = $recursive;
|
$this->recursive = $recursive;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getAssumeDeactivate()
|
||||||
|
{
|
||||||
|
return $this->assume_deactivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $assume_deactivate
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAssumeDeactivate($assume_deactivate)
|
||||||
|
{
|
||||||
|
$this->assume_deactivate = $assume_deactivate;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ class OrderEvent extends ActionEvent
|
|||||||
/** @var null|int */
|
/** @var null|int */
|
||||||
protected $cartItemId = null;
|
protected $cartItemId = null;
|
||||||
|
|
||||||
|
/** @var null|string */
|
||||||
|
protected $transactionRef = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Response
|
* @var Response
|
||||||
*/
|
*/
|
||||||
@@ -352,4 +355,24 @@ class OrderEvent extends ActionEvent
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.4.0
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
public function getTransactionRef()
|
||||||
|
{
|
||||||
|
return $this->transactionRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.4.0
|
||||||
|
* @param null|string $transactionRef
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTransactionRef($transactionRef)
|
||||||
|
{
|
||||||
|
$this->transactionRef = $transactionRef;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,23 @@ use Thelia\Model\Product;
|
|||||||
|
|
||||||
class ProductCloneEvent extends ActionEvent
|
class ProductCloneEvent extends ActionEvent
|
||||||
{
|
{
|
||||||
|
/** @var string */
|
||||||
protected $ref;
|
protected $ref;
|
||||||
|
/** @var string */
|
||||||
protected $lang;
|
protected $lang;
|
||||||
protected $originalProduct = array();
|
/** @var Product */
|
||||||
protected $clonedProduct = array();
|
protected $originalProduct;
|
||||||
|
/** @var Product */
|
||||||
|
protected $clonedProduct;
|
||||||
|
/** @var array */
|
||||||
protected $types = array('images', 'documents');
|
protected $types = array('images', 'documents');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProductCloneEvent constructor.
|
||||||
|
* @param string $ref
|
||||||
|
* @param string $lang the locale (such as fr_FR)
|
||||||
|
* @param $originalProduct
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
$ref,
|
$ref,
|
||||||
$lang,
|
$lang,
|
||||||
@@ -34,7 +45,7 @@ class ProductCloneEvent extends ActionEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getRef()
|
public function getRef()
|
||||||
{
|
{
|
||||||
@@ -42,7 +53,7 @@ class ProductCloneEvent extends ActionEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $ref
|
* @param string $ref
|
||||||
*/
|
*/
|
||||||
public function setRef($ref)
|
public function setRef($ref)
|
||||||
{
|
{
|
||||||
@@ -50,7 +61,7 @@ class ProductCloneEvent extends ActionEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return string the locale (such as fr_FR)
|
||||||
*/
|
*/
|
||||||
public function getLang()
|
public function getLang()
|
||||||
{
|
{
|
||||||
@@ -58,7 +69,7 @@ class ProductCloneEvent extends ActionEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $lang
|
* @param string $lang the locale (such as fr_FR)
|
||||||
*/
|
*/
|
||||||
public function setLang($lang)
|
public function setLang($lang)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,34 +14,55 @@ namespace Thelia\Core\Event\ProductSaleElement;
|
|||||||
|
|
||||||
class ProductSaleElementDeleteEvent extends ProductSaleElementEvent
|
class ProductSaleElementDeleteEvent extends ProductSaleElementEvent
|
||||||
{
|
{
|
||||||
|
/** @var int */
|
||||||
protected $product_sale_element_id;
|
protected $product_sale_element_id;
|
||||||
|
/** @var int */
|
||||||
protected $currency_id;
|
protected $currency_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProductSaleElementDeleteEvent constructor.
|
||||||
|
* @param int $product_sale_element_id
|
||||||
|
* @param int $currency_id
|
||||||
|
*/
|
||||||
public function __construct($product_sale_element_id, $currency_id)
|
public function __construct($product_sale_element_id, $currency_id)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->product_sale_element_id = $product_sale_element_id;
|
$this->product_sale_element_id = $product_sale_element_id;
|
||||||
$this->setCurrencyId($currency_id);
|
$this->currency_id = $currency_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getProductSaleElementId()
|
public function getProductSaleElementId()
|
||||||
{
|
{
|
||||||
return $this->product_sale_element_id;
|
return $this->product_sale_element_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $product_sale_element_id
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setProductSaleElementId($product_sale_element_id)
|
public function setProductSaleElementId($product_sale_element_id)
|
||||||
{
|
{
|
||||||
$this->product_sale_element_id = $product_sale_element_id;
|
$this->product_sale_element_id = $product_sale_element_id;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getCurrencyId()
|
public function getCurrencyId()
|
||||||
{
|
{
|
||||||
return $this->currency_id;
|
return $this->currency_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $currency_id
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setCurrencyId($currency_id)
|
public function setCurrencyId($currency_id)
|
||||||
{
|
{
|
||||||
$this->currency_id = $currency_id;
|
$this->currency_id = $currency_id;
|
||||||
|
|||||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Event\State;
|
|||||||
*/
|
*/
|
||||||
class StateToggleVisibilityEvent extends StateEvent
|
class StateToggleVisibilityEvent extends StateEvent
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,36 @@ use Thelia\Model\Template;
|
|||||||
|
|
||||||
class TemplateEvent extends ActionEvent
|
class TemplateEvent extends ActionEvent
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Template
|
||||||
|
*/
|
||||||
protected $template = null;
|
protected $template = null;
|
||||||
|
|
||||||
public function __construct(Template $template = null)
|
public function __construct(Template $template = null)
|
||||||
{
|
{
|
||||||
$this->template = $template;
|
$this->template = $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function hasTemplate()
|
public function hasTemplate()
|
||||||
{
|
{
|
||||||
return ! is_null($this->template);
|
return ! is_null($this->template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Template
|
||||||
|
*/
|
||||||
public function getTemplate()
|
public function getTemplate()
|
||||||
{
|
{
|
||||||
return $this->template;
|
return $this->template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Template $template
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setTemplate($template)
|
public function setTemplate($template)
|
||||||
{
|
{
|
||||||
$this->template = $template;
|
$this->template = $template;
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ final class TheliaEvents
|
|||||||
* sent at the beginning
|
* sent at the beginning
|
||||||
*/
|
*/
|
||||||
const BOOT = "thelia.boot";
|
const BOOT = "thelia.boot";
|
||||||
|
/**
|
||||||
|
* Kernel View Check Handle
|
||||||
|
*/
|
||||||
|
const VIEW_CHECK = "thelia.view_check";
|
||||||
// -- END CORE EVENTS ---------------------------------------------------------
|
// -- END CORE EVENTS ---------------------------------------------------------
|
||||||
// -- ADDRESS EVENTS ---------------------------------------------------------
|
// -- ADDRESS EVENTS ---------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
@@ -115,6 +119,8 @@ final class TheliaEvents
|
|||||||
const CATEGORY_REMOVE_CONTENT = "action.categoryRemoveContent";
|
const CATEGORY_REMOVE_CONTENT = "action.categoryRemoveContent";
|
||||||
|
|
||||||
const CATEGORY_UPDATE_SEO = "action.updateCategorySeo";
|
const CATEGORY_UPDATE_SEO = "action.updateCategorySeo";
|
||||||
|
|
||||||
|
const VIEW_CATEGORY_ID_NOT_VISIBLE = "action.viewCategoryIdNotVisible";
|
||||||
// -- END CATEGORIES EVENTS -----------------------------------------------
|
// -- END CATEGORIES EVENTS -----------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -137,6 +143,8 @@ final class TheliaEvents
|
|||||||
|
|
||||||
const CONTENT_ADD_FOLDER = "action.contentAddFolder";
|
const CONTENT_ADD_FOLDER = "action.contentAddFolder";
|
||||||
const CONTENT_REMOVE_FOLDER = "action.contentRemoveFolder";
|
const CONTENT_REMOVE_FOLDER = "action.contentRemoveFolder";
|
||||||
|
|
||||||
|
const VIEW_CONTENT_ID_NOT_VISIBLE = "action.viewContentIdNotVisible";
|
||||||
// -- END CONTENT EVENTS ---------------------------------------------------------
|
// -- END CONTENT EVENTS ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -234,6 +242,12 @@ final class TheliaEvents
|
|||||||
* sent when a customer need a new password
|
* sent when a customer need a new password
|
||||||
*/
|
*/
|
||||||
const LOST_PASSWORD = "action.lostPassword";
|
const LOST_PASSWORD = "action.lostPassword";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the account ccreation confirmation email
|
||||||
|
*/
|
||||||
|
const SEND_ACCOUNT_CONFIRMATION_EMAIL = "action.customer.sendAccountConfirmationEmail";
|
||||||
|
|
||||||
// -- END CUSTOMER EVENTS ---------------------------------------------------------
|
// -- END CUSTOMER EVENTS ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -253,6 +267,8 @@ final class TheliaEvents
|
|||||||
const FOLDER_TOGGLE_VISIBILITY = "action.toggleFolderVisibility";
|
const FOLDER_TOGGLE_VISIBILITY = "action.toggleFolderVisibility";
|
||||||
const FOLDER_UPDATE_POSITION = "action.updateFolderPosition";
|
const FOLDER_UPDATE_POSITION = "action.updateFolderPosition";
|
||||||
const FOLDER_UPDATE_SEO = "action.updateFolderSeo";
|
const FOLDER_UPDATE_SEO = "action.updateFolderSeo";
|
||||||
|
|
||||||
|
const VIEW_FOLDER_ID_NOT_VISIBLE = "action.viewFolderIdNotVisible";
|
||||||
// -- END FOLDER EVENTS ---------------------------------------------------------
|
// -- END FOLDER EVENTS ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -299,6 +315,7 @@ final class TheliaEvents
|
|||||||
const VIRTUAL_PRODUCT_ORDER_HANDLE = "action.virtualProduct.handleOrder";
|
const VIRTUAL_PRODUCT_ORDER_HANDLE = "action.virtualProduct.handleOrder";
|
||||||
const VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE = "action.virtualProduct.downloadResponse";
|
const VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE = "action.virtualProduct.downloadResponse";
|
||||||
|
|
||||||
|
const VIEW_PRODUCT_ID_NOT_VISIBLE = "action.viewProductIdNotVisible";
|
||||||
// -- END PRODUCT EVENTS ---------------------------------------------------------
|
// -- END PRODUCT EVENTS ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -437,6 +454,7 @@ final class TheliaEvents
|
|||||||
const ORDER_SEND_NOTIFICATION_EMAIL = "action.order.sendOrderNotificationEmail";
|
const ORDER_SEND_NOTIFICATION_EMAIL = "action.order.sendOrderNotificationEmail";
|
||||||
|
|
||||||
const ORDER_UPDATE_DELIVERY_REF = "action.order.updateDeliveryRef";
|
const ORDER_UPDATE_DELIVERY_REF = "action.order.updateDeliveryRef";
|
||||||
|
const ORDER_UPDATE_TRANSACTION_REF = "action.order.updateTransactionRef";
|
||||||
const ORDER_UPDATE_ADDRESS = "action.order.updateAddress";
|
const ORDER_UPDATE_ADDRESS = "action.order.updateAddress";
|
||||||
|
|
||||||
const ORDER_PRODUCT_BEFORE_CREATE = "action.orderProduct.beforeCreate";
|
const ORDER_PRODUCT_BEFORE_CREATE = "action.orderProduct.beforeCreate";
|
||||||
@@ -694,6 +712,7 @@ final class TheliaEvents
|
|||||||
const TEMPLATE_CREATE = "action.createTemplate";
|
const TEMPLATE_CREATE = "action.createTemplate";
|
||||||
const TEMPLATE_UPDATE = "action.updateTemplate";
|
const TEMPLATE_UPDATE = "action.updateTemplate";
|
||||||
const TEMPLATE_DELETE = "action.deleteTemplate";
|
const TEMPLATE_DELETE = "action.deleteTemplate";
|
||||||
|
const TEMPLATE_DUPLICATE = "action.duplicateTemplate";
|
||||||
|
|
||||||
const TEMPLATE_ADD_ATTRIBUTE = "action.templateAddAttribute";
|
const TEMPLATE_ADD_ATTRIBUTE = "action.templateAddAttribute";
|
||||||
const TEMPLATE_DELETE_ATTRIBUTE = "action.templateDeleteAttribute";
|
const TEMPLATE_DELETE_ATTRIBUTE = "action.templateDeleteAttribute";
|
||||||
@@ -912,6 +931,8 @@ final class TheliaEvents
|
|||||||
const BEFORE_UPDATEBRAND = "action.before_updateBrand";
|
const BEFORE_UPDATEBRAND = "action.before_updateBrand";
|
||||||
const AFTER_UPDATEBRAND = "action.after_updateBrand";
|
const AFTER_UPDATEBRAND = "action.after_updateBrand";
|
||||||
|
|
||||||
|
const VIEW_BRAND_ID_NOT_VISIBLE = "action.viewBrandIdNotVisible";
|
||||||
|
|
||||||
// -- Import ----------------------------------------------
|
// -- Import ----------------------------------------------
|
||||||
|
|
||||||
const IMPORT_CHANGE_POSITION = 'import.change.position';
|
const IMPORT_CHANGE_POSITION = 'import.change.position';
|
||||||
@@ -980,4 +1001,20 @@ final class TheliaEvents
|
|||||||
|
|
||||||
const TRANSLATION_GET_STRINGS = 'action.translation.get_strings';
|
const TRANSLATION_GET_STRINGS = 'action.translation.get_strings';
|
||||||
const TRANSLATION_WRITE_FILE = 'action.translation.write_file';
|
const TRANSLATION_WRITE_FILE = 'action.translation.write_file';
|
||||||
|
|
||||||
|
// -- ORDER STATUS EVENTS -----------------------------------------------
|
||||||
|
const BEFORE_CREATE_ORDER_STATUS = "action.before_createOrderStatus";
|
||||||
|
const ORDER_STATUS_CREATE = "action.createOrderStatus";
|
||||||
|
const AFTER_CREATE_ORDER_STATUS = "action.after_createOrderStatus";
|
||||||
|
|
||||||
|
const BEFORE_UPDATE_ORDER_STATUS = "action.before_updateOrderStatus";
|
||||||
|
const ORDER_STATUS_UPDATE = "action.updateOrderStatus";
|
||||||
|
const AFTER_UPDATE_ORDER_STATUS = "action.after_updateOrderStatus";
|
||||||
|
|
||||||
|
const BEFORE_DELETE_ORDER_STATUS = "action.before_deleteOrderStatus";
|
||||||
|
const ORDER_STATUS_DELETE = "action.deleteOrderStatus";
|
||||||
|
const AFTER_DELETE_ORDER_STATUS = "action.after_deleteOrderStatus";
|
||||||
|
|
||||||
|
const ORDER_STATUS_UPDATE_POSITION = "action.updateOrderStatusPosition";
|
||||||
|
// -- END ORDER STATUS EVENTS -----------------------------------------------
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use Thelia\Core\Security\Exception\AuthenticationException;
|
|||||||
use Thelia\Core\Security\SecurityContext;
|
use Thelia\Core\Security\SecurityContext;
|
||||||
use Thelia\Core\Template\ParserInterface;
|
use Thelia\Core\Template\ParserInterface;
|
||||||
use Thelia\Core\TheliaKernelEvents;
|
use Thelia\Core\TheliaKernelEvents;
|
||||||
|
use Thelia\Log\Tlog;
|
||||||
use Thelia\Model\ConfigQuery;
|
use Thelia\Model\ConfigQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,6 +90,25 @@ class ErrorListener implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function logException(GetResponseForExceptionEvent $event)
|
||||||
|
{
|
||||||
|
// Log exception in the Thelia log
|
||||||
|
$exception = $event->getException();
|
||||||
|
|
||||||
|
$logMessage = '';
|
||||||
|
|
||||||
|
do {
|
||||||
|
$logMessage .=
|
||||||
|
($logMessage ? PHP_EOL . 'Caused by' : 'Uncaught exception')
|
||||||
|
. $event->getException()->getMessage()
|
||||||
|
. PHP_EOL
|
||||||
|
. "Stack Trace: " . $event->getException()->getTraceAsString()
|
||||||
|
;
|
||||||
|
} while (null !== $exception = $exception->getPrevious());
|
||||||
|
|
||||||
|
Tlog::getInstance()->error($logMessage);
|
||||||
|
}
|
||||||
|
|
||||||
public function authenticationException(GetResponseForExceptionEvent $event)
|
public function authenticationException(GetResponseForExceptionEvent $event)
|
||||||
{
|
{
|
||||||
$exception = $event->getException();
|
$exception = $event->getException();
|
||||||
@@ -107,6 +127,7 @@ class ErrorListener implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
KernelEvents::EXCEPTION => [
|
KernelEvents::EXCEPTION => [
|
||||||
|
["logException", 0],
|
||||||
["handleException", 0],
|
["handleException", 0],
|
||||||
['authenticationException', 100]
|
['authenticationException', 100]
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -275,9 +275,11 @@ class RequestListener implements EventSubscriberInterface
|
|||||||
) {
|
) {
|
||||||
$request->getSession()->setCurrency($find);
|
$request->getSession()->setCurrency($find);
|
||||||
$this->eventDispatcher->dispatch(TheliaEvents::CHANGE_DEFAULT_CURRENCY, new CurrencyChangeEvent($find, $request));
|
$this->eventDispatcher->dispatch(TheliaEvents::CHANGE_DEFAULT_CURRENCY, new CurrencyChangeEvent($find, $request));
|
||||||
|
} else {
|
||||||
|
$defaultCurrency = Currency::getDefaultCurrency();
|
||||||
|
$request->getSession()->setCurrency($defaultCurrency);
|
||||||
|
$this->eventDispatcher->dispatch(TheliaEvents::CHANGE_DEFAULT_CURRENCY, new CurrencyChangeEvent($defaultCurrency, $request));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$request->getSession()->setCurrency(Currency::getDefaultCurrency());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ class ResponseListener implements EventSubscriberInterface
|
|||||||
$session = $event->getRequest()->getSession();
|
$session = $event->getRequest()->getSession();
|
||||||
|
|
||||||
if (null !== $id = $session->get("cart_use_cookie")) {
|
if (null !== $id = $session->get("cart_use_cookie")) {
|
||||||
|
|
||||||
$response = $event->getResponse();
|
$response = $event->getResponse();
|
||||||
$cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart');
|
$cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart');
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
namespace Thelia\Core\EventListener;
|
namespace Thelia\Core\EventListener;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@@ -20,6 +21,8 @@ use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
|
|||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Symfony\Component\HttpKernel\KernelEvents;
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
use Symfony\Component\Routing\Router;
|
use Symfony\Component\Routing\Router;
|
||||||
|
use Thelia\Core\Event\TheliaEvents;
|
||||||
|
use Thelia\Core\Event\ViewCheckEvent;
|
||||||
use Thelia\Core\HttpFoundation\Response;
|
use Thelia\Core\HttpFoundation\Response;
|
||||||
use Thelia\Core\Template\Exception\ResourceNotFoundException;
|
use Thelia\Core\Template\Exception\ResourceNotFoundException;
|
||||||
use Thelia\Exception\OrderException;
|
use Thelia\Exception\OrderException;
|
||||||
@@ -35,23 +38,23 @@ use Thelia\Exception\OrderException;
|
|||||||
|
|
||||||
class ViewListener implements EventSubscriberInterface
|
class ViewListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
/**
|
/** @var ContainerInterface */
|
||||||
*
|
|
||||||
* @var \Symfony\Component\DependencyInjection\ContainerInterface
|
|
||||||
*/
|
|
||||||
private $container;
|
private $container;
|
||||||
|
|
||||||
|
/** @var EventDispatcherInterface */
|
||||||
|
protected $eventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param ContainerInterface $container
|
* @param ContainerInterface $container
|
||||||
|
* @param EventDispatcherInterface $eventDispatcher
|
||||||
*/
|
*/
|
||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container, EventDispatcherInterface $eventDispatcher)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Launch the parser defined on the constructor and get the result.
|
* Launch the parser defined on the constructor and get the result.
|
||||||
*
|
*
|
||||||
* The result is transform id needed into a Response object
|
* The result is transform id needed into a Response object
|
||||||
@@ -66,7 +69,13 @@ class ViewListener implements EventSubscriberInterface
|
|||||||
$request = $this->container->get('request_stack')->getCurrentRequest();
|
$request = $this->container->get('request_stack')->getCurrentRequest();
|
||||||
$response = null;
|
$response = null;
|
||||||
try {
|
try {
|
||||||
$content = $parser->render($request->attributes->get('_view').".html");
|
$view = $request->attributes->get('_view');
|
||||||
|
|
||||||
|
$viewId = $request->attributes->get($view . '_id');
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(TheliaEvents::VIEW_CHECK, new ViewCheckEvent($view, $viewId));
|
||||||
|
|
||||||
|
$content = $parser->render($view . '.html');
|
||||||
|
|
||||||
if ($content instanceof Response) {
|
if ($content instanceof Response) {
|
||||||
$response = $content;
|
$response = $content;
|
||||||
@@ -98,15 +107,19 @@ class ViewListener implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
$request = $this->container->get('request_stack')->getCurrentRequest();
|
$request = $this->container->get('request_stack')->getCurrentRequest();
|
||||||
|
|
||||||
if (null === $request->attributes->get('_view')) {
|
if (null === $view = $request->attributes->get('_view')) {
|
||||||
$request->attributes->set('_view', $this->findView($request));
|
$request->attributes->set('_view', $this->findView($request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $request->attributes->get($view . '_id')) {
|
||||||
|
$request->attributes->set($view . '_id', $this->findViewId($request, $view));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findView(Request $request)
|
public function findView(Request $request)
|
||||||
{
|
{
|
||||||
if (! $view = $request->query->get('view')) {
|
if (! $view = $request->query->get('view')) {
|
||||||
$view = "index";
|
$view = 'index';
|
||||||
if ($request->request->has('view')) {
|
if ($request->request->has('view')) {
|
||||||
$view = $request->request->get('view');
|
$view = $request->request->get('view');
|
||||||
}
|
}
|
||||||
@@ -115,6 +128,17 @@ class ViewListener implements EventSubscriberInterface
|
|||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findViewId(Request $request, $view)
|
||||||
|
{
|
||||||
|
if (! $viewId = $request->query->get($view . '_id')) {
|
||||||
|
$viewId = 0;
|
||||||
|
if ($request->request->has($view . '_id')) {
|
||||||
|
$viewId = $request->request->get($view . '_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $viewId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
|||||||
@@ -20,5 +20,4 @@ namespace Thelia\Core\Hook;
|
|||||||
*/
|
*/
|
||||||
class DefaultHook extends BaseHook
|
class DefaultHook extends BaseHook
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace Thelia\Core\Routing;
|
namespace Thelia\Core\Routing;
|
||||||
|
|
||||||
|
use Propel\Runtime\ActiveQuery\Criteria;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Exception\InvalidParameterException;
|
use Symfony\Component\Routing\Exception\InvalidParameterException;
|
||||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||||
@@ -26,7 +27,10 @@ use Thelia\Core\HttpFoundation\Request as TheliaRequest;
|
|||||||
use Thelia\Core\HttpKernel\Exception\RedirectException;
|
use Thelia\Core\HttpKernel\Exception\RedirectException;
|
||||||
use Thelia\Exception\UrlRewritingException;
|
use Thelia\Exception\UrlRewritingException;
|
||||||
use Thelia\Model\ConfigQuery;
|
use Thelia\Model\ConfigQuery;
|
||||||
|
use Thelia\Model\CustomerQuery;
|
||||||
|
use Thelia\Model\Lang;
|
||||||
use Thelia\Model\LangQuery;
|
use Thelia\Model\LangQuery;
|
||||||
|
use Thelia\Model\RewritingUrlQuery;
|
||||||
use Thelia\Rewriting\RewritingResolver;
|
use Thelia\Rewriting\RewritingResolver;
|
||||||
use Thelia\Tools\URL;
|
use Thelia\Tools\URL;
|
||||||
|
|
||||||
@@ -177,6 +181,11 @@ class RewritingRouter implements RouterInterface, RequestMatcherInterface
|
|||||||
if (null ==! $requestedLocale = $request->get('lang')) {
|
if (null ==! $requestedLocale = $request->get('lang')) {
|
||||||
if (null !== $requestedLang = LangQuery::create()->findOneByLocale($requestedLocale)) {
|
if (null !== $requestedLang = LangQuery::create()->findOneByLocale($requestedLocale)) {
|
||||||
if ($requestedLang->getLocale() != $rewrittenUrlData->locale) {
|
if ($requestedLang->getLocale() != $rewrittenUrlData->locale) {
|
||||||
|
// Save one redirection if requested locale is disabled.
|
||||||
|
if (! $requestedLang->getActive()) {
|
||||||
|
$requestedLang = Lang::getDefaultLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
$localizedUrl = $urlTool->retrieve(
|
$localizedUrl = $urlTool->retrieve(
|
||||||
$rewrittenUrlData->view,
|
$rewrittenUrlData->view,
|
||||||
$rewrittenUrlData->viewId,
|
$rewrittenUrlData->viewId,
|
||||||
@@ -188,9 +197,33 @@ class RewritingRouter implements RouterInterface, RequestMatcherInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the rewritten URL locale is disabled, redirect to the URL in the default language
|
||||||
|
if (null === $lang = LangQuery::create()
|
||||||
|
->filterByActive(true)
|
||||||
|
->filterByLocale($rewrittenUrlData->locale)
|
||||||
|
->findOne()) {
|
||||||
|
$lang = Lang::getDefaultLanguage();
|
||||||
|
|
||||||
|
$localizedUrl = $urlTool->retrieve(
|
||||||
|
$rewrittenUrlData->view,
|
||||||
|
$rewrittenUrlData->viewId,
|
||||||
|
$lang->getLocale()
|
||||||
|
)->toString();
|
||||||
|
|
||||||
|
$this->redirect($urlTool->absoluteUrl($localizedUrl), 301);
|
||||||
|
}
|
||||||
|
|
||||||
/* is the URL redirected ? */
|
/* is the URL redirected ? */
|
||||||
if (null !== $rewrittenUrlData->redirectedToUrl) {
|
if (null !== $rewrittenUrlData->redirectedToUrl) {
|
||||||
$this->redirect($urlTool->absoluteUrl($rewrittenUrlData->redirectedToUrl), 301);
|
$redirect = RewritingUrlQuery::create()
|
||||||
|
->filterByView($rewrittenUrlData->view)
|
||||||
|
->filterByViewId($rewrittenUrlData->viewId)
|
||||||
|
->filterByViewLocale($rewrittenUrlData->locale)
|
||||||
|
->filterByRedirected(null, Criteria::ISNULL)
|
||||||
|
->findOne()
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->redirect($urlTool->absoluteUrl($redirect->getUrl()), 301);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* define GET arguments in request */
|
/* define GET arguments in request */
|
||||||
|
|||||||
@@ -13,11 +13,14 @@
|
|||||||
namespace Thelia\Core\Security\Authentication;
|
namespace Thelia\Core\Security\Authentication;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Thelia\Core\Security\Exception\CustomerNotConfirmedException;
|
||||||
use Thelia\Core\Security\UserProvider\UserProviderInterface;
|
use Thelia\Core\Security\UserProvider\UserProviderInterface;
|
||||||
use Thelia\Core\Security\Exception\WrongPasswordException;
|
use Thelia\Core\Security\Exception\WrongPasswordException;
|
||||||
use Thelia\Core\Security\Exception\UsernameNotFoundException;
|
use Thelia\Core\Security\Exception\UsernameNotFoundException;
|
||||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||||
use Thelia\Form\BaseForm;
|
use Thelia\Form\BaseForm;
|
||||||
|
use Thelia\Model\ConfigQuery;
|
||||||
|
use Thelia\Model\Customer;
|
||||||
|
|
||||||
class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
|
class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
|
||||||
{
|
{
|
||||||
@@ -78,6 +81,14 @@ class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
|
|||||||
if ($authOk !== true) {
|
if ($authOk !== true) {
|
||||||
throw new WrongPasswordException(sprintf("Wrong password for user '%s'.", $username));
|
throw new WrongPasswordException(sprintf("Wrong password for user '%s'.", $username));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigQuery::isCustomerEmailConfirmationEnable() && $user instanceof Customer) {
|
||||||
|
// Customer email confirmation feature is available since Thelia 2.3.4
|
||||||
|
if ($user->getConfirmationToken() !== null && ! $user->getEnable()) {
|
||||||
|
throw (new CustomerNotConfirmedException())->setUser($user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ class AdminResources
|
|||||||
|
|
||||||
const ORDER = "admin.order";
|
const ORDER = "admin.order";
|
||||||
|
|
||||||
|
const ORDER_STATUS = "admin.configuration.order-status";
|
||||||
|
|
||||||
const PRODUCT = "admin.product";
|
const PRODUCT = "admin.product";
|
||||||
|
|
||||||
const PROFILE = "admin.configuration.profile";
|
const PROFILE = "admin.configuration.profile";
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class CSVSerializer extends AbstractSerializer
|
|||||||
if ($this->headers !== null) {
|
if ($this->headers !== null) {
|
||||||
// Create tmp file with header
|
// Create tmp file with header
|
||||||
$fd = fopen('php://temp', 'w+b');
|
$fd = fopen('php://temp', 'w+b');
|
||||||
fputcsv($fd, $this->headers);
|
fputcsv($fd, $this->headers, $this->delimiter, $this->enclosure);
|
||||||
|
|
||||||
// Copy file content into tmp file
|
// Copy file content into tmp file
|
||||||
$fileObject->rewind();
|
$fileObject->rewind();
|
||||||
@@ -131,6 +131,8 @@ class CSVSerializer extends AbstractSerializer
|
|||||||
|
|
||||||
// Remove last line feed
|
// Remove last line feed
|
||||||
$fileObject->ftruncate($fileObject->getSize() - 1);
|
$fileObject->ftruncate($fileObject->getSize() - 1);
|
||||||
|
|
||||||
|
clearstatcache(true, $fileObject->getPathname());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unserialize(\SplFileObject $fileObject)
|
public function unserialize(\SplFileObject $fileObject)
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ class ParamInitMiddleware implements HttpKernelInterface
|
|||||||
Tlog::getInstance()->warning("The domain URL for language ".$lang->getTitle()." (id ".$lang->getId().") is not defined.");
|
Tlog::getInstance()->warning("The domain URL for language ".$lang->getTitle()." (id ".$lang->getId().") is not defined.");
|
||||||
|
|
||||||
return Lang::getDefaultLanguage();
|
return Lang::getDefaultLanguage();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// one domain for all languages, the lang has to be set into session
|
// one domain for all languages, the lang has to be set into session
|
||||||
return $lang;
|
return $lang;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace Thelia\Core\Template\Element;
|
namespace Thelia\Core\Template\Element;
|
||||||
|
|
||||||
|
use Propel\Runtime\ActiveQuery\Criteria;
|
||||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||||
use Thelia\Model\Tools\ModelCriteriaTools;
|
use Thelia\Model\Tools\ModelCriteriaTools;
|
||||||
@@ -54,8 +55,13 @@ abstract class BaseI18nLoop extends BaseLoop
|
|||||||
*
|
*
|
||||||
* @return mixed the locale
|
* @return mixed the locale
|
||||||
*/
|
*/
|
||||||
protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false)
|
protected function configureI18nProcessing(
|
||||||
{
|
ModelCriteria $search,
|
||||||
|
$columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
|
||||||
|
$foreignTable = null,
|
||||||
|
$foreignKey = 'ID',
|
||||||
|
$forceReturn = false
|
||||||
|
) {
|
||||||
/* manage translations */
|
/* manage translations */
|
||||||
|
|
||||||
$this->locale = ModelCriteriaTools::getI18n(
|
$this->locale = ModelCriteriaTools::getI18n(
|
||||||
@@ -69,4 +75,34 @@ abstract class BaseI18nLoop extends BaseLoop
|
|||||||
$this->getForceReturn()
|
$this->getForceReturn()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the search clause for an I18N column, taking care of the back/front context, as default_locale_i18n is
|
||||||
|
* not defined in the backEnd I18N context.
|
||||||
|
*
|
||||||
|
* @param ModelCriteria $search
|
||||||
|
* @param string $columnName the column to search into, such as TITLE
|
||||||
|
* @param string $searchCriteria the search criteria, such as Criterial::LIKE, Criteria::EQUAL, etc.
|
||||||
|
* @param string $searchTerm the searched term
|
||||||
|
*/
|
||||||
|
public function addSearchInI18nColumn($search, $columnName, $searchCriteria, $searchTerm)
|
||||||
|
{
|
||||||
|
if (! $this->getBackendContext()) {
|
||||||
|
$search->where(
|
||||||
|
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
||||||
|
THEN `requested_locale_i18n`.`$columnName`
|
||||||
|
ELSE `default_locale_i18n`.`$columnName`
|
||||||
|
END " . $searchCriteria . " ?",
|
||||||
|
$searchTerm,
|
||||||
|
\PDO::PARAM_STR
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$search->where(
|
||||||
|
"`requested_locale_i18n`.`$columnName` $searchCriteria ?",
|
||||||
|
$searchTerm,
|
||||||
|
\PDO::PARAM_STR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
core/lib/Thelia/Core/Template/Element/BaseLoop.php
Normal file → Executable file
22
core/lib/Thelia/Core/Template/Element/BaseLoop.php
Normal file → Executable file
@@ -86,6 +86,7 @@ abstract class BaseLoop
|
|||||||
protected $translator = null;
|
protected $translator = null;
|
||||||
|
|
||||||
private static $cacheLoopResult = [];
|
private static $cacheLoopResult = [];
|
||||||
|
private static $cacheLoopPagination = [];
|
||||||
private static $cacheCount = [];
|
private static $cacheCount = [];
|
||||||
|
|
||||||
/** @var array cache of event to dispatch */
|
/** @var array cache of event to dispatch */
|
||||||
@@ -498,6 +499,10 @@ abstract class BaseLoop
|
|||||||
$hash = $this->args->getHash();
|
$hash = $this->args->getHash();
|
||||||
|
|
||||||
if (($isCaching = $this->isCaching()) && isset(self::$cacheLoopResult[$hash])) {
|
if (($isCaching = $this->isCaching()) && isset(self::$cacheLoopResult[$hash])) {
|
||||||
|
if (isset(self::$cacheLoopPagination[$hash])) {
|
||||||
|
$pagination = self::$cacheLoopPagination[$hash];
|
||||||
|
}
|
||||||
|
|
||||||
return self::$cacheLoopResult[$hash];
|
return self::$cacheLoopResult[$hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,9 +538,15 @@ abstract class BaseLoop
|
|||||||
}
|
}
|
||||||
|
|
||||||
$parsedResults = $this->extendsParseResults($this->parseResults($loopResult));
|
$parsedResults = $this->extendsParseResults($this->parseResults($loopResult));
|
||||||
|
|
||||||
|
$loopResult->finalizeRows();
|
||||||
|
|
||||||
if ($isCaching) {
|
if ($isCaching) {
|
||||||
self::$cacheLoopResult[$hash] = $parsedResults;
|
self::$cacheLoopResult[$hash] = $parsedResults;
|
||||||
|
|
||||||
|
if ($pagination instanceof PropelModelPager) {
|
||||||
|
self::$cacheLoopPagination[$hash] = clone $pagination;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $parsedResults;
|
return $parsedResults;
|
||||||
@@ -708,10 +719,11 @@ abstract class BaseLoop
|
|||||||
|
|
||||||
$eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_BUILD_ARRAY);
|
$eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_BUILD_ARRAY);
|
||||||
if (null !== $eventName) {
|
if (null !== $eventName) {
|
||||||
$this->dispatcher->dispatch(
|
$event = new LoopExtendsBuildArrayEvent($this, $search);
|
||||||
$eventName,
|
|
||||||
new LoopExtendsBuildArrayEvent($this, $search)
|
$this->dispatcher->dispatch($eventName, $event);
|
||||||
);
|
|
||||||
|
$search = $event->getArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $search;
|
return $search;
|
||||||
|
|||||||
@@ -80,6 +80,20 @@ class LoopResult implements \Iterator, \JsonSerializable
|
|||||||
|
|
||||||
$this->collection[] = $row;
|
$this->collection[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the collection once all results have been added.
|
||||||
|
*/
|
||||||
|
public function finalizeRows()
|
||||||
|
{
|
||||||
|
// Fix rows LOOP_TOTAL if parseResults() did not added all resultsCollection items to the collection array
|
||||||
|
// see https://github.com/thelia/thelia/issues/2337
|
||||||
|
if (true === $this->countable && $this->getResultDataCollectionCount() !== $realCount = $this->getCount()) {
|
||||||
|
foreach ($this->collection as &$item) {
|
||||||
|
$item->set('LOOP_TOTAL', $realCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getCount()
|
public function getCount()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
namespace Thelia\Core\Template\Element;
|
namespace Thelia\Core\Template\Element;
|
||||||
|
|
||||||
|
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||||
@@ -28,5 +30,11 @@ interface SearchLoopInterface
|
|||||||
*/
|
*/
|
||||||
public function getSearchIn();
|
public function getSearchIn();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ModelCriteria $search a query
|
||||||
|
* @param string $searchTerm the searched term
|
||||||
|
* @param array $searchIn available field to search in
|
||||||
|
* @param string $searchCriteria the search criteria, such as Criterial::LIKE, Criteria::EQUAL, etc.
|
||||||
|
*/
|
||||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria);
|
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,13 +143,12 @@ class Argument
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is available from Thelia 2.2 version
|
|
||||||
*
|
|
||||||
* @param $name
|
* @param $name
|
||||||
* @param null $default
|
* @param null $default
|
||||||
* @param bool $mandatory
|
* @param bool $mandatory
|
||||||
* @param bool $empty
|
* @param bool $empty
|
||||||
* @return Argument
|
* @return Argument
|
||||||
|
* @since 2.2
|
||||||
*/
|
*/
|
||||||
public static function createAnyListTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
public static function createAnyListTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||||
{
|
{
|
||||||
@@ -176,4 +175,46 @@ class Argument
|
|||||||
$empty
|
$empty
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
* @param null $default
|
||||||
|
* @param bool $mandatory
|
||||||
|
* @param bool $empty
|
||||||
|
* @return Argument
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
public static function createAlphaNumStringTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||||
|
{
|
||||||
|
return new Argument(
|
||||||
|
$name,
|
||||||
|
new TypeCollection(
|
||||||
|
new Type\AlphaNumStringType()
|
||||||
|
),
|
||||||
|
$default,
|
||||||
|
$mandatory,
|
||||||
|
$empty
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
* @param null $default
|
||||||
|
* @param bool $mandatory
|
||||||
|
* @param bool $empty
|
||||||
|
* @return Argument
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
public static function createAlphaNumStringListTypeArgument($name, $default = null, $mandatory = false, $empty = true)
|
||||||
|
{
|
||||||
|
return new Argument(
|
||||||
|
$name,
|
||||||
|
new TypeCollection(
|
||||||
|
new Type\AlphaNumStringListType()
|
||||||
|
),
|
||||||
|
$default,
|
||||||
|
$mandatory,
|
||||||
|
$empty
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
|||||||
use Thelia\Core\Template\Element\LoopResultRow;
|
use Thelia\Core\Template\Element\LoopResultRow;
|
||||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||||
|
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||||
use Thelia\Model\BrandQuery;
|
use Thelia\Model\BrandQuery;
|
||||||
@@ -46,6 +47,8 @@ use Thelia\Type\TypeCollection;
|
|||||||
*/
|
*/
|
||||||
class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||||
{
|
{
|
||||||
|
use StandardI18nFieldsSearchTrait;
|
||||||
|
|
||||||
protected $timestampable = true;
|
protected $timestampable = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,28 +93,20 @@ class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoo
|
|||||||
*/
|
*/
|
||||||
public function getSearchIn()
|
public function getSearchIn()
|
||||||
{
|
{
|
||||||
return [
|
return $this->getStandardI18nSearchFields();
|
||||||
"title"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BrandQuery $search
|
* @param BrandQuery $search
|
||||||
* @param string $searchTerm
|
* @param string $searchTerm
|
||||||
* @param string $searchIn
|
* @param array $searchIn
|
||||||
* @param string $searchCriteria
|
* @param string $searchCriteria
|
||||||
*/
|
*/
|
||||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||||
{
|
{
|
||||||
$search->_and();
|
$search->_and();
|
||||||
|
|
||||||
$search->where(
|
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
|
||||||
THEN `requested_locale_i18n`.`TITLE`ELSE `default_locale_i18n`.`TITLE`
|
|
||||||
END ".$searchCriteria." ?",
|
|
||||||
$searchTerm,
|
|
||||||
\PDO::PARAM_STR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildModelCriteria()
|
public function buildModelCriteria()
|
||||||
@@ -153,14 +148,7 @@ class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoo
|
|||||||
$title = $this->getTitle();
|
$title = $this->getTitle();
|
||||||
|
|
||||||
if (!is_null($title)) {
|
if (!is_null($title)) {
|
||||||
$search->where(
|
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID)
|
|
||||||
THEN `requested_locale_i18n`.`TITLE`
|
|
||||||
ELSE `default_locale_i18n`.`TITLE`
|
|
||||||
END ".Criteria::LIKE." ?",
|
|
||||||
"%".$title."%",
|
|
||||||
\PDO::PARAM_STR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$current = $this->getCurrent();
|
$current = $this->getCurrent();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
|||||||
use Thelia\Core\Template\Element\LoopResultRow;
|
use Thelia\Core\Template\Element\LoopResultRow;
|
||||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||||
|
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||||
use Thelia\Model\CategoryQuery;
|
use Thelia\Model\CategoryQuery;
|
||||||
@@ -59,9 +60,13 @@ use Thelia\Model\Category as CategoryModel;
|
|||||||
* @method bool|string getVisible()
|
* @method bool|string getVisible()
|
||||||
* @method int[] getExclude()
|
* @method int[] getExclude()
|
||||||
* @method string[] getOrder()
|
* @method string[] getOrder()
|
||||||
|
* @method int[] getTemplateId()
|
||||||
|
* @method bool getProductCountVisibleOnly()
|
||||||
*/
|
*/
|
||||||
class Category extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
class Category extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||||
{
|
{
|
||||||
|
use StandardI18nFieldsSearchTrait;
|
||||||
|
|
||||||
protected $timestampable = true;
|
protected $timestampable = true;
|
||||||
protected $versionable = true;
|
protected $versionable = true;
|
||||||
|
|
||||||
@@ -82,11 +87,21 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
Argument::createBooleanTypeArgument('with_prev_next_info', false),
|
Argument::createBooleanTypeArgument('with_prev_next_info', false),
|
||||||
Argument::createBooleanTypeArgument('need_count_child', false),
|
Argument::createBooleanTypeArgument('need_count_child', false),
|
||||||
Argument::createBooleanTypeArgument('need_product_count', false),
|
Argument::createBooleanTypeArgument('need_product_count', false),
|
||||||
|
Argument::createBooleanTypeArgument('product_count_visible_only', false),
|
||||||
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
||||||
|
Argument::createIntListTypeArgument('template_id'),
|
||||||
new Argument(
|
new Argument(
|
||||||
'order',
|
'order',
|
||||||
new TypeCollection(
|
new TypeCollection(
|
||||||
new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'visible', 'visible_reverse', 'random'))
|
new Type\EnumListType([
|
||||||
|
'id', 'id_reverse',
|
||||||
|
'alpha', 'alpha_reverse',
|
||||||
|
'manual', 'manual_reverse',
|
||||||
|
'visible', 'visible_reverse',
|
||||||
|
'created', 'created_reverse',
|
||||||
|
'updated', 'updated_reverse',
|
||||||
|
'random'
|
||||||
|
])
|
||||||
),
|
),
|
||||||
'manual'
|
'manual'
|
||||||
),
|
),
|
||||||
@@ -99,22 +114,20 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
*/
|
*/
|
||||||
public function getSearchIn()
|
public function getSearchIn()
|
||||||
{
|
{
|
||||||
return [
|
return $this->getStandardI18nSearchFields();
|
||||||
"title"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CategoryQuery $search
|
* @param CategoryQuery $search
|
||||||
* @param string $searchTerm
|
* @param string $searchTerm
|
||||||
* @param string $searchIn
|
* @param array $searchIn
|
||||||
* @param string $searchCriteria
|
* @param string $searchCriteria
|
||||||
*/
|
*/
|
||||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||||
{
|
{
|
||||||
$search->_and();
|
$search->_and();
|
||||||
|
|
||||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR);
|
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildModelCriteria()
|
public function buildModelCriteria()
|
||||||
@@ -132,8 +145,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
|
|
||||||
$parent = $this->getParent();
|
$parent = $this->getParent();
|
||||||
|
|
||||||
if (!is_null($parent)) {
|
if (null !== $parent) {
|
||||||
$search->filterByParent($parent, Criteria::IN);
|
$search->filterByParent($parent, Criteria::IN);
|
||||||
|
$positionOrderAllowed = true;
|
||||||
|
} else {
|
||||||
|
$positionOrderAllowed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$excludeParent = $this->getExcludeParent();
|
$excludeParent = $this->getExcludeParent();
|
||||||
@@ -190,6 +206,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
->endUse()
|
->endUse()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
$templateIdList = $this->getTemplateId();
|
||||||
|
|
||||||
|
if (!is_null($templateIdList)) {
|
||||||
|
$search->filterByDefaultTemplateId($templateIdList, Criteria::IN);
|
||||||
|
}
|
||||||
|
|
||||||
$orders = $this->getOrder();
|
$orders = $this->getOrder();
|
||||||
|
|
||||||
@@ -219,6 +240,18 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
case "visible_reverse":
|
case "visible_reverse":
|
||||||
$search->orderByVisible(Criteria::DESC);
|
$search->orderByVisible(Criteria::DESC);
|
||||||
break;
|
break;
|
||||||
|
case "created":
|
||||||
|
$search->addAscendingOrderByColumn('created_at');
|
||||||
|
break;
|
||||||
|
case "created_reverse":
|
||||||
|
$search->addDescendingOrderByColumn('created_at');
|
||||||
|
break;
|
||||||
|
case "updated":
|
||||||
|
$search->addAscendingOrderByColumn('updated_at');
|
||||||
|
break;
|
||||||
|
case "updated_reverse":
|
||||||
|
$search->addDescendingOrderByColumn('updated_at');
|
||||||
|
break;
|
||||||
case "random":
|
case "random":
|
||||||
$search->clearOrderByColumns();
|
$search->clearOrderByColumns();
|
||||||
$search->addAscendingOrderByColumn('RAND()');
|
$search->addAscendingOrderByColumn('RAND()');
|
||||||
@@ -264,7 +297,11 @@ class Category extends BaseI18nLoop implements PropelSearchLoopInterface, Search
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getNeedProductCount()) {
|
if ($this->getNeedProductCount()) {
|
||||||
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProducts());
|
if ($this->getProductCountVisibleOnly()) {
|
||||||
|
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProductsVisibleOnly());
|
||||||
|
} else {
|
||||||
|
$loopResultRow->set("PRODUCT_COUNT", $category->countAllProducts());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$isBackendContext = $this->getBackendContext();
|
$isBackendContext = $this->getBackendContext();
|
||||||
|
|||||||
@@ -49,32 +49,34 @@ class CategoryPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
|||||||
{
|
{
|
||||||
return new ArgumentCollection(
|
return new ArgumentCollection(
|
||||||
Argument::createIntTypeArgument('category', null, true),
|
Argument::createIntTypeArgument('category', null, true),
|
||||||
Argument::createIntTypeArgument('depth'),
|
Argument::createIntTypeArgument('depth', PHP_INT_MAX),
|
||||||
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildArray()
|
public function buildArray()
|
||||||
{
|
{
|
||||||
$id = $this->getCategory();
|
$originalId = $currentId = $this->getCategory();
|
||||||
$visible = $this->getVisible();
|
$visible = $this->getVisible();
|
||||||
|
$depth = $this->getDepth();
|
||||||
$search = CategoryQuery::create();
|
|
||||||
|
|
||||||
$this->configureI18nProcessing($search, array('TITLE'));
|
|
||||||
|
|
||||||
$search->filterById($id);
|
|
||||||
if ($visible !== BooleanOrBothType::ANY) {
|
|
||||||
$search->filterByVisible($visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
|
|
||||||
$ids = array();
|
$ids = array();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
$search = CategoryQuery::create();
|
||||||
|
|
||||||
|
$this->configureI18nProcessing($search, array('TITLE'));
|
||||||
|
|
||||||
|
$search->filterById($currentId);
|
||||||
|
|
||||||
|
if ($visible !== BooleanOrBothType::ANY) {
|
||||||
|
$search->filterByVisible($visible);
|
||||||
|
}
|
||||||
|
|
||||||
$category = $search->findOne();
|
$category = $search->findOne();
|
||||||
|
|
||||||
if ($category != null) {
|
if ($category != null) {
|
||||||
$results[] = array(
|
$results[] = array(
|
||||||
"ID" => $category->getId(),
|
"ID" => $category->getId(),
|
||||||
@@ -82,29 +84,26 @@ class CategoryPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
|||||||
"URL" => $category->getUrl($this->locale),
|
"URL" => $category->getUrl($this->locale),
|
||||||
"LOCALE" => $this->locale,
|
"LOCALE" => $this->locale,
|
||||||
);
|
);
|
||||||
|
|
||||||
$parent = $category->getParent();
|
$currentId = $category->getParent();
|
||||||
|
|
||||||
if ($parent > 0) {
|
if ($currentId > 0) {
|
||||||
// Prevent circular refererences
|
// Prevent circular refererences
|
||||||
if (in_array($parent, $ids)) {
|
if (in_array($currentId, $ids)) {
|
||||||
throw new \LogicException(sprintf("Circular reference detected in category ID=%d hierarchy (category ID=%d appears more than one times in path)", $id, $parent));
|
throw new \LogicException(
|
||||||
}
|
sprintf(
|
||||||
|
"Circular reference detected in category ID=%d hierarchy (category ID=%d appears more than one times in path)",
|
||||||
$ids[] = $parent;
|
$originalId,
|
||||||
|
$currentId
|
||||||
$search = CategoryQuery::create();
|
)
|
||||||
|
);
|
||||||
$this->configureI18nProcessing($search, array('TITLE'));
|
|
||||||
|
|
||||||
$search->filterById($parent);
|
|
||||||
if ($visible != BooleanOrBothType::ANY) {
|
|
||||||
$search->filterByVisible($visible);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ids[] = $currentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($category != null && $parent > 0);
|
} while ($category != null && $currentId > 0 && --$depth > 0);
|
||||||
|
|
||||||
// Reverse list and build the final result
|
// Reverse list and build the final result
|
||||||
return array_reverse($results);
|
return array_reverse($results);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
|||||||
use Thelia\Core\Template\Element\LoopResultRow;
|
use Thelia\Core\Template\Element\LoopResultRow;
|
||||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||||
|
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||||
use Thelia\Model\ContentFolderQuery;
|
use Thelia\Model\ContentFolderQuery;
|
||||||
@@ -54,6 +55,8 @@ use Thelia\Type\BooleanOrBothType;
|
|||||||
*/
|
*/
|
||||||
class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||||
{
|
{
|
||||||
|
use StandardI18nFieldsSearchTrait;
|
||||||
|
|
||||||
protected $timestampable = true;
|
protected $timestampable = true;
|
||||||
protected $versionable = true;
|
protected $versionable = true;
|
||||||
|
|
||||||
@@ -77,18 +80,15 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
new TypeCollection(
|
new TypeCollection(
|
||||||
new Type\EnumListType(
|
new Type\EnumListType(
|
||||||
array(
|
array(
|
||||||
'alpha',
|
'id', 'id_reverse',
|
||||||
'alpha-reverse',
|
'alpha', 'alpha-reverse', 'alpha_reverse',
|
||||||
'manual',
|
'manual', 'manual_reverse',
|
||||||
'manual_reverse',
|
'visible', 'visible_reverse',
|
||||||
'random',
|
'random',
|
||||||
'given_id',
|
'given_id',
|
||||||
'created',
|
'created', 'created_reverse',
|
||||||
'created_reverse',
|
'updated', 'updated_reverse',
|
||||||
'updated',
|
'position', 'position_reverse'
|
||||||
'updated_reverse',
|
|
||||||
'position',
|
|
||||||
'position_reverse'
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -104,22 +104,20 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
*/
|
*/
|
||||||
public function getSearchIn()
|
public function getSearchIn()
|
||||||
{
|
{
|
||||||
return [
|
return $this->getStandardI18nSearchFields();
|
||||||
"title"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ContentQuery $search
|
* @param ContentQuery $search
|
||||||
* @param string $searchTerm
|
* @param string $searchTerm
|
||||||
* @param string $searchIn
|
* @param array $searchIn
|
||||||
* @param string $searchCriteria
|
* @param string $searchCriteria
|
||||||
*/
|
*/
|
||||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||||
{
|
{
|
||||||
$search->_and();
|
$search->_and();
|
||||||
|
|
||||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR);
|
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildModelCriteria()
|
public function buildModelCriteria()
|
||||||
@@ -140,8 +138,8 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
// Select the contents which have $folderDefault as the default folder.
|
// Select the contents which have $folderDefault as the default folder.
|
||||||
$search
|
$search
|
||||||
->useContentFolderQuery('FolderSelect')
|
->useContentFolderQuery('FolderSelect')
|
||||||
->filterByDefaultFolder(true)
|
->filterByDefaultFolder(true)
|
||||||
->filterByFolderId($folderDefault, Criteria::IN)
|
->filterByFolderId($folderDefault, Criteria::IN)
|
||||||
->endUse()
|
->endUse()
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -155,7 +153,7 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
|
|
||||||
$search
|
$search
|
||||||
->useContentFolderQuery('FolderSelect')
|
->useContentFolderQuery('FolderSelect')
|
||||||
->filterByFolderId($allFolderIDs, Criteria::IN)
|
->filterByFolderId($allFolderIDs, Criteria::IN)
|
||||||
->endUse()
|
->endUse()
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -163,12 +161,18 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
$manualOrderAllowed = (1 == $depth && 1 == count($folderIdList));
|
$manualOrderAllowed = (1 == $depth && 1 == count($folderIdList));
|
||||||
} else {
|
} else {
|
||||||
$search
|
$search
|
||||||
->useContentFolderQuery('FolderSelect')
|
->leftJoinContentFolder('FolderSelect')
|
||||||
->filterByDefaultFolder(true)
|
->addJoinCondition('FolderSelect', '`FolderSelect`.DEFAULT_FOLDER = 1')
|
||||||
->endUse()
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$search->withColumn(
|
||||||
|
'CAST(CASE WHEN ISNULL(`FolderSelect`.POSITION) THEN \'' . PHP_INT_MAX . '\' ELSE `FolderSelect`.POSITION END AS SIGNED)',
|
||||||
|
'position_delegate'
|
||||||
|
);
|
||||||
|
$search->withColumn('`FolderSelect`.FOLDER_ID', 'default_folder_id');
|
||||||
|
$search->withColumn('`FolderSelect`.DEFAULT_FOLDER', 'is_default_folder');
|
||||||
|
|
||||||
$current = $this->getCurrent();
|
$current = $this->getCurrent();
|
||||||
|
|
||||||
if ($current === true) {
|
if ($current === true) {
|
||||||
@@ -198,19 +202,39 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
$title = $this->getTitle();
|
$title = $this->getTitle();
|
||||||
|
|
||||||
if (!is_null($title)) {
|
if (!is_null($title)) {
|
||||||
$search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".Criteria::LIKE." ?", "%".$title."%", \PDO::PARAM_STR);
|
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||||
}
|
}
|
||||||
|
|
||||||
$search->withColumn('`FolderSelect`.POSITION', 'position_delegate');
|
$exclude = $this->getExclude();
|
||||||
|
|
||||||
|
if (!is_null($exclude)) {
|
||||||
|
$search->filterById($exclude, Criteria::NOT_IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
$exclude_folder = $this->getExcludeFolder();
|
||||||
|
|
||||||
|
if (!is_null($exclude_folder)) {
|
||||||
|
$search->filterByFolder(
|
||||||
|
FolderQuery::create()->filterById($exclude_folder, Criteria::IN)->find(),
|
||||||
|
Criteria::NOT_IN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$orders = $this->getOrder();
|
$orders = $this->getOrder();
|
||||||
|
|
||||||
foreach ($orders as $order) {
|
foreach ($orders as $order) {
|
||||||
switch ($order) {
|
switch ($order) {
|
||||||
|
case "id":
|
||||||
|
$search->orderById(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "id_reverse":
|
||||||
|
$search->orderById(Criteria::DESC);
|
||||||
|
break;
|
||||||
case "alpha":
|
case "alpha":
|
||||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||||
break;
|
break;
|
||||||
case "alpha-reverse":
|
case "alpha-reverse":
|
||||||
|
case "alpha_reverse":
|
||||||
$search->addDescendingOrderByColumn('i18n_TITLE');
|
$search->addDescendingOrderByColumn('i18n_TITLE');
|
||||||
break;
|
break;
|
||||||
case "manual":
|
case "manual":
|
||||||
@@ -235,6 +259,12 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
$search->orderBy($givenIdMatched, Criteria::DESC);
|
$search->orderBy($givenIdMatched, Criteria::DESC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "visible":
|
||||||
|
$search->orderByVisible(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "visible_reverse":
|
||||||
|
$search->orderByVisible(Criteria::DESC);
|
||||||
|
break;
|
||||||
case "random":
|
case "random":
|
||||||
$search->clearOrderByColumns();
|
$search->clearOrderByColumns();
|
||||||
$search->addAscendingOrderByColumn('RAND()');
|
$search->addAscendingOrderByColumn('RAND()');
|
||||||
@@ -260,20 +290,7 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$exclude = $this->getExclude();
|
$search->groupById();
|
||||||
|
|
||||||
if (!is_null($exclude)) {
|
|
||||||
$search->filterById($exclude, Criteria::NOT_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
$exclude_folder = $this->getExcludeFolder();
|
|
||||||
|
|
||||||
if (!is_null($exclude_folder)) {
|
|
||||||
$search->filterByFolder(
|
|
||||||
FolderQuery::create()->filterById($exclude_folder, Criteria::IN)->find(),
|
|
||||||
Criteria::NOT_IN
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $search;
|
return $search;
|
||||||
}
|
}
|
||||||
@@ -283,7 +300,13 @@ class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchL
|
|||||||
/** @var ContentModel $content */
|
/** @var ContentModel $content */
|
||||||
foreach ($loopResult->getResultDataCollection() as $content) {
|
foreach ($loopResult->getResultDataCollection() as $content) {
|
||||||
$loopResultRow = new LoopResultRow($content);
|
$loopResultRow = new LoopResultRow($content);
|
||||||
$defaultFolderId = $content->getDefaultFolderId();
|
|
||||||
|
if ((bool) $content->getVirtualColumn('is_default_folder')) {
|
||||||
|
$defaultFolderId = $content->getVirtualColumn('default_folder_id');
|
||||||
|
} else {
|
||||||
|
$defaultFolderId = $content->getDefaultFolderId();
|
||||||
|
}
|
||||||
|
|
||||||
$loopResultRow->set("ID", $content->getId())
|
$loopResultRow->set("ID", $content->getId())
|
||||||
->set("IS_TRANSLATED", $content->getVirtualColumn('IS_TRANSLATED'))
|
->set("IS_TRANSLATED", $content->getVirtualColumn('IS_TRANSLATED'))
|
||||||
->set("LOCALE", $this->locale)
|
->set("LOCALE", $this->locale)
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class Country extends BaseI18nLoop implements PropelSearchLoopInterface
|
|||||||
|
|
||||||
if (true === $withArea) {
|
if (true === $withArea) {
|
||||||
$search
|
$search
|
||||||
|
->distinct()
|
||||||
->joinCountryArea('with_area', Criteria::LEFT_JOIN)
|
->joinCountryArea('with_area', Criteria::LEFT_JOIN)
|
||||||
->where('`with_area`.country_id ' . Criteria::ISNOTNULL);
|
->where('`with_area`.country_id ' . Criteria::ISNOTNULL);
|
||||||
} elseif (false === $withArea) {
|
} elseif (false === $withArea) {
|
||||||
|
|||||||
@@ -252,7 +252,9 @@ class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoop
|
|||||||
->set("RESELLER", $customer->getReseller())
|
->set("RESELLER", $customer->getReseller())
|
||||||
->set("SPONSOR", $customer->getSponsor())
|
->set("SPONSOR", $customer->getSponsor())
|
||||||
->set("DISCOUNT", $customer->getDiscount())
|
->set("DISCOUNT", $customer->getDiscount())
|
||||||
->set("NEWSLETTER", $customer->getVirtualColumn("is_registered_to_newsletter"));
|
->set("NEWSLETTER", $customer->getVirtualColumn("is_registered_to_newsletter"))
|
||||||
|
->set("CONFIRMATION_TOKEN", $customer->getConfirmationToken())
|
||||||
|
;
|
||||||
|
|
||||||
if ($this->getWithPrevNextInfo()) {
|
if ($this->getWithPrevNextInfo()) {
|
||||||
// Find previous and next category
|
// Find previous and next category
|
||||||
|
|||||||
@@ -123,6 +123,13 @@ class Feature extends BaseI18nLoop implements PropelSearchLoopInterface
|
|||||||
|
|
||||||
/** @var ProductModel $product */
|
/** @var ProductModel $product */
|
||||||
foreach ($products as $product) {
|
foreach ($products as $product) {
|
||||||
|
if (!$this->getBackendContext()) {
|
||||||
|
$search
|
||||||
|
->useFeatureProductQuery()
|
||||||
|
->filterByProduct($product)
|
||||||
|
->endUse()
|
||||||
|
;
|
||||||
|
}
|
||||||
$tplId = $product->getTemplateId();
|
$tplId = $product->getTemplateId();
|
||||||
|
|
||||||
if (! is_null($tplId)) {
|
if (! is_null($tplId)) {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ use Thelia\Core\Template\Loop\Argument\Argument;
|
|||||||
use Thelia\Model\FeatureAv;
|
use Thelia\Model\FeatureAv;
|
||||||
use Thelia\Model\FeatureAvQuery;
|
use Thelia\Model\FeatureAvQuery;
|
||||||
use Thelia\Model\FeatureProductQuery;
|
use Thelia\Model\FeatureProductQuery;
|
||||||
|
use Thelia\Model\Map\FeatureAvTableMap;
|
||||||
|
use Thelia\Model\Map\FeatureProductTableMap;
|
||||||
use Thelia\Type\TypeCollection;
|
use Thelia\Type\TypeCollection;
|
||||||
use Thelia\Type;
|
use Thelia\Type;
|
||||||
|
|
||||||
@@ -106,6 +108,24 @@ class FeatureAvailability extends BaseI18nLoop implements PropelSearchLoopInterf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do not consider here Free Text values, so be sure that the features values we will get
|
||||||
|
// are not free text ones, e.g. are not defined as free-text feature values in the
|
||||||
|
// feature_product table.
|
||||||
|
// We are doig here something like
|
||||||
|
// SELECT * FROM `feature_av`
|
||||||
|
// WHERE feature_av.FEATURE_ID IN ('7')
|
||||||
|
// AND feature_av.ID not in (
|
||||||
|
// select feature_av_id from feature_product
|
||||||
|
// where feature_id = `feature_av`.feature_id
|
||||||
|
// and feature_av_id = `feature_av`.id
|
||||||
|
// and free_text_value = 1
|
||||||
|
// )
|
||||||
|
$search->where(FeatureAvTableMap::ID . ' NOT IN (
|
||||||
|
SELECT '. FeatureProductTableMap::FEATURE_AV_ID . '
|
||||||
|
FROM ' .FeatureProductTableMap::TABLE_NAME. '
|
||||||
|
WHERE ' . FeatureProductTableMap::FREE_TEXT_VALUE . ' = 1
|
||||||
|
)');
|
||||||
|
|
||||||
return $search;
|
return $search;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,26 +133,19 @@ class FeatureAvailability extends BaseI18nLoop implements PropelSearchLoopInterf
|
|||||||
{
|
{
|
||||||
/** @var FeatureAv $featureAv */
|
/** @var FeatureAv $featureAv */
|
||||||
foreach ($loopResult->getResultDataCollection() as $featureAv) {
|
foreach ($loopResult->getResultDataCollection() as $featureAv) {
|
||||||
$isFreeText = FeatureProductQuery::create()
|
$loopResultRow = new LoopResultRow($featureAv);
|
||||||
->filterByFeatureId($featureAv->getFeatureId())
|
$loopResultRow->set("ID", $featureAv->getId())
|
||||||
->filterByFeatureAvId($featureAv->getId())
|
->set("IS_TRANSLATED", $featureAv->getVirtualColumn('IS_TRANSLATED'))
|
||||||
->findOneByFreeTextValue(true);
|
->set("LOCALE", $this->locale)
|
||||||
|
->set("FEATURE_ID", $featureAv->getFeatureId())
|
||||||
|
->set("TITLE", $featureAv->getVirtualColumn('i18n_TITLE'))
|
||||||
|
->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO'))
|
||||||
|
->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION'))
|
||||||
|
->set("POSTSCRIPTUM", $featureAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||||
|
->set("POSITION", $featureAv->getPosition());
|
||||||
|
$this->addOutputFields($loopResultRow, $featureAv);
|
||||||
|
|
||||||
if ($isFreeText === null) {
|
$loopResult->addRow($loopResultRow);
|
||||||
$loopResultRow = new LoopResultRow($featureAv);
|
|
||||||
$loopResultRow->set("ID", $featureAv->getId())
|
|
||||||
->set("IS_TRANSLATED", $featureAv->getVirtualColumn('IS_TRANSLATED'))
|
|
||||||
->set("LOCALE", $this->locale)
|
|
||||||
->set("FEATURE_ID", $featureAv->getFeatureId())
|
|
||||||
->set("TITLE", $featureAv->getVirtualColumn('i18n_TITLE'))
|
|
||||||
->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO'))
|
|
||||||
->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION'))
|
|
||||||
->set("POSTSCRIPTUM", $featureAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
|
||||||
->set("POSITION", $featureAv->getPosition());
|
|
||||||
$this->addOutputFields($loopResultRow, $featureAv);
|
|
||||||
|
|
||||||
$loopResult->addRow($loopResultRow);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $loopResult;
|
return $loopResult;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace Thelia\Core\Template\Loop;
|
namespace Thelia\Core\Template\Loop;
|
||||||
|
|
||||||
|
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||||
use Thelia\Core\Template\Element\ArraySearchLoopInterface;
|
use Thelia\Core\Template\Element\ArraySearchLoopInterface;
|
||||||
use Thelia\Core\Template\Element\BaseLoop;
|
use Thelia\Core\Template\Element\BaseLoop;
|
||||||
use Thelia\Core\Template\Element\LoopResult;
|
use Thelia\Core\Template\Element\LoopResult;
|
||||||
@@ -41,27 +42,25 @@ class Feed extends BaseLoop implements ArraySearchLoopInterface
|
|||||||
|
|
||||||
public function buildArray()
|
public function buildArray()
|
||||||
{
|
{
|
||||||
$cachedir = THELIA_ROOT . 'cache/feeds';
|
/** @var AdapterInterface $cacheAdapter */
|
||||||
|
$cacheAdapter = $this->container->get('thelia.cache');
|
||||||
|
|
||||||
if (! is_dir($cachedir)) {
|
$cacheItem = $cacheAdapter->getItem('feed_' . md5($this->getUrl()));
|
||||||
if (! mkdir($cachedir)) {
|
|
||||||
throw new \Exception(sprintf("Failed to create cache directory '%s'", $cachedir));
|
if (!$cacheItem->isHit()) {
|
||||||
}
|
$feed = new \SimplePie();
|
||||||
|
$feed->set_feed_url($this->getUrl());
|
||||||
|
|
||||||
|
$feed->init();
|
||||||
|
|
||||||
|
$feed->handle_content_type();
|
||||||
|
|
||||||
|
$cacheItem->expiresAfter($this->getTimeout() * 60);
|
||||||
|
$cacheItem->set($feed->get_items());
|
||||||
|
$cacheAdapter->save($cacheItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
$feed = new \SimplePie();
|
return $cacheItem->get();
|
||||||
$feed->set_feed_url($this->getUrl());
|
|
||||||
$feed->set_cache_location(THELIA_ROOT . 'cache/feeds');
|
|
||||||
|
|
||||||
$feed->init();
|
|
||||||
|
|
||||||
$feed->handle_content_type();
|
|
||||||
|
|
||||||
$feed->set_timeout($this->getTimeout());
|
|
||||||
|
|
||||||
$items = $feed->get_items();
|
|
||||||
|
|
||||||
return $items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parseResults(LoopResult $loopResult)
|
public function parseResults(LoopResult $loopResult)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use Thelia\Core\Template\Element\LoopResult;
|
|||||||
use Thelia\Core\Template\Element\LoopResultRow;
|
use Thelia\Core\Template\Element\LoopResultRow;
|
||||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||||
use Thelia\Core\Template\Element\SearchLoopInterface;
|
use Thelia\Core\Template\Element\SearchLoopInterface;
|
||||||
|
use Thelia\Core\Template\Element\StandardI18nFieldsSearchTrait;
|
||||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||||
use Thelia\Model\ContentQuery;
|
use Thelia\Model\ContentQuery;
|
||||||
@@ -42,9 +43,14 @@ use Thelia\Type\BooleanOrBothType;
|
|||||||
* @method string getTitle()
|
* @method string getTitle()
|
||||||
* @method string[] getOrder()
|
* @method string[] getOrder()
|
||||||
* @method bool getWithPrevNextInfo()
|
* @method bool getWithPrevNextInfo()
|
||||||
|
* @method bool getNeedCountChild()
|
||||||
|
* @method bool getNeedContentCount()
|
||||||
|
* @method bool getContentCountVisible()
|
||||||
*/
|
*/
|
||||||
class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface
|
||||||
{
|
{
|
||||||
|
use StandardI18nFieldsSearchTrait;
|
||||||
|
|
||||||
protected $timestampable = true;
|
protected $timestampable = true;
|
||||||
protected $versionable = true;
|
protected $versionable = true;
|
||||||
|
|
||||||
@@ -61,27 +67,28 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
Argument::createBooleanTypeArgument('not_empty', 0),
|
Argument::createBooleanTypeArgument('not_empty', 0),
|
||||||
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
Argument::createBooleanOrBothTypeArgument('visible', 1),
|
||||||
Argument::createAnyTypeArgument('title'),
|
Argument::createAnyTypeArgument('title'),
|
||||||
|
Argument::createBooleanTypeArgument('need_count_child', true),
|
||||||
|
Argument::createBooleanTypeArgument('need_content_count', true),
|
||||||
new Argument(
|
new Argument(
|
||||||
'order',
|
'order',
|
||||||
new TypeCollection(
|
new TypeCollection(
|
||||||
new Type\EnumListType(
|
new Type\EnumListType(
|
||||||
[
|
[
|
||||||
'alpha',
|
'id', 'id_reverse',
|
||||||
'alpha_reverse',
|
'alpha', 'alpha_reverse',
|
||||||
'manual',
|
'manual', 'manual_reverse',
|
||||||
'manual_reverse',
|
'visible', 'visible_reverse',
|
||||||
'random',
|
'random',
|
||||||
'created',
|
'created', 'created_reverse',
|
||||||
'created_reverse',
|
'updated', 'updated_reverse'
|
||||||
'updated',
|
|
||||||
'updated_reverse'
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'manual'
|
'manual'
|
||||||
),
|
),
|
||||||
Argument::createIntListTypeArgument('exclude'),
|
Argument::createIntListTypeArgument('exclude'),
|
||||||
Argument::createBooleanTypeArgument('with_prev_next_info', false)
|
Argument::createBooleanTypeArgument('with_prev_next_info', false),
|
||||||
|
Argument::createBooleanOrBothTypeArgument('content_count_visible', true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,36 +97,20 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
*/
|
*/
|
||||||
public function getSearchIn()
|
public function getSearchIn()
|
||||||
{
|
{
|
||||||
return [
|
return $this->getStandardI18nSearchFields();
|
||||||
"title"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param FolderQuery $search
|
* @param FolderQuery $search
|
||||||
* @param string $searchTerm
|
* @param string $searchTerm
|
||||||
* @param string $searchIn
|
* @param array $searchIn
|
||||||
* @param string $searchCriteria
|
* @param string $searchCriteria
|
||||||
*/
|
*/
|
||||||
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria)
|
||||||
{
|
{
|
||||||
$search->_and();
|
$search->_and();
|
||||||
|
|
||||||
$this->addTitleSearchWhereClause($search, $searchCriteria, $searchTerm);
|
$this->addStandardI18nSearch($search, $searchTerm, $searchCriteria);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FolderQuery $search
|
|
||||||
* @param string $criteria
|
|
||||||
* @param string $value
|
|
||||||
*/
|
|
||||||
protected function addTitleSearchWhereClause($search, $criteria, $value)
|
|
||||||
{
|
|
||||||
$search->where(
|
|
||||||
"CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$criteria." ?",
|
|
||||||
$value,
|
|
||||||
\PDO::PARAM_STR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildModelCriteria()
|
public function buildModelCriteria()
|
||||||
@@ -140,7 +131,7 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
|
|
||||||
$parent = $this->getParent();
|
$parent = $this->getParent();
|
||||||
|
|
||||||
if (!is_null($parent)) {
|
if (null !== $parent) {
|
||||||
$search->filterByParent($parent);
|
$search->filterByParent($parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +162,7 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
$title = $this->getTitle();
|
$title = $this->getTitle();
|
||||||
|
|
||||||
if (!is_null($title)) {
|
if (!is_null($title)) {
|
||||||
$this->addTitleSearchWhereClause($search, Criteria::LIKE, '%'.$title.'%');
|
$this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%");
|
||||||
}
|
}
|
||||||
|
|
||||||
$visible = $this->getVisible();
|
$visible = $this->getVisible();
|
||||||
@@ -184,6 +175,12 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
|
|
||||||
foreach ($orders as $order) {
|
foreach ($orders as $order) {
|
||||||
switch ($order) {
|
switch ($order) {
|
||||||
|
case "id":
|
||||||
|
$search->orderById(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "id_reverse":
|
||||||
|
$search->orderById(Criteria::DESC);
|
||||||
|
break;
|
||||||
case "alpha":
|
case "alpha":
|
||||||
$search->addAscendingOrderByColumn('i18n_TITLE');
|
$search->addAscendingOrderByColumn('i18n_TITLE');
|
||||||
break;
|
break;
|
||||||
@@ -196,6 +193,12 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
case "manual":
|
case "manual":
|
||||||
$search->orderByPosition(Criteria::ASC);
|
$search->orderByPosition(Criteria::ASC);
|
||||||
break;
|
break;
|
||||||
|
case "visible":
|
||||||
|
$search->orderByVisible(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "visible_reverse":
|
||||||
|
$search->orderByVisible(Criteria::DESC);
|
||||||
|
break;
|
||||||
case "random":
|
case "random":
|
||||||
$search->clearOrderByColumns();
|
$search->clearOrderByColumns();
|
||||||
$search->addAscendingOrderByColumn('RAND()');
|
$search->addAscendingOrderByColumn('RAND()');
|
||||||
@@ -221,6 +224,15 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
|
|
||||||
public function parseResults(LoopResult $loopResult)
|
public function parseResults(LoopResult $loopResult)
|
||||||
{
|
{
|
||||||
|
$needCountChild = $this->getNeedCountChild();
|
||||||
|
$needContentCount = $this->getNeedContentCount();
|
||||||
|
|
||||||
|
$contentCountVisiblility = $this->getContentCountVisible();
|
||||||
|
|
||||||
|
if ($contentCountVisiblility !== BooleanOrBothType::ANY) {
|
||||||
|
$contentCountVisiblility = $contentCountVisiblility ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** @var \Thelia\Model\Folder $folder */
|
/** @var \Thelia\Model\Folder $folder */
|
||||||
foreach ($loopResult->getResultDataCollection() as $folder) {
|
foreach ($loopResult->getResultDataCollection() as $folder) {
|
||||||
$loopResultRow = new LoopResultRow($folder);
|
$loopResultRow = new LoopResultRow($folder);
|
||||||
@@ -239,11 +251,18 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
->set("META_TITLE", $folder->getVirtualColumn('i18n_META_TITLE'))
|
->set("META_TITLE", $folder->getVirtualColumn('i18n_META_TITLE'))
|
||||||
->set("META_DESCRIPTION", $folder->getVirtualColumn('i18n_META_DESCRIPTION'))
|
->set("META_DESCRIPTION", $folder->getVirtualColumn('i18n_META_DESCRIPTION'))
|
||||||
->set("META_KEYWORDS", $folder->getVirtualColumn('i18n_META_KEYWORDS'))
|
->set("META_KEYWORDS", $folder->getVirtualColumn('i18n_META_KEYWORDS'))
|
||||||
->set("CHILD_COUNT", $folder->countChild())
|
|
||||||
->set("CONTENT_COUNT", $folder->countAllContents())
|
|
||||||
->set("VISIBLE", $folder->getVisible() ? "1" : "0")
|
->set("VISIBLE", $folder->getVisible() ? "1" : "0")
|
||||||
->set("POSITION", $folder->getPosition());
|
->set("POSITION", $folder->getPosition());
|
||||||
|
|
||||||
|
|
||||||
|
if ($needCountChild) {
|
||||||
|
$loopResultRow->set("CHILD_COUNT", $folder->countChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($needContentCount) {
|
||||||
|
$loopResultRow->set("CONTENT_COUNT", $folder->countAllContents($contentCountVisiblility));
|
||||||
|
}
|
||||||
|
|
||||||
$isBackendContext = $this->getBackendContext();
|
$isBackendContext = $this->getBackendContext();
|
||||||
|
|
||||||
if ($this->getWithPrevNextInfo()) {
|
if ($this->getWithPrevNextInfo()) {
|
||||||
@@ -286,4 +305,4 @@ class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLo
|
|||||||
|
|
||||||
return $loopResult;
|
return $loopResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ use Thelia\Type\BooleanOrBothType;
|
|||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
* @method int getFolder()
|
* @method int getFolder()
|
||||||
* @method bool|string getVisible()
|
* @method bool|string getVisible()
|
||||||
|
* @method int getDepth()
|
||||||
* @method string[] getOrder()
|
* @method string[] getOrder()
|
||||||
*/
|
*/
|
||||||
class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
||||||
@@ -40,30 +41,32 @@ class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
|||||||
{
|
{
|
||||||
return new ArgumentCollection(
|
return new ArgumentCollection(
|
||||||
Argument::createIntTypeArgument('folder', null, true),
|
Argument::createIntTypeArgument('folder', null, true),
|
||||||
Argument::createIntTypeArgument('depth'),
|
Argument::createIntTypeArgument('depth', PHP_INT_MAX),
|
||||||
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
Argument::createBooleanOrBothTypeArgument('visible', true, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildArray()
|
public function buildArray()
|
||||||
{
|
{
|
||||||
$id = $this->getFolder();
|
$originalId = $currentId = $this->getFolder();
|
||||||
$visible = $this->getVisible();
|
$visible = $this->getVisible();
|
||||||
|
$depth = $this->getDepth();
|
||||||
$search = FolderQuery::create();
|
|
||||||
|
|
||||||
$this->configureI18nProcessing($search, array('TITLE'));
|
|
||||||
|
|
||||||
$search->filterById($id);
|
|
||||||
if ($visible !== BooleanOrBothType::ANY) {
|
|
||||||
$search->filterByVisible($visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
|
|
||||||
$ids = array();
|
$ids = array();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
$search = FolderQuery::create();
|
||||||
|
|
||||||
|
$this->configureI18nProcessing($search, array('TITLE'));
|
||||||
|
|
||||||
|
$search->filterById($currentId);
|
||||||
|
|
||||||
|
if ($visible !== BooleanOrBothType::ANY) {
|
||||||
|
$search->filterByVisible($visible);
|
||||||
|
}
|
||||||
|
|
||||||
$folder = $search->findOne();
|
$folder = $search->findOne();
|
||||||
|
|
||||||
if ($folder != null) {
|
if ($folder != null) {
|
||||||
@@ -73,28 +76,25 @@ class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface
|
|||||||
"URL" => $folder->getUrl($this->locale),
|
"URL" => $folder->getUrl($this->locale),
|
||||||
"LOCALE" => $this->locale,
|
"LOCALE" => $this->locale,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$currentId = $folder->getParent();
|
||||||
|
|
||||||
$parent = $folder->getParent();
|
if ($currentId > 0) {
|
||||||
|
|
||||||
if ($parent > 0) {
|
|
||||||
// Prevent circular refererences
|
// Prevent circular refererences
|
||||||
if (in_array($parent, $ids)) {
|
if (in_array($currentId, $ids)) {
|
||||||
throw new \LogicException(sprintf("Circular reference detected in folder ID=%d hierarchy (folder ID=%d appears more than one times in path)", $id, $parent));
|
throw new \LogicException(
|
||||||
|
sprintf(
|
||||||
|
"Circular reference detected in folder ID=%d hierarchy (folder ID=%d appears more than one times in path)",
|
||||||
|
$originalId,
|
||||||
|
$currentId
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ids[] = $parent;
|
$ids[] = $currentId;
|
||||||
|
|
||||||
$search = FolderQuery::create();
|
|
||||||
|
|
||||||
$this->configureI18nProcessing($search, array('TITLE'));
|
|
||||||
|
|
||||||
$search->filterById($parent);
|
|
||||||
if ($visible != BooleanOrBothType::ANY) {
|
|
||||||
$search->filterByVisible($visible);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($folder != null && $parent > 0);
|
} while ($folder != null && $currentId > 0 && --$depth > 0);
|
||||||
|
|
||||||
// Reverse list and build the final result
|
// Reverse list and build the final result
|
||||||
return array_reverse($results);
|
return array_reverse($results);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ use Thelia\Type\TypeCollection;
|
|||||||
* @method int[] getExclude()
|
* @method int[] getExclude()
|
||||||
* @method bool|string getActive()
|
* @method bool|string getActive()
|
||||||
* @method string[] getOrder()
|
* @method string[] getOrder()
|
||||||
|
* @method bool|string getMandatory()
|
||||||
|
* @method bool|string getHidden()
|
||||||
*/
|
*/
|
||||||
class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||||
{
|
{
|
||||||
@@ -87,24 +89,26 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
|||||||
'order',
|
'order',
|
||||||
new TypeCollection(
|
new TypeCollection(
|
||||||
new Type\EnumListType([
|
new Type\EnumListType([
|
||||||
'id',
|
'id',
|
||||||
'id_reverse',
|
'id_reverse',
|
||||||
'code',
|
'code',
|
||||||
'code_reverse',
|
'code_reverse',
|
||||||
'title',
|
'title',
|
||||||
'title_reverse',
|
'title_reverse',
|
||||||
'type',
|
'type',
|
||||||
'type_reverse',
|
'type_reverse',
|
||||||
'manual',
|
'manual',
|
||||||
'manual_reverse',
|
'manual_reverse',
|
||||||
'enabled',
|
'enabled',
|
||||||
'enabled_reverse'
|
'enabled_reverse'
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
'manual'
|
'manual'
|
||||||
),
|
),
|
||||||
Argument::createIntListTypeArgument('exclude'),
|
Argument::createIntListTypeArgument('exclude'),
|
||||||
Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY)
|
Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY),
|
||||||
|
Argument::createBooleanOrBothTypeArgument('hidden', Type\BooleanOrBothType::ANY),
|
||||||
|
Argument::createBooleanOrBothTypeArgument('mandatory', Type\BooleanOrBothType::ANY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +173,18 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
|||||||
$search->filterByActivate($active ? 1 : 0, Criteria::EQUAL);
|
$search->filterByActivate($active ? 1 : 0, Criteria::EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hidden = $this->getHidden();
|
||||||
|
|
||||||
|
if ($hidden !== Type\BooleanOrBothType::ANY) {
|
||||||
|
$search->filterByHidden($hidden ? 1 : 0, Criteria::EQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mandatory = $this->getMandatory();
|
||||||
|
|
||||||
|
if ($mandatory !== Type\BooleanOrBothType::ANY) {
|
||||||
|
$search->filterByMandatory($mandatory ? 1 : 0, Criteria::EQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
$orders = $this->getOrder();
|
$orders = $this->getOrder();
|
||||||
|
|
||||||
foreach ($orders as $order) {
|
foreach ($orders as $order) {
|
||||||
@@ -245,6 +261,8 @@ class Module extends BaseI18nLoop implements PropelSearchLoopInterface
|
|||||||
->set("VERSION", $module->getVersion())
|
->set("VERSION", $module->getVersion())
|
||||||
->set("CLASS", $module->getFullNamespace())
|
->set("CLASS", $module->getFullNamespace())
|
||||||
->set("POSITION", $module->getPosition())
|
->set("POSITION", $module->getPosition())
|
||||||
|
->set("MANDATORY", $module->getMandatory())
|
||||||
|
->set("HIDDEN", $module->getHidden())
|
||||||
->set("EXISTS", $exists);
|
->set("EXISTS", $exists);
|
||||||
|
|
||||||
$hasConfigurationInterface = false;
|
$hasConfigurationInterface = false;
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ class OrderCoupon extends BaseLoop implements PropelSearchLoopInterface
|
|||||||
|
|
||||||
$loopResultRow->set("ID", $orderCoupon->getId())
|
$loopResultRow->set("ID", $orderCoupon->getId())
|
||||||
->set("CODE", $orderCoupon->getCode())
|
->set("CODE", $orderCoupon->getCode())
|
||||||
|
->set("DISCOUNT_AMOUNT", $orderCoupon->getAmount())
|
||||||
->set("TITLE", $orderCoupon->getTitle())
|
->set("TITLE", $orderCoupon->getTitle())
|
||||||
->set("SHORT_DESCRIPTION", $orderCoupon->getShortDescription())
|
->set("SHORT_DESCRIPTION", $orderCoupon->getShortDescription())
|
||||||
->set("DESCRIPTION", $orderCoupon->getDescription())
|
->set("DESCRIPTION", $orderCoupon->getDescription())
|
||||||
@@ -104,6 +105,7 @@ class OrderCoupon extends BaseLoop implements PropelSearchLoopInterface
|
|||||||
->set("FREE_SHIPPING_FOR_COUNTRIES_LIST", implode(',', $freeShippingForCountriesIds))
|
->set("FREE_SHIPPING_FOR_COUNTRIES_LIST", implode(',', $freeShippingForCountriesIds))
|
||||||
->set("FREE_SHIPPING_FOR_MODULES_LIST", implode(',', $freeShippingForModulesIds))
|
->set("FREE_SHIPPING_FOR_MODULES_LIST", implode(',', $freeShippingForModulesIds))
|
||||||
->set("PER_CUSTOMER_USAGE_COUNT", $orderCoupon->getPerCustomerUsageCount())
|
->set("PER_CUSTOMER_USAGE_COUNT", $orderCoupon->getPerCustomerUsageCount())
|
||||||
|
->set("IS_USAGE_CANCELED", $orderCoupon->getUsageCanceled())
|
||||||
;
|
;
|
||||||
$this->addOutputFields($loopResultRow, $orderCoupon);
|
$this->addOutputFields($loopResultRow, $orderCoupon);
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user